Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 31 additions & 0 deletions bootstraptest/test_ractor.rb
Original file line number Diff line number Diff line change
Expand Up @@ -754,6 +754,37 @@ def ractor_local_globals
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
Expand Down
42 changes: 21 additions & 21 deletions vm_eval.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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);
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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);
Expand Down
Loading