diff options
| -rw-r--r-- | bootstraptest/test_ractor.rb | 31 | ||||
| -rw-r--r-- | vm_eval.c | 42 |
2 files changed, 52 insertions, 21 deletions
diff --git a/bootstraptest/test_ractor.rb b/bootstraptest/test_ractor.rb index 65ef07fb73..fef55ffd68 100644 --- a/bootstraptest/test_ractor.rb +++ b/bootstraptest/test_ractor.rb @@ -754,6 +754,37 @@ assert_equal 'ArgumentError', %q{ end } +# eval with outer locals in a Ractor raises SyntaxError +# [Bug #21522] +assert_equal 'SyntaxError', %q{ + outer = 42 + r = Ractor.new do + eval("outer") + end + begin + r.value + rescue Ractor::RemoteError => e + e.cause.class + end +} + +# eval of an undefined name in a Ractor raises NameError +assert_equal 'NameError', %q{ + r = Ractor.new do + eval("totally_undefined_name") + end + begin + r.value + rescue Ractor::RemoteError => e + e.cause.class + end +} + +# eval of a local defined inside the Ractor works +assert_equal '99', %q{ + Ractor.new { inner = 99; eval("inner").to_s }.value +} + # ivar in shareable-objects are not allowed to access from non-main Ractor assert_equal "can not get unshareable values from instance variables of classes/modules from non-main Ractors", <<~'RUBY', frozen_string_literal: false class C @@ -1669,6 +1669,24 @@ get_eval_default_path(void) return eval_default_path; } +static inline int +compute_isolated_depth_from_ep(const VALUE *ep) +{ + int depth = 1; + while (1) { + if (VM_ENV_FLAGS(ep, VM_ENV_FLAG_ISOLATED)) return depth; + if (VM_ENV_LOCAL_P(ep)) return 0; + ep = VM_ENV_PREV_EP(ep); + depth++; + } +} + +static inline int +compute_isolated_depth_from_block(const struct rb_block *blk) +{ + return compute_isolated_depth_from_ep(vm_block_ep(blk)); +} + static const rb_iseq_t * pm_eval_make_iseq(VALUE src, VALUE fname, int line, const struct rb_block *base_block) @@ -1677,8 +1695,8 @@ pm_eval_make_iseq(VALUE src, VALUE fname, int line, const rb_iseq_t *iseq = parent; VALUE name = rb_fstring_lit("<compiled>"); - // Conditionally enable coverage depending on the current mode: int coverage_enabled = ((rb_get_coverage_mode() & COVERAGE_TARGET_EVAL) != 0) ? 1 : 0; + int isolated_depth = compute_isolated_depth_from_block(base_block); if (!fname) { fname = rb_source_location(&line); @@ -1872,7 +1890,7 @@ pm_eval_make_iseq(VALUE src, VALUE fname, int line, #undef FORWARDING_ALL_STR int error_state; - iseq = pm_iseq_new_eval(&result.node, name, fname, Qnil, line, parent, 0, &error_state); + iseq = pm_iseq_new_eval(&result.node, name, fname, Qnil, line, parent, isolated_depth, &error_state); pm_scope_node_t *prev = result.node.previous; while (prev) { @@ -1908,27 +1926,9 @@ eval_make_iseq(VALUE src, VALUE fname, int line, rb_iseq_t *iseq = NULL; VALUE ast_value; rb_ast_t *ast; - int isolated_depth = 0; - // Conditionally enable coverage depending on the current mode: int coverage_enabled = (rb_get_coverage_mode() & COVERAGE_TARGET_EVAL) != 0; - - { - int depth = 1; - const VALUE *ep = vm_block_ep(base_block); - - while (1) { - if (VM_ENV_FLAGS(ep, VM_ENV_FLAG_ISOLATED)) { - isolated_depth = depth; - break; - } - else if (VM_ENV_LOCAL_P(ep)) { - break; - } - ep = VM_ENV_PREV_EP(ep); - depth++; - } - } + int isolated_depth = compute_isolated_depth_from_block(base_block); if (!fname) { fname = rb_source_location(&line); |
