mirror of
https://github.com/mruby/mruby
synced 2026-06-08 16:11:16 +00:00
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:
+29
-21
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user