summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSatoshi Tagomori <s-tagomori@sakura.ad.jp>2025-06-22 17:38:24 +0900
committerSatoshi Tagomori <tagomoris@gmail.com>2025-09-29 01:15:38 +0900
commit76c4663a77796fdcba539250dca3e6786ca0fd32 (patch)
tree258c3aa8efc44c17ca4cddf902922cb142499638
parent4f47327287c00836a9826805a8799678d2c18516 (diff)
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.
-rw-r--r--eval_intern.h1
-rw-r--r--namespace.c3
-rw-r--r--vm.c18
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 *