Skip to content

Commit

Permalink
Fix warning when using yield in templates on ruby 2.7
Browse files Browse the repository at this point in the history
Take the class of the scope, and pass it through the
compilation methods.  Call class_eval on the scope's
class so that constant lookup works, and switch the
singleton class opening to instance_exec.

This radically simplifies the compiled template method
code, and I would guess it speeds it up significantly
as well.  However, this approach can cause a memory
leak if you are creating anonymous classes at runtime
and then passing instances of those classes as the scope
of the render.
  • Loading branch information
jeremyevans authored and judofyr committed Sep 23, 2019
1 parent a7e0018 commit dbb4df9
Showing 1 changed file with 7 additions and 12 deletions.
19 changes: 7 additions & 12 deletions lib/tilt/template.rb
Expand Up @@ -166,7 +166,7 @@ def prepare
def evaluate(scope, locals, &block) def evaluate(scope, locals, &block)
locals_keys = locals.keys locals_keys = locals.keys
locals_keys.sort!{|x, y| x.to_s <=> y.to_s} locals_keys.sort!{|x, y| x.to_s <=> y.to_s}
method = compiled_method(locals_keys) method = compiled_method(locals_keys, scope.class)
method.bind(scope).call(locals, &block) method.bind(scope).call(locals, &block)
end end


Expand Down Expand Up @@ -231,9 +231,9 @@ def read_template_file
end end


# The compiled method for the locals keys provided. # The compiled method for the locals keys provided.
def compiled_method(locals_keys) def compiled_method(locals_keys, scope_class=nil)
LOCK.synchronize do LOCK.synchronize do
@compiled_method[locals_keys] ||= compile_template_method(locals_keys) @compiled_method[[scope_class, locals_keys]] ||= compile_template_method(locals_keys, scope_class)
end end
end end


Expand All @@ -247,7 +247,7 @@ def local_extraction(local_keys)
end.join("\n") end.join("\n")
end end


def compile_template_method(local_keys) def compile_template_method(local_keys, scope_class=nil)
source, offset = precompiled(local_keys) source, offset = precompiled(local_keys)
local_code = local_extraction(local_keys) local_code = local_extraction(local_keys)


Expand All @@ -261,17 +261,12 @@ def compile_template_method(local_keys)
method_source << <<-RUBY method_source << <<-RUBY
TOPOBJECT.class_eval do TOPOBJECT.class_eval do
def #{method_name}(locals) def #{method_name}(locals)
Thread.current[:tilt_vars] = [self, locals] #{local_code}
class << self
this, locals = Thread.current[:tilt_vars]
locals = locals
this.instance_eval do
#{local_code}
RUBY RUBY
offset += method_source.count("\n") offset += method_source.count("\n")
method_source << source method_source << source
method_source << "\nend;end;end;end" method_source << "\nend;end;"
Object.class_eval(method_source, eval_file, line - offset) (scope_class || Object).class_eval(method_source, eval_file, line - offset)
unbind_compiled_method(method_name) unbind_compiled_method(method_name)
end end


Expand Down

0 comments on commit dbb4df9

Please sign in to comment.