Skip to content
Browse files

Fix warning when using yield in templates on ruby 2.7

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 May 31, 2019
1 parent a7e0018 commit dbb4df94e5bc6e533fc2ed09b2fd70df39c049c3
Showing with 7 additions and 12 deletions.
  1. +7 −12 lib/tilt/template.rb
@@ -166,7 +166,7 @@ def prepare
def evaluate(scope, locals, &block)
locals_keys = locals.keys
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)

@@ -231,9 +231,9 @@ def read_template_file

# The compiled method for the locals keys provided.
def compiled_method(locals_keys)
def compiled_method(locals_keys, scope_class=nil)
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)

@@ -247,7 +247,7 @@ def local_extraction(local_keys)

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

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

0 comments on commit dbb4df9

Please sign in to comment.
You can’t perform that action at this time.