From 5c385c2b1cc3ee1902ac97f7978e02f38d580a25 Mon Sep 17 00:00:00 2001 From: pjh456 <147148383@qq.com> Date: Fri, 7 Aug 2026 18:32:05 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E9=97=AD=E5=8C=85=E6=8D=95=E8=8E=B7?= =?UTF-8?q?=E5=88=86=E6=9E=90=E8=A1=A5=E6=89=AB=20catch=20=E5=8F=82?= =?UTF-8?q?=E6=95=B0=E8=A7=A3=E6=9E=84=E6=A8=A1=E5=BC=8F=E7=9A=84=E8=A1=A8?= =?UTF-8?q?=E8=BE=BE=E5=BC=8F=E5=BC=95=E7=94=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- crates/oxide_emit/src/closure.rs | 80 ++++++++++++++++++++++++++++++-- 1 file changed, 77 insertions(+), 3 deletions(-) diff --git a/crates/oxide_emit/src/closure.rs b/crates/oxide_emit/src/closure.rs index b576b77d..2c52a384 100644 --- a/crates/oxide_emit/src/closure.rs +++ b/crates/oxide_emit/src/closure.rs @@ -175,8 +175,14 @@ impl Emitter { self.collect_capture_names_stmt(s, ref_set, shadow, out); } if let Some(h) = &ts.handler { + // catch 参数解构模式内的表达式引用(默认值等)也会被内部闭包捕获; + // 参数声明名遮蔽 catch 作用域。 + let mut catch_shadow = shadow.clone(); + if let Some(param) = &h.param { + self.collect_capture_names_binding_pattern(¶m.pattern, ref_set, shadow, out, &mut catch_shadow); + } for s in &h.body.body { - self.collect_capture_names_stmt(s, ref_set, shadow, out); + self.collect_capture_names_stmt(s, ref_set, &catch_shadow, out); } } if let Some(f) = &ts.finalizer { @@ -199,6 +205,41 @@ impl Emitter { } } + /// 遍历 catch 参数解构模式:收集模式内表达式引用(默认值等),声明名写入 + /// `catch_shadow` 遮蔽 catch 作用域。 + fn collect_capture_names_binding_pattern( + &self, pattern: &oxide_parser::BindingPattern, ref_set: &HashSet, shadow: &HashSet, + out: &mut HashSet, catch_shadow: &mut HashSet, + ) { + match pattern { + oxide_parser::BindingPattern::BindingIdentifier(bi) => { + catch_shadow.insert(bi.name.as_str().to_string()); + } + oxide_parser::BindingPattern::ArrayPattern(ap) => { + for elem in &ap.elements { + if let Some(p) = elem { + self.collect_capture_names_binding_pattern(p, ref_set, shadow, out, catch_shadow); + } + } + if let Some(rest) = &ap.rest { + self.collect_capture_names_binding_pattern(&rest.argument, ref_set, shadow, out, catch_shadow); + } + } + oxide_parser::BindingPattern::ObjectPattern(op) => { + for prop in &op.properties { + self.collect_capture_names_binding_pattern(&prop.value, ref_set, shadow, out, catch_shadow); + } + if let Some(rest) = &op.rest { + self.collect_capture_names_binding_pattern(&rest.argument, ref_set, shadow, out, catch_shadow); + } + } + oxide_parser::BindingPattern::AssignmentPattern(ap) => { + self.collect_capture_names_expr(&ap.right, ref_set, shadow, out); + self.collect_capture_names_binding_pattern(&ap.left, ref_set, shadow, out, catch_shadow); + } + } + } + fn collect_capture_names_expr( &self, expr: &Expression, ref_set: &HashSet, shadow: &HashSet, out: &mut HashSet, ) { @@ -353,8 +394,7 @@ impl Emitter { } /// 只从嵌套函数节点进入扫描(本函数直接引用不算捕获)。 - fn collect_captured_stmt(&self, stmt: &Statement, own: &HashSet, out: &mut HashSet) { - match stmt { + fn collect_captured_stmt(&self, stmt: &Statement, own: &HashSet, out: &mut HashSet) { match stmt { Statement::FunctionDeclaration(fd) => { let body: &[Statement] = fd.body.as_ref().map(|b| &b.statements[..]).unwrap_or(&[]); self.collect_capture_names(body, own, out); @@ -419,6 +459,9 @@ impl Emitter { self.collect_captured_stmt(s, own, out); } if let Some(h) = &ts.handler { + if let Some(param) = &h.param { + self.collect_captured_binding_pattern(¶m.pattern, own, out); + } for s in &h.body.body { self.collect_captured_stmt(s, own, out); } @@ -443,6 +486,37 @@ impl Emitter { } } + /// 遍历 catch 参数解构模式内表达式引用(默认值等),供父层 MAKE_CELL 判定。 + fn collect_captured_binding_pattern( + &self, pattern: &oxide_parser::BindingPattern, own: &HashSet, out: &mut HashSet, + ) { + match pattern { + oxide_parser::BindingPattern::BindingIdentifier(_) => {} + oxide_parser::BindingPattern::ArrayPattern(ap) => { + for elem in &ap.elements { + if let Some(p) = elem { + self.collect_captured_binding_pattern(p, own, out); + } + } + if let Some(rest) = &ap.rest { + self.collect_captured_binding_pattern(&rest.argument, own, out); + } + } + oxide_parser::BindingPattern::ObjectPattern(op) => { + for prop in &op.properties { + self.collect_captured_binding_pattern(&prop.value, own, out); + } + if let Some(rest) = &op.rest { + self.collect_captured_binding_pattern(&rest.argument, own, out); + } + } + oxide_parser::BindingPattern::AssignmentPattern(ap) => { + self.collect_captured_expr(&ap.right, own, out); + self.collect_captured_binding_pattern(&ap.left, own, out); + } + } + } + fn collect_captured_expr(&self, expr: &Expression, own: &HashSet, out: &mut HashSet) { match expr { Expression::FunctionExpression(fe) => {