Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

binding does not capture block #3285

Open
jonathanhefner opened this issue Oct 3, 2023 · 2 comments
Open

binding does not capture block #3285

jonathanhefner opened this issue Oct 3, 2023 · 2 comments

Comments

@jonathanhefner
Copy link

@eregon Continuing from rails/sdoc#314 (comment)...

Here is a reproduction stripped down from rails/sdoc#314:

require "erb"

def render(template_string)
  ERB.new(template_string).result(binding)
end

render("<%= yield %>") { "x" }

The original test failure (before I added the workaround) was due to ERB#result raising LocalJumpError: no block given (yield). The tests all pass on CRuby >= 2.7.

jonathanhefner added a commit to jonathanhefner/sdoc that referenced this issue Oct 5, 2023
There is currently a bug in TruffleRuby ([truffleruby#3285][]) wherein
`Kernel#binding` does not capture a given anonymous block, which breaks
`yield` calls evaluated using that binding.  This bug is preventing us
from extending our rendering API.

Furthermore, this bug was caught by a test unit for said API extension,
but our views themselves aren't tested by CI.  So if such a `yield` call
were added to a view, CI would still pass but the `sdoc` command would
be broken when using TruffleRuby.

Also, Rails itself does not officially support TruffleRuby.

Considering all of the above, this commit removes TruffleRuby from CI.

[truffleruby#3285]: oracle/truffleruby#3285
@eregon
Copy link
Member

eregon commented Oct 6, 2023

Thank you for the report.
It can be simplified to just:

def render
  eval('yield', binding)
end

p render { "x" }

If we look at the stacktrace with eval('puts caller(0)', binding):

(eval):1:in `render' # block available here
bind.rb:2:in `eval'
bind.rb:2:in `render' # block passed here
bind.rb:5:in `<main>'

So the eval is treated like a block inside render.
So there is probably an issue where we don't correctly look for the surrounding block with eval.

@eregon
Copy link
Member

eregon commented May 7, 2024

FWIW, somewhat related:
https://bugs.ruby-lang.org/issues/15554

warning: use yield in eval will not be supported in Ruby 3.

(although that's not the exact warning on CRuby master)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants