From e682b20f1da77d0b49fb65218584b1871752f8ec Mon Sep 17 00:00:00 2001 From: "Yukihiro \"Matz\" Matsumoto" Date: Tue, 28 Oct 2025 09:46:51 +0900 Subject: [PATCH] mruby-compiler: restore exception handling for ||= on class variables; fix #6657 Restore exception handling for `||=` operator on class variables and constants that was inadvertently removed in commit 0ca48e24f. When reading an undefined class variable with GETCV opcode raises NameError, the exception handler catches it and loads false, allowing the assignment to proceed. Co-authored-by: Claude --- mrbgems/mruby-compiler/core/codegen.c | 29 +++++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/mrbgems/mruby-compiler/core/codegen.c b/mrbgems/mruby-compiler/core/codegen.c index d8e2ce4fb..a3ace0f6f 100644 --- a/mrbgems/mruby-compiler/core/codegen.c +++ b/mrbgems/mruby-compiler/core/codegen.c @@ -4542,9 +4542,34 @@ codegen_op_asgn(codegen_scope *s, node *varnode, int val) ((name[0] == '|' && name[1] == '|') || (name[0] == '&' && name[1] == '&'))) { uint32_t pos; + enum node_type lhs_type = get_node_type(lhs); + + /* For ||= on class variables and constants, wrap read in exception handling */ + if (name[0] == '|' && (lhs_type == NODE_CVAR || lhs_type == NODE_CONST)) { + int catch_entry, begin, end; + int noexc, exc; + struct loopinfo *lp; + + lp = loop_push(s, LOOP_BEGIN); + lp->pc0 = new_label(s); + catch_entry = catch_handler_new(s); + begin = s->pc; + exc = cursp(); + codegen(s, lhs, VAL); + end = s->pc; + noexc = genjmp_0(s, OP_JMP); + lp->type = LOOP_RESCUE; + catch_handler_set(s, catch_entry, MRB_CATCH_RESCUE, begin, end, s->pc); + genop_1(s, OP_EXCEPT, exc); + genop_1(s, OP_LOADF, exc); + dispatch(s, noexc); + loop_pop(s, NOVAL); + } + else { + /* Generate code to get current value of LHS */ + codegen(s, lhs, VAL); + } - /* Generate code to get current value of LHS */ - codegen(s, lhs, VAL); pop(); if (val) { if (vsp >= 0) {