Fixed visibility at method definition

There was a problem with visibility state from proc that straddles a fiber or is independent.

Therefore, it has been changed to give priority to env objects, if any.
Also, added "separate module" flag to block traversal to a higher level env object.

Note that the "separate module" flag is now set when calling blocks with the `mrb_yield_with_class()` function.

fixed https://github.com/mruby/mruby/issues/6494
This commit is contained in:
dearblue
2025-04-09 22:20:33 +09:00
parent 52de3b7e10
commit 3fd5e1c250
12 changed files with 169 additions and 34 deletions
+29 -21
View File
@@ -743,30 +743,30 @@ mrb_define_class_under(mrb_state *mrb, struct RClass *outer, const char *name, s
}
static mrb_callinfo*
find_visibility_ci(mrb_state *mrb, const struct RClass *c, int n)
find_visibility_ci(mrb_state *mrb, const struct RClass *c, int n, struct REnv **e)
{
mrb_callinfo *ci = mrb->c->ci - n;
const mrb_callinfo *cibase = mrb->c->cibase;
const struct mrb_context *ec = mrb->c;
mrb_callinfo *ci = ec->ci - n;
const struct RProc *p = ci->proc;
mrb_assert(p != NULL);
if (c == NULL) c = mrb_vm_ci_target_class(ci);
while (p->upper && cibase < ci) {
p = p->upper;
mrb_callinfo *upper_ci = ci - 1;
while (cibase < upper_ci) {
if (upper_ci->proc == p) {
if (mrb_vm_ci_target_class(upper_ci) != c) {
return ci;
}
ci = upper_ci;
break;
}
upper_ci--;
if (!p || p->upper == NULL || MRB_PROC_SCOPE_P(p) ||
p->e.env == NULL || !MRB_PROC_ENV_P(p) || mrb_vm_ci_target_class(ci) != c || MRB_CI_SEPARATE_MODULE_P(ci)) {
mrb_assert(ci->u.env);
*e = (ci->u.env->tt == MRB_TT_ENV ? ci->u.env : NULL);
return ci;
}
for (;;) {
struct REnv *env = p->e.env;
p = p->upper;
if (p->upper == NULL || MRB_PROC_SCOPE_P(p) ||
p->e.env == NULL || !MRB_PROC_ENV_P(p) || p->e.env->c != c || MRB_ENV_SEPARATE_MODULE_P(env)) {
*e = env;
return NULL;
}
}
return ci;
}
MRB_API void
@@ -813,8 +813,10 @@ mrb_define_method_raw(mrb_state *mrb, struct RClass *c, mrb_sym mid, mrb_method_
MRB_SET_VISIBILITY(flags, MT_PRIVATE);
}
else if ((flags & MT_VMASK) == MT_VDEFAULT) {
mrb_callinfo *ci = find_visibility_ci(mrb, c, 0);
MRB_SET_VISIBILITY(flags, ci->vis);
struct REnv *e;
mrb_callinfo *ci = find_visibility_ci(mrb, c, 0, &e);
mrb_assert(ci || e);
MRB_SET_VISIBILITY(flags, (e ? MRB_ENV_VISIBILITY(e) : MRB_CI_VISIBILITY(ci)));
}
mt_put(mrb, h, mid, flags, ptr);
mc_clear_by_id(mrb, mid);
@@ -1697,8 +1699,14 @@ mrb_mod_visibility(mrb_state *mrb, mrb_value mod, int vis)
mrb_get_args(mrb, "*!", &argv, &argc);
if (argc == 0) {
mrb_callinfo *ci = find_visibility_ci(mrb, NULL, 1);
ci->vis = vis;
struct REnv *e;
mrb_callinfo *ci = find_visibility_ci(mrb, NULL, 1, &e);
if (e) {
MRB_ENV_SET_VISIBILITY(e, vis);
}
else {
MRB_CI_SET_VISIBILITY(ci, vis);
}
}
else {
mt_tbl *h = c->mt;
+1
View File
@@ -86,6 +86,7 @@ mrb_env_new(mrb_state *mrb, struct mrb_context *c, mrb_callinfo *ci, int nstacks
e->mid = ci->mid;
e->stack = stack;
e->cxt = c;
MRB_ENV_COPY_FLAGS_FROM_CI(e, ci);
return e;
}
+28 -8
View File
@@ -812,10 +812,13 @@ exec_irep(mrb_state *mrb, mrb_value self, const struct RProc *p)
}
mrb_value
mrb_exec_irep(mrb_state *mrb, mrb_value self, const struct RProc *p)
mrb_exec_irep(mrb_state *mrb, mrb_value self, const struct RProc *p, mrb_bool separate_module)
{
mrb_callinfo *ci = mrb->c->ci;
if (ci->cci == CINFO_NONE) {
if (separate_module) {
MRB_CI_SET_SEPARATE_MODULE(ci);
}
return exec_irep(mrb, self, p);
}
else {
@@ -824,14 +827,20 @@ mrb_exec_irep(mrb_state *mrb, mrb_value self, const struct RProc *p)
if (MRB_PROC_NOARG_P(p) && (ci->n > 0 || ci->nk > 0)) {
check_method_noarg(mrb, ci);
}
cipush(mrb, 0, CINFO_DIRECT, CI_TARGET_CLASS(ci), p, NULL, ci->mid, ci->n|(ci->nk<<4));
ci = cipush(mrb, 0, CINFO_DIRECT, CI_TARGET_CLASS(ci), p, NULL, ci->mid, ci->n|(ci->nk<<4));
if (separate_module) {
MRB_CI_SET_SEPARATE_MODULE(ci);
}
mrb->exc = NULL;
ret = MRB_PROC_CFUNC(p)(mrb, self);
cipop(mrb);
}
else {
mrb_int keep = ci_bidx(ci) + 1; /* receiver + block */
cipush(mrb, 0, CINFO_SKIP, CI_TARGET_CLASS(ci), p, NULL, ci->mid, ci->n|(ci->nk<<4));
ci = cipush(mrb, 0, CINFO_SKIP, CI_TARGET_CLASS(ci), p, NULL, ci->mid, ci->n|(ci->nk<<4));
if (separate_module) {
MRB_CI_SET_SEPARATE_MODULE(ci);
}
ret = mrb_vm_run(mrb, p, self, keep);
}
if (mrb->exc && mrb->jmp) {
@@ -855,7 +864,7 @@ mrb_object_exec(mrb_state *mrb, mrb_value self, struct RClass *target_class)
mrb_gc_protect(mrb, blk);
ci->stack[bidx] = mrb_nil_value();
mrb_vm_ci_target_class_set(ci, target_class);
return mrb_exec_irep(mrb, self, mrb_proc_ptr(blk));
return mrb_exec_irep(mrb, self, mrb_proc_ptr(blk), FALSE);
}
/* 15.3.1.3.4 */
@@ -977,6 +986,7 @@ eval_under(mrb_state *mrb, mrb_value self, mrb_value blk, struct RClass *c)
ci->n = 1;
ci->nk = 0;
ci->mid = ci[-1].mid;
MRB_CI_SET_SEPARATE_MODULE(ci);
if (MRB_PROC_CFUNC_P(p)) {
stack_extend(mrb, 4);
mrb->c->ci->stack[0] = self;
@@ -1048,8 +1058,9 @@ mrb_obj_instance_eval(mrb_state *mrb, mrb_value self)
return eval_under(mrb, self, b, mrb_singleton_class_ptr(mrb, self));
}
MRB_API mrb_value
mrb_yield_with_class(mrb_state *mrb, mrb_value b, mrb_int argc, const mrb_value *argv, mrb_value self, struct RClass *c)
static mrb_value
yield_with_attr(mrb_state *mrb, mrb_value b, mrb_int argc, const mrb_value *argv, mrb_value self, struct RClass *c,
mrb_bool separate_module)
{
check_block(mrb, b);
@@ -1068,6 +1079,9 @@ mrb_yield_with_class(mrb_state *mrb, mrb_value b, mrb_int argc, const mrb_value
funcall_args_capture(mrb, 0, argc, argv, mrb_nil_value(), ci);
ci->u.target_class = c;
ci->proc = p;
if (separate_module) {
MRB_CI_SET_SEPARATE_MODULE(ci);
}
mrb_value val;
if (MRB_PROC_CFUNC_P(p)) {
@@ -1086,6 +1100,12 @@ mrb_yield_with_class(mrb_state *mrb, mrb_value b, mrb_int argc, const mrb_value
return val;
}
MRB_API mrb_value
mrb_yield_with_class(mrb_state *mrb, mrb_value b, mrb_int argc, const mrb_value *argv, mrb_value self, struct RClass *c)
{
return yield_with_attr(mrb, b, argc, argv, self, c, TRUE);
}
MRB_API mrb_value
mrb_yield_argv(mrb_state *mrb, mrb_value b, mrb_int argc, const mrb_value *argv)
{
@@ -1093,7 +1113,7 @@ mrb_yield_argv(mrb_state *mrb, mrb_value b, mrb_int argc, const mrb_value *argv)
struct RClass *tc;
mrb_value self = mrb_proc_get_self(mrb, p, &tc);
return mrb_yield_with_class(mrb, b, argc, argv, self, tc);
return yield_with_attr(mrb, b, argc, argv, self, tc, FALSE);
}
MRB_API mrb_value
@@ -1103,7 +1123,7 @@ mrb_yield(mrb_state *mrb, mrb_value b, mrb_value arg)
struct RClass *tc;
mrb_value self = mrb_proc_get_self(mrb, p, &tc);
return mrb_yield_with_class(mrb, b, 1, &arg, self, tc);
return yield_with_attr(mrb, b, 1, &arg, self, tc, FALSE);
}
mrb_value