From 76c4663a77796fdcba539250dca3e6786ca0fd32 Mon Sep 17 00:00:00 2001 From: Satoshi Tagomori Date: Sun, 22 Jun 2025 17:38:24 +0900 Subject: Fix Namespace.current to show its caller's namespace Calling rb_current_namespace() in rb_namespace_current() means to show the definition namespace of Namespace.current itself (it's the root always) but the users' expectation is to show the namespace of the place where the Namespace.current is called. --- eval_intern.h | 1 + namespace.c | 3 ++- vm.c | 18 +++++++++++++----- 3 files changed, 16 insertions(+), 6 deletions(-) diff --git a/eval_intern.h b/eval_intern.h index 6353319c6f..4ac950e238 100644 --- a/eval_intern.h +++ b/eval_intern.h @@ -299,6 +299,7 @@ VALUE rb_vm_call_cfunc(VALUE recv, VALUE (*func)(VALUE), VALUE arg, VALUE block_ VALUE rb_vm_call_cfunc_in_namespace(VALUE recv, VALUE (*func)(VALUE, VALUE), VALUE arg1, VALUE arg2, VALUE filename, const rb_namespace_t *ns); void rb_vm_frame_flag_set_ns_require(const rb_execution_context_t *ec); const rb_namespace_t *rb_vm_current_namespace(const rb_execution_context_t *ec); +const rb_namespace_t *rb_vm_caller_namespace(const rb_execution_context_t *ec); const rb_namespace_t *rb_vm_loading_namespace(const rb_execution_context_t *ec); void rb_vm_set_progname(VALUE filename); VALUE rb_vm_cbase(void); diff --git a/namespace.c b/namespace.c index d3ac255363..65a90cb0da 100644 --- a/namespace.c +++ b/namespace.c @@ -455,11 +455,12 @@ rb_namespace_s_getenabled(VALUE namespace) static VALUE rb_namespace_current(VALUE klass) { - const rb_namespace_t *ns = rb_current_namespace(); + const rb_namespace_t *ns; if (!rb_namespace_available()) return Qnil; + ns = rb_vm_caller_namespace(GET_EC()); VM_ASSERT(ns && ns->ns_object); return ns->ns_object; } diff --git a/vm.c b/vm.c index 3eb5d74e83..83119c32d2 100644 --- a/vm.c +++ b/vm.c @@ -3052,13 +3052,21 @@ current_namespace_on_env(const VALUE *ep) const rb_namespace_t * rb_vm_current_namespace(const rb_execution_context_t *ec) { - const rb_control_frame_t *cfp; + VM_ASSERT(rb_namespace_available()); + return current_namespace_on_env(ec->cfp->ep); +} - if (!rb_namespace_available() || !ec) - return rb_root_namespace(); +const rb_namespace_t * +rb_vm_caller_namespace(const rb_execution_context_t *ec) +{ + const rb_control_frame_t *caller_cfp; - cfp = ec->cfp; - return current_namespace_on_env(cfp->ep); + VM_ASSERT(rb_namespace_available()); + + // The current control frame is MAGIC_CFUNC to call Namespace.current, but + // we want to get the current namespace of its caller. + caller_cfp = vm_get_ruby_level_caller_cfp(ec, RUBY_VM_PREVIOUS_CONTROL_FRAME(ec->cfp)); + return current_namespace_on_env(caller_cfp->ep); } const rb_namespace_t * -- cgit v1.2.3