From 52eafbd7495367aa48192100a922181d097e5b22 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Fri, 22 Feb 2019 17:23:54 -0800 Subject: Add a finalizer to inline templates This commit adds a finalizer just to inline templates. We can't cache compilation of inline templates because it's possible that people could have render calls that look like this: ```ruby loop do render inline: "#{rand}" end ``` and we would cache every one of these different inline templates. That would cause a memory leak. OTOH, we don't need finalizers on regular templates because we can cache, control, and detect changes to the template source. Fixes: #35372 --- .../lib/action_view/renderer/template_renderer.rb | 2 +- actionview/lib/action_view/template.rb | 1 + actionview/lib/action_view/template/inline.rb | 22 ++++++++++++++++++++++ 3 files changed, 24 insertions(+), 1 deletion(-) create mode 100644 actionview/lib/action_view/template/inline.rb (limited to 'actionview/lib/action_view') diff --git a/actionview/lib/action_view/renderer/template_renderer.rb b/actionview/lib/action_view/renderer/template_renderer.rb index a129ef0e15..87f6cf3de3 100644 --- a/actionview/lib/action_view/renderer/template_renderer.rb +++ b/actionview/lib/action_view/renderer/template_renderer.rb @@ -34,7 +34,7 @@ module ActionView else @lookup_context.formats.first end - Template.new(options[:inline], "inline template", handler, locals: keys, format: format) + Template::Inline.new(options[:inline], "inline template", handler, locals: keys, format: format) elsif options.key?(:template) if options[:template].respond_to?(:render) options[:template] diff --git a/actionview/lib/action_view/template.rb b/actionview/lib/action_view/template.rb index 907b322c8a..133a316405 100644 --- a/actionview/lib/action_view/template.rb +++ b/actionview/lib/action_view/template.rb @@ -115,6 +115,7 @@ module ActionView autoload :Error autoload :Handlers autoload :HTML + autoload :Inline autoload :Text autoload :Types end diff --git a/actionview/lib/action_view/template/inline.rb b/actionview/lib/action_view/template/inline.rb new file mode 100644 index 0000000000..44658487ea --- /dev/null +++ b/actionview/lib/action_view/template/inline.rb @@ -0,0 +1,22 @@ +# frozen_string_literal: true + +module ActionView #:nodoc: + class Template #:nodoc: + class Inline < Template #:nodoc: + # This finalizer is needed (and exactly with a proc inside another proc) + # otherwise templates leak in development. + Finalizer = proc do |method_name, mod| # :nodoc: + proc do + mod.module_eval do + remove_possible_method method_name + end + end + end + + def compile(mod) + super + ObjectSpace.define_finalizer(self, Finalizer[method_name, mod]) + end + end + end +end -- cgit v1.2.3