Skip to content

Commit bb21b61

Browse files
committed
Detect the correct loading namespace from control frames
* checking all control frames (instead of filtering by VM_FRAME_RUBYFRAME_P) because VM_FRAME_FLAG_NS_REQUIRE is set on non-rubyframe * skip frames of CFUNC in the root namespace for Kernel#require (etc) to avoid detecting the root namespace of those frames wrongly
1 parent 48523da commit bb21b61

File tree

1 file changed

+22
-8
lines changed

1 file changed

+22
-8
lines changed

vm.c

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3065,10 +3065,24 @@ rb_vm_caller_namespace(const rb_execution_context_t *ec)
30653065

30663066
// The current control frame is MAGIC_CFUNC to call Namespace.current, but
30673067
// we want to get the current namespace of its caller.
3068-
caller_cfp = vm_get_ruby_level_caller_cfp(ec, RUBY_VM_PREVIOUS_CONTROL_FRAME(ec->cfp));
3068+
caller_cfp = vm_get_ruby_level_caller_cfp(ec, ec->cfp);
30693069
return current_namespace_on_env(caller_cfp->ep);
30703070
}
30713071

3072+
static const rb_control_frame_t *
3073+
find_loader_control_frame(const rb_control_frame_t *cfp, const rb_control_frame_t *end_cfp)
3074+
{
3075+
while (RUBY_VM_VALID_CONTROL_FRAME_P(cfp, end_cfp)) {
3076+
if (!VM_ENV_FRAME_TYPE_P(cfp->ep, VM_FRAME_MAGIC_CFUNC))
3077+
break;
3078+
if (!NAMESPACE_ROOT_P(current_namespace_on_env(cfp->ep)))
3079+
break;
3080+
cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp);
3081+
}
3082+
VM_ASSERT(RUBY_VM_VALID_CONTROL_FRAME_P(cfp, end_cfp));
3083+
return cfp;
3084+
}
3085+
30723086
const rb_namespace_t *
30733087
rb_vm_loading_namespace(const rb_execution_context_t *ec)
30743088
{
@@ -3082,14 +3096,14 @@ rb_vm_loading_namespace(const rb_execution_context_t *ec)
30823096
end_cfp = RUBY_VM_END_CONTROL_FRAME(ec);
30833097

30843098
while (RUBY_VM_VALID_CONTROL_FRAME_P(cfp, end_cfp)) {
3085-
if (VM_FRAME_RUBYFRAME_P(cfp)) {
3086-
if (VM_ENV_FLAGS(cfp->ep, VM_FRAME_FLAG_NS_REQUIRE)) {
3087-
if (RTEST(cfp->self) && NAMESPACE_OBJ_P(cfp->self)) {
3088-
// Namespace#require (, require_relative, load)
3089-
return rb_get_namespace_t(cfp->self);
3090-
}
3091-
return current_namespace_on_env(cfp->ep);
3099+
if (VM_ENV_FLAGS(cfp->ep, VM_FRAME_FLAG_NS_REQUIRE)) {
3100+
if (RTEST(cfp->self) && NAMESPACE_OBJ_P(cfp->self)) {
3101+
// Namespace#require, #require_relative, #load
3102+
return rb_get_namespace_t(cfp->self);
30923103
}
3104+
// Kernel#require, #require_relative, #load
3105+
cfp = find_loader_control_frame(cfp, end_cfp);
3106+
return current_namespace_on_env(cfp->ep);
30933107
}
30943108
cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp);
30953109
}

0 commit comments

Comments
 (0)