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
上级 a796de1b
......@@ -34,7 +34,7 @@ def determine_template(options)
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]
......
......@@ -115,6 +115,7 @@ def self.finalize_compiled_template_methods=(_)
autoload :Error
autoload :Handlers
autoload :HTML
autoload :Inline
autoload :Text
autoload :Types
end
......
# 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
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册