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) => {