From fa4c9edb8172e1efe09bbe111ff816f55067414c Mon Sep 17 00:00:00 2001 From: pjh456 <147148383@qq.com> Date: Tue, 15 Sep 2026 23:02:03 +0000 Subject: [PATCH] =?UTF-8?q?refactor:=20=E9=97=AD=E5=8C=85=E6=8D=95?= =?UTF-8?q?=E8=8E=B7=E5=88=86=E6=9E=90=E6=8B=86=E7=9B=AE=E5=BD=95=E5=B9=B6?= =?UTF-8?q?=E8=87=AA=E7=94=B1=E5=87=BD=E6=95=B0=E5=8C=96=E5=8E=BB=E9=99=A4?= =?UTF-8?q?=E6=8E=A5=E6=94=B6=E8=80=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- crates/oxide_emit/src/capture/captured.rs | 424 +++++ crates/oxide_emit/src/capture/mod.rs | 71 + crates/oxide_emit/src/capture/names.rs | 261 ++++ crates/oxide_emit/src/capture/scanner.rs | 614 ++++++++ crates/oxide_emit/src/capture/upvalues.rs | 48 + crates/oxide_emit/src/closure.rs | 1383 ----------------- crates/oxide_emit/src/function_body.rs | 19 +- crates/oxide_emit/src/lib.rs | 2 +- crates/oxide_emit/src/module.rs | 5 +- crates/oxide_emit/src/prepass/block_fn.rs | 13 +- crates/oxide_emit/src/program.rs | 18 +- .../oxide_emit/src/stmt/iteration/for_in.rs | 3 +- 12 files changed, 1453 insertions(+), 1408 deletions(-) create mode 100644 crates/oxide_emit/src/capture/captured.rs create mode 100644 crates/oxide_emit/src/capture/mod.rs create mode 100644 crates/oxide_emit/src/capture/names.rs create mode 100644 crates/oxide_emit/src/capture/scanner.rs create mode 100644 crates/oxide_emit/src/capture/upvalues.rs delete mode 100644 crates/oxide_emit/src/closure.rs diff --git a/crates/oxide_emit/src/capture/captured.rs b/crates/oxide_emit/src/capture/captured.rs new file mode 100644 index 00000000..6fddf4dc --- /dev/null +++ b/crates/oxide_emit/src/capture/captured.rs @@ -0,0 +1,424 @@ +//! 闭包捕获分析,父层捕获分析:本函数哪些绑定被任意深度嵌套函数捕获 +//! → BTreeMap(cell_idx 按名字序,稳定跨 run)。 + +use std::collections::{BTreeMap, HashSet}; + +use oxide_parser::{Expression, Statement}; + +use super::collect_fn_param_names; +use super::names::collect_own_binding_names; +use super::scanner::{collect_capture_names_expr, collect_capture_names_shadowed, collect_class_capture_names}; + +/// 分析本函数:哪些绑定被任意深度嵌套函数捕获 → captured_bindings。 +pub(crate) fn collect_captured_bindings( + stmts: &[Statement], extra_exprs: &[&oxide_parser::Expression], own: &HashSet, +) -> BTreeMap { + let mut names = HashSet::new(); + for stmt in stmts { + collect_captured_stmt(stmt, own, &mut names); + } + // 参数默认值表达式(不在 body_stmts 内)里的嵌套函数引用也要纳入捕获, + // 否则默认值内 IIFE 引用全局/外层变量走 LOAD_VAR 读寄存器残留(B022 扩展)。 + for expr in extra_exprs { + collect_captured_expr(expr, own, &mut names); + } + // 名字排序分配 cell_idx(稳定跨 run,父 MAKE_CELL 与子 upvalue 统一引用) + let mut sorted: Vec = names.into_iter().collect(); + sorted.sort(); + sorted.into_iter().enumerate().map(|(i, n)| (n, i as u8)).collect() +} + +/// 收集函数参数默认值表达式里的嵌套函数引用(父层 captured/子层 upvalue 判定)。 +pub(crate) fn collect_fn_default_captured( + params: &oxide_parser::FormalParameters, own: &HashSet, out: &mut HashSet, +) { + let empty_shadow = HashSet::new(); + for p in ¶ms.items { + if let Some(init) = &p.initializer { + collect_capture_names_expr(init, own, &empty_shadow, out); + } + // 形参模式的运行时求值表达式(计算键/内嵌默认值)在子作用域求值, + // 其标识符引用须纳入父层 MAKE_CELL 判定。 + collect_captured_pattern_runtime_exprs(&p.pattern, own, out); + } +} + +/// 遍历绑定 pattern 内全部运行时求值表达式(计算键与 AssignmentPattern 默认值): +/// 这些表达式在子作用域(嵌套函数形参绑定时)求值,引用的父层绑定须建 cell 供 +/// 子函数 upvalue 读取——与 `collect_capture_names_expr` 同口径(标识符比对)。 +pub(crate) fn collect_captured_pattern_runtime_exprs( + pattern: &oxide_parser::BindingPattern, own: &HashSet, out: &mut HashSet, +) { + let empty_shadow = HashSet::new(); + match pattern { + oxide_parser::BindingPattern::BindingIdentifier(_) => {} + oxide_parser::BindingPattern::ArrayPattern(ap) => { + for p in ap.elements.iter().flatten() { + collect_captured_pattern_runtime_exprs(p, own, out); + } + if let Some(rest) = &ap.rest { + collect_captured_pattern_runtime_exprs(&rest.argument, own, out); + } + } + oxide_parser::BindingPattern::ObjectPattern(op) => { + for prop in &op.properties { + if prop.computed { + collect_capture_names_expr(prop.key.to_expression(), own, &empty_shadow, out); + } + collect_captured_pattern_runtime_exprs(&prop.value, own, out); + } + if let Some(rest) = &op.rest { + collect_captured_pattern_runtime_exprs(&rest.argument, own, out); + } + } + oxide_parser::BindingPattern::AssignmentPattern(ap) => { + collect_capture_names_expr(&ap.right, own, &empty_shadow, out); + collect_captured_pattern_runtime_exprs(&ap.left, own, out); + } + } +} + +/// 只从嵌套函数节点进入扫描(本函数直接引用不算捕获)。 +pub(crate) fn collect_captured_stmt(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(&[]); + collect_fn_default_captured(&fd.params, own, out); + // 函数参数与体内部声明遮蔽父级绑定:体内对这些名字的引用不算捕获父级。 + let mut fn_shadow = HashSet::new(); + fn_shadow.extend(collect_fn_param_names(&fd.params)); + fn_shadow.extend(collect_own_binding_names(&[], body)); + collect_capture_names_shadowed(body, own, &fn_shadow, out); + } + Statement::ClassDeclaration(cd) => { + // 类构造器/方法体与字段表达式引用的父级绑定须建 cell,供子模块 upvalue 捕获。 + let mut class_shadow = HashSet::new(); + if let Some(id) = &cd.id { + class_shadow.insert(id.name.as_str().to_string()); + } + collect_class_capture_names(&cd.body, own, &class_shadow, out); + } + Statement::ExpressionStatement(es) => collect_captured_expr(&es.expression, own, out), + Statement::ReturnStatement(rs) => { + if let Some(a) = &rs.argument { + collect_captured_expr(a, own, out); + } + } + Statement::VariableDeclaration(vd) => { + for d in &vd.declarations { + // 绑定 pattern 的计算键是运行时求值表达式,其引用须纳入捕获判定。 + collect_captured_binding_keys(&d.id, own, out); + if let Some(init) = &d.init { + collect_captured_expr(init, own, out); + } + } + } + Statement::IfStatement(is) => { + collect_captured_expr(&is.test, own, out); + collect_captured_stmt(&is.consequent, own, out); + if let Some(alt) = &is.alternate { + collect_captured_stmt(alt, own, out); + } + } + Statement::ForStatement(fs) => { + if let Some(init) = &fs.init { + if let Some(e) = init.as_expression() { + collect_captured_expr(e, own, out); + } + if let oxide_parser::ForStatementInit::VariableDeclaration(vd) = init { + for d in &vd.declarations { + collect_captured_binding_keys(&d.id, own, out); + if let Some(i) = &d.init { + collect_captured_expr(i, own, out); + } + } + } + } + if let Some(t) = &fs.test { + collect_captured_expr(t, own, out); + } + if let Some(u) = &fs.update { + collect_captured_expr(u, own, out); + } + collect_captured_stmt(&fs.body, own, out); + } + Statement::WhileStatement(w) => { + collect_captured_expr(&w.test, own, out); + collect_captured_stmt(&w.body, own, out); + } + Statement::DoWhileStatement(d) => { + collect_captured_stmt(&d.body, own, out); + collect_captured_expr(&d.test, own, out); + } + Statement::ForInStatement(fi) => { + collect_captured_expr(&fi.right, own, out); + if let oxide_parser::ForStatementLeft::VariableDeclaration(vd) = &fi.left { + for d in &vd.declarations { + collect_captured_binding_keys(&d.id, own, out); + } + } + collect_captured_stmt(&fi.body, own, out); + } + Statement::ForOfStatement(fo) => { + collect_captured_expr(&fo.right, own, out); + if let oxide_parser::ForStatementLeft::VariableDeclaration(vd) = &fo.left { + for d in &vd.declarations { + collect_captured_binding_keys(&d.id, own, out); + } + } + collect_captured_stmt(&fo.body, own, out); + } + Statement::BlockStatement(b) => { + for s in &b.body { + collect_captured_stmt(s, own, out); + } + } + Statement::TryStatement(ts) => { + for s in &ts.block.body { + collect_captured_stmt(s, own, out); + } + if let Some(h) = &ts.handler { + if let Some(param) = &h.param { + collect_captured_binding_pattern(¶m.pattern, own, out); + } + for s in &h.body.body { + collect_captured_stmt(s, own, out); + } + } + if let Some(f) = &ts.finalizer { + for s in &f.body { + collect_captured_stmt(s, own, out); + } + } + } + Statement::ThrowStatement(ts) => collect_captured_expr(&ts.argument, own, out), + Statement::SwitchStatement(sw) => { + collect_captured_expr(&sw.discriminant, own, out); + for case in &sw.cases { + for s in &case.consequent { + collect_captured_stmt(s, own, out); + } + } + } + Statement::LabeledStatement(ls) => collect_captured_stmt(&ls.body, own, out), + Statement::WithStatement(ws) => { + collect_captured_expr(&ws.object, own, out); + collect_captured_stmt(&ws.body, own, out); + } + _ => {} + } +} + +/// 遍历 catch 参数解构模式内表达式引用(默认值等),供父层 MAKE_CELL 判定。 +pub(crate) fn collect_captured_binding_pattern( + pattern: &oxide_parser::BindingPattern, own: &HashSet, out: &mut HashSet, +) { + match pattern { + oxide_parser::BindingPattern::BindingIdentifier(_) => {} + oxide_parser::BindingPattern::ArrayPattern(ap) => { + for p in ap.elements.iter().flatten() { + collect_captured_binding_pattern(p, own, out); + } + if let Some(rest) = &ap.rest { + collect_captured_binding_pattern(&rest.argument, own, out); + } + } + oxide_parser::BindingPattern::ObjectPattern(op) => { + for prop in &op.properties { + // 计算键表达式(本作用域 catch 参数求值,含 IIFE 等嵌套函数)引用 + // 本函数绑定走寄存器,只须扫描键内嵌套函数表达式。 + if prop.computed { + collect_captured_expr(prop.key.to_expression(), own, out); + } + collect_captured_binding_pattern(&prop.value, own, out); + } + if let Some(rest) = &op.rest { + collect_captured_binding_pattern(&rest.argument, own, out); + } + } + oxide_parser::BindingPattern::AssignmentPattern(ap) => { + collect_captured_expr(&ap.right, own, out); + collect_captured_binding_pattern(&ap.left, own, out); + } + } +} + +/// 遍历绑定 pattern 的运行时求值表达式引用:计算键(`{[k]: a}` 的键)与内嵌 +/// 默认值(`{a = x}` 的 x),供父层捕获判定(声明语句/for 头的模式与 catch/ +/// 默认值路径同口径)。 +pub(crate) fn collect_captured_binding_keys( + pattern: &oxide_parser::BindingPattern, own: &HashSet, out: &mut HashSet, +) { + match pattern { + oxide_parser::BindingPattern::BindingIdentifier(_) => {} + oxide_parser::BindingPattern::ArrayPattern(ap) => { + for p in ap.elements.iter().flatten() { + collect_captured_binding_keys(p, own, out); + } + if let Some(rest) = &ap.rest { + collect_captured_binding_keys(&rest.argument, own, out); + } + } + oxide_parser::BindingPattern::ObjectPattern(op) => { + for prop in &op.properties { + if prop.computed { + collect_captured_expr(prop.key.to_expression(), own, out); + } + collect_captured_binding_keys(&prop.value, own, out); + } + if let Some(rest) = &op.rest { + collect_captured_binding_keys(&rest.argument, own, out); + } + } + oxide_parser::BindingPattern::AssignmentPattern(ap) => { + // 内嵌默认值表达式引用外层绑定须建 cell(与 captured_binding_pattern + // 同口径);left 继续递归模式键。 + collect_captured_expr(&ap.right, own, out); + collect_captured_binding_keys(&ap.left, own, out); + } + } +} + +pub(crate) fn collect_captured_expr(expr: &Expression, own: &HashSet, out: &mut HashSet) { + match expr { + Expression::FunctionExpression(fe) => { + let body: &[Statement] = fe.body.as_ref().map(|b| &b.statements[..]).unwrap_or(&[]); + let mut inner = collect_fn_param_names(&fe.params); + inner.extend(collect_own_binding_names(&[], body)); + collect_fn_default_captured(&fe.params, own, out); + collect_capture_names_shadowed(body, own, &inner, out); + } + Expression::ArrowFunctionExpression(ae) => { + let mut inner = collect_fn_param_names(&ae.params); + inner.extend(collect_own_binding_names(&[], &ae.body.statements)); + collect_fn_default_captured(&ae.params, own, out); + collect_capture_names_shadowed(&ae.body.statements, own, &inner, out); + } + Expression::ClassExpression(class) => { + // 类表达式:构造器/方法体与字段表达式引用的父级绑定须建 cell。 + let mut class_shadow = HashSet::new(); + if let Some(id) = &class.id { + class_shadow.insert(id.name.as_str().to_string()); + } + collect_class_capture_names(&class.body, own, &class_shadow, out); + } + Expression::CallExpression(ce) => { + collect_captured_expr(&ce.callee, own, out); + for a in &ce.arguments { + collect_captured_arg(a, own, out); + } + } + Expression::BinaryExpression(be) => { + collect_captured_expr(&be.left, own, out); + collect_captured_expr(&be.right, own, out); + } + Expression::UnaryExpression(ue) => collect_captured_expr(&ue.argument, own, out), + Expression::LogicalExpression(le) => { + collect_captured_expr(&le.left, own, out); + collect_captured_expr(&le.right, own, out); + } + Expression::ConditionalExpression(ce) => { + collect_captured_expr(&ce.test, own, out); + collect_captured_expr(&ce.consequent, own, out); + collect_captured_expr(&ce.alternate, own, out); + } + Expression::SequenceExpression(se) => { + for e in &se.expressions { + collect_captured_expr(e, own, out); + } + } + Expression::AssignmentExpression(ae) => { + // 只扫右侧:左侧赋值目标是本函数绑定,不引用嵌套函数; + // 若目标含嵌套函数表达式(如 `[f()] = ...`),由其自身递归处理。 + collect_captured_expr(&ae.right, own, out); + } + Expression::UpdateExpression(_ue) => {} // 一元更新目标不引用嵌套函数,无需捕获 + Expression::ArrayExpression(ae) => { + for e in &ae.elements { + if let Some(e) = e.as_expression() { + collect_captured_expr(e, own, out); + } + } + } + Expression::ObjectExpression(o) => { + for prop in &o.properties { + match prop { + oxide_parser::ObjectPropertyKind::ObjectProperty(p) => { + if p.computed { + collect_captured_expr(p.key.to_expression(), own, out); + } + collect_captured_expr(&p.value, own, out); + } + oxide_parser::ObjectPropertyKind::SpreadProperty(spread) => { + collect_captured_expr(&spread.argument, own, out); + } + } + } + } + Expression::NewExpression(ne) => { + collect_captured_expr(&ne.callee, own, out); + for a in &ne.arguments { + collect_captured_arg(a, own, out); + } + } + Expression::ComputedMemberExpression(m) => { + collect_captured_expr(&m.object, own, out); + collect_captured_expr(&m.expression, own, out); + } + Expression::StaticMemberExpression(m) => collect_captured_expr(&m.object, own, out), + Expression::PrivateFieldExpression(m) => collect_captured_expr(&m.object, own, out), + Expression::TemplateLiteral(tl) => { + for e in &tl.expressions { + collect_captured_expr(e, own, out); + } + } + Expression::TaggedTemplateExpression(tt) => { + collect_captured_expr(&tt.tag, own, out); + for e in &tt.quasi.expressions { + collect_captured_expr(e, own, out); + } + } + Expression::ParenthesizedExpression(p) => collect_captured_expr(&p.expression, own, out), + Expression::YieldExpression(ye) => { + if let Some(a) = &ye.argument { + collect_captured_expr(a, own, out); + } + } + Expression::AwaitExpression(ae) => collect_captured_expr(&ae.argument, own, out), + Expression::ChainExpression(c) => collect_captured_chain(&c.expression, own, out), + _ => {} + } +} + +pub(crate) fn collect_captured_chain( + element: &oxide_parser::ChainElement, own: &HashSet, out: &mut HashSet, +) { + match element { + oxide_parser::ChainElement::StaticMemberExpression(m) => { + collect_captured_expr(&m.object, own, out); + } + oxide_parser::ChainElement::ComputedMemberExpression(m) => { + collect_captured_expr(&m.object, own, out); + collect_captured_expr(&m.expression, own, out); + } + oxide_parser::ChainElement::PrivateFieldExpression(m) => { + collect_captured_expr(&m.object, own, out); + } + oxide_parser::ChainElement::CallExpression(c) => { + collect_captured_expr(&c.callee, own, out); + for a in &c.arguments { + collect_captured_arg(a, own, out); + } + } + _ => {} + } +} + +/// 遍历调用实参:静态实参与 spread 内部表达式都纳入捕获判定。 +pub(crate) fn collect_captured_arg(arg: &oxide_parser::Argument, own: &HashSet, out: &mut HashSet) { + if let Some(e) = arg.as_expression() { + collect_captured_expr(e, own, out); + } else if let oxide_parser::Argument::SpreadElement(sp) = arg { + collect_captured_expr(&sp.argument, own, out); + } +} diff --git a/crates/oxide_emit/src/capture/mod.rs b/crates/oxide_emit/src/capture/mod.rs new file mode 100644 index 00000000..c2f6a52a --- /dev/null +++ b/crates/oxide_emit/src/capture/mod.rs @@ -0,0 +1,71 @@ +//! 闭包捕获分析(AST 级,emit 前完成,时序无关)。 +//! +//! 收集本函数绑定的名字(own_bindings)与被嵌套函数捕获的名字 +//! (captured_bindings → cell_idx,按名排序稳定跨 run),为 MAKE_CELL / +//! CELL_GET / CELL_SET 与子函数 upvalue cell_idx 提供统一依据。 +//! +//! 五区严格单向分层(本文件 ← names ← scanner ← captured ← upvalues): +//! 跨区调用单向、无共享局部状态、无接收者状态。 + +mod captured; +mod names; +mod scanner; +mod upvalues; + +use std::collections::HashSet; + +pub(crate) use captured::collect_captured_bindings; +pub(crate) use names::collect_own_binding_names; +pub(crate) use names::collect_top_level_function_names; +pub(crate) use names::collect_top_level_function_names_ordered; +pub(crate) use names::collect_var_binding_names; +pub(crate) use upvalues::collect_upvalue_names; + +pub(crate) fn collect_fn_param_names(params: &oxide_parser::FormalParameters) -> HashSet { + let mut names = HashSet::new(); + for p in ¶ms.items { + collect_binding_pattern_names(&p.pattern, &mut names); + } + // rest 形参也是本函数作用域绑定,遮蔽外层同名变量。 + if let Some(rest) = ¶ms.rest { + collect_binding_pattern_names(&rest.rest.argument, &mut names); + } + names +} + +/// 递归收集 binding pattern 内全部绑定标识符名(解构 `[a, b]` / `{x: y}` 嵌套)。 +pub(crate) fn collect_binding_pattern_names(pattern: &oxide_parser::BindingPattern, out: &mut HashSet) { + match pattern { + oxide_parser::BindingPattern::BindingIdentifier(bi) => { + out.insert(bi.name.to_string()); + } + oxide_parser::BindingPattern::ArrayPattern(ap) => { + for p in ap.elements.iter().flatten() { + collect_binding_pattern_names(p, out); + } + if let Some(rest) = &ap.rest { + collect_binding_pattern_names(&rest.argument, out); + } + } + oxide_parser::BindingPattern::ObjectPattern(op) => { + for prop in &op.properties { + collect_binding_pattern_names(&prop.value, out); + } + if let Some(rest) = &op.rest { + collect_binding_pattern_names(&rest.argument, out); + } + } + oxide_parser::BindingPattern::AssignmentPattern(ap) => { + collect_binding_pattern_names(&ap.left, out); + } + } +} + +/// 收集 for-in/for-of 头部声明(`var x` / 解构 pattern)绑定的名字。 +pub(crate) fn collect_for_left_decl_names(left: &oxide_parser::ForStatementLeft, out: &mut HashSet) { + if let oxide_parser::ForStatementLeft::VariableDeclaration(vd) = left { + for d in &vd.declarations { + collect_binding_pattern_names(&d.id, out); + } + } +} diff --git a/crates/oxide_emit/src/capture/names.rs b/crates/oxide_emit/src/capture/names.rs new file mode 100644 index 00000000..ae7d6275 --- /dev/null +++ b/crates/oxide_emit/src/capture/names.rs @@ -0,0 +1,261 @@ +//! 闭包捕获分析,own/var/顶层声明名收集:本函数 own_bindings 名集 +//! (参数名 + 变量/函数/import/export 声明,含嵌套块)、var 提升入口 +//! 名集、顶层函数声明名集(无序集 + 声明序列表)。 + +use std::collections::HashSet; + +use oxide_parser::{Statement, VariableDeclarationKind}; + +use super::{collect_binding_pattern_names, collect_for_left_decl_names}; + +/// 收集语句树中全部 `var` 声明名(var 提升到函数/程序作用域,递归进嵌套块)。 +/// 供函数/程序入口批量 MAKE_CELL(undefined) 使用(var 入口实例化语义)。 +pub(crate) fn collect_var_binding_names(stmts: &[Statement]) -> HashSet { + let mut names = HashSet::new(); + collect_var_names_stmt(stmts, &mut names); + names +} + +pub(crate) fn collect_var_names_stmt(stmts: &[Statement], out: &mut HashSet) { + for stmt in stmts { + match stmt { + Statement::VariableDeclaration(vd) => { + if matches!(vd.kind, VariableDeclarationKind::Var) { + for d in &vd.declarations { + collect_binding_pattern_names(&d.id, out); + } + } + } + Statement::BlockStatement(b) => collect_var_names_stmt(&b.body, out), + Statement::IfStatement(is) => { + collect_var_names_stmt(std::slice::from_ref(&is.consequent), out); + if let Some(alt) = &is.alternate { + collect_var_names_stmt(std::slice::from_ref(alt), out); + } + } + Statement::WhileStatement(w) => collect_var_names_stmt(std::slice::from_ref(&w.body), out), + Statement::DoWhileStatement(d) => collect_var_names_stmt(std::slice::from_ref(&d.body), out), + Statement::ForStatement(f) => { + if let Some(oxide_parser::ForStatementInit::VariableDeclaration(vd)) = &f.init { + if matches!(vd.kind, VariableDeclarationKind::Var) { + for d in &vd.declarations { + collect_binding_pattern_names(&d.id, out); + } + } + } + collect_var_names_stmt(std::slice::from_ref(&f.body), out); + } + Statement::ForInStatement(fi) => { + if let oxide_parser::ForStatementLeft::VariableDeclaration(vd) = &fi.left { + // 仅 var 头名提升到函数作用域,let/const 头名是迭代级绑定。 + if matches!(vd.kind, VariableDeclarationKind::Var) { + collect_for_left_decl_names(&fi.left, out); + } + } + collect_var_names_stmt(std::slice::from_ref(&fi.body), out); + } + Statement::ForOfStatement(fo) => { + if let oxide_parser::ForStatementLeft::VariableDeclaration(vd) = &fo.left { + // 仅 var 头名提升到函数作用域,let/const 头名是迭代级绑定。 + if matches!(vd.kind, VariableDeclarationKind::Var) { + collect_for_left_decl_names(&fo.left, out); + } + } + collect_var_names_stmt(std::slice::from_ref(&fo.body), out); + } + Statement::SwitchStatement(sw) => { + for case in &sw.cases { + collect_var_names_stmt(&case.consequent, out); + } + } + Statement::TryStatement(ts) => { + collect_var_names_stmt(&ts.block.body, out); + if let Some(h) = &ts.handler { + collect_var_names_stmt(&h.body.body, out); + } + if let Some(f) = &ts.finalizer { + collect_var_names_stmt(&f.body, out); + } + } + Statement::LabeledStatement(ls) => collect_var_names_stmt(std::slice::from_ref(&ls.body), out), + Statement::WithStatement(ws) => collect_var_names_stmt(std::slice::from_ref(&ws.body), out), + Statement::ExportNamedDeclaration(exp) => { + if let Some(oxide_parser::Declaration::VariableDeclaration(vd)) = &exp.declaration { + if matches!(vd.kind, VariableDeclarationKind::Var) { + for d in &vd.declarations { + collect_binding_pattern_names(&d.id, out); + } + } + } + } + _ => {} + } + } +} + +/// 收集语句列表**直接子级**函数声明的绑定名(顶层函数声明是全局 var 绑定, +/// 裸读/裸写与 var 名同路由全局对象属性)。不递归进块:块内函数声明是块 +/// 作用域,不参与全局对象同步;`export default function` 是 lexical 绑定,不纳。 +pub(crate) fn collect_top_level_function_names(stmts: &[Statement]) -> HashSet { + let mut names = HashSet::new(); + for stmt in stmts { + if let Statement::FunctionDeclaration(fd) = stmt { + if let Some(id) = &fd.id { + names.insert(id.name.to_string()); + } + } + } + names +} + +/// 同 [`collect_top_level_function_names`] 的收集面,但按**声明序**返回 Vec +/// (供 GDI 检查阶段逆序遍历逐名去重,规范"逆序首见 = 源序最后声明")。 +pub(crate) fn collect_top_level_function_names_ordered(stmts: &[Statement]) -> Vec { + let mut names = Vec::new(); + for stmt in stmts { + if let Statement::FunctionDeclaration(fd) = stmt { + if let Some(id) = &fd.id { + names.push(id.name.to_string()); + } + } + } + names +} + +/// 收集当前函数作用域声明的绑定名(参数 + 变量/函数声明,含嵌套 block,不含嵌套函数体)。 +pub(crate) fn collect_own_binding_names(param_names: &[&str], stmts: &[Statement]) -> HashSet { + let mut names = HashSet::new(); + for p in param_names { + names.insert(p.to_string()); + } + collect_decl_names_stmt(stmts, &mut names); + names +} + +pub(crate) fn collect_decl_names_stmt(stmts: &[Statement], out: &mut HashSet) { + for stmt in stmts { + match stmt { + Statement::VariableDeclaration(vd) => { + for d in &vd.declarations { + collect_binding_pattern_names(&d.id, out); + } + } + Statement::FunctionDeclaration(fd) => { + if let Some(id) = &fd.id { + out.insert(id.name.to_string()); + } + } + // class 名是本作用域 const 绑定:须计入 own_bindings,否则嵌套函数 + // 引用类名时捕获分析缺失 → 落符号表兜底(TDZ 误报或读父寄存器残留)。 + Statement::ClassDeclaration(cd) => { + if let Some(id) = &cd.id { + out.insert(id.name.to_string()); + } + } + // import 绑定是模块作用域 const 绑定,须计入 own_bindings 供 + // 嵌套函数 cell 捕获。 + Statement::ImportDeclaration(imp) => { + if let Some(specifiers) = &imp.specifiers { + for sp in specifiers { + match sp { + oxide_parser::ImportDeclarationSpecifier::ImportSpecifier(s) => { + out.insert(s.local.name.to_string()); + } + oxide_parser::ImportDeclarationSpecifier::ImportDefaultSpecifier(s) => { + out.insert(s.local.name.to_string()); + } + oxide_parser::ImportDeclarationSpecifier::ImportNamespaceSpecifier(s) => { + out.insert(s.local.name.to_string()); + } + } + } + } + } + Statement::ExportNamedDeclaration(exp) => { + if let Some(decl) = &exp.declaration { + match decl { + oxide_parser::Declaration::VariableDeclaration(vd) => { + for d in &vd.declarations { + collect_binding_pattern_names(&d.id, out); + } + } + oxide_parser::Declaration::FunctionDeclaration(fd) => { + if let Some(id) = &fd.id { + out.insert(id.name.to_string()); + } + } + oxide_parser::Declaration::ClassDeclaration(cd) => { + if let Some(id) = &cd.id { + out.insert(id.name.to_string()); + } + } + _ => {} + } + } + } + Statement::ExportDefaultDeclaration(exp) => match &exp.declaration { + oxide_parser::ExportDefaultDeclarationKind::FunctionDeclaration(fd) => { + if let Some(id) = &fd.id { + out.insert(id.name.to_string()); + } + } + oxide_parser::ExportDefaultDeclarationKind::ClassDeclaration(cd) => { + if let Some(id) = &cd.id { + out.insert(id.name.to_string()); + } + } + _ => {} + }, + Statement::BlockStatement(b) => collect_decl_names_stmt(&b.body, out), + Statement::IfStatement(is) => { + collect_decl_names_stmt(std::slice::from_ref(&is.consequent), out); + if let Some(alt) = &is.alternate { + collect_decl_names_stmt(std::slice::from_ref(alt), out); + } + } + Statement::WhileStatement(w) => collect_decl_names_stmt(std::slice::from_ref(&w.body), out), + Statement::DoWhileStatement(d) => collect_decl_names_stmt(std::slice::from_ref(&d.body), out), + Statement::ForStatement(f) => { + if let Some(oxide_parser::ForStatementInit::VariableDeclaration(vd)) = &f.init { + for d in &vd.declarations { + if let oxide_parser::BindingPattern::BindingIdentifier(bi) = &d.id { + out.insert(bi.name.to_string()); + } + } + } + collect_decl_names_stmt(std::slice::from_ref(&f.body), out); + } + // for-in / for-of 头部的 var 声明是本函数局部绑定(遮蔽外层同名), + // 须计入 own_bindings,否则闭包捕获分析会误判为捕获外层变量。 + Statement::ForInStatement(fi) => { + if let oxide_parser::ForStatementLeft::VariableDeclaration(_) = &fi.left { + collect_for_left_decl_names(&fi.left, out); + } + collect_decl_names_stmt(std::slice::from_ref(&fi.body), out); + } + Statement::ForOfStatement(fo) => { + if let oxide_parser::ForStatementLeft::VariableDeclaration(_) = &fo.left { + collect_for_left_decl_names(&fo.left, out); + } + collect_decl_names_stmt(std::slice::from_ref(&fo.body), out); + } + Statement::SwitchStatement(sw) => { + for case in &sw.cases { + collect_decl_names_stmt(&case.consequent, out); + } + } + Statement::TryStatement(ts) => { + collect_decl_names_stmt(&ts.block.body, out); + if let Some(h) = &ts.handler { + collect_decl_names_stmt(&h.body.body, out); + } + if let Some(f) = &ts.finalizer { + collect_decl_names_stmt(&f.body, out); + } + } + Statement::LabeledStatement(ls) => collect_decl_names_stmt(std::slice::from_ref(&ls.body), out), + Statement::WithStatement(ws) => collect_decl_names_stmt(std::slice::from_ref(&ws.body), out), + _ => {} + } + } +} diff --git a/crates/oxide_emit/src/capture/scanner.rs b/crates/oxide_emit/src/capture/scanner.rs new file mode 100644 index 00000000..dd5700aa --- /dev/null +++ b/crates/oxide_emit/src/capture/scanner.rs @@ -0,0 +1,614 @@ +//! 闭包捕获分析,遮蔽感知引用收集:ref_set × shadow 双集驱动,遍历 +//! 语句/表达式/赋值目标/类体 AST,嵌套函数/类/for 头/catch 参数逐层 +//! 遮蔽,收集任意深度嵌套函数引用的名字。 + +use std::collections::HashSet; + +use oxide_parser::{ClassBody, ClassElement, Expression, Statement}; + +use super::names::collect_own_binding_names; +use super::{collect_fn_param_names, collect_for_left_decl_names}; + +pub(crate) fn collect_capture_names_shadowed( + stmts: &[Statement], ref_set: &HashSet, shadow: &HashSet, out: &mut HashSet, +) { + for stmt in stmts { + collect_capture_names_stmt(stmt, ref_set, shadow, out); + } +} + +pub(crate) fn collect_capture_names_stmt( + stmt: &Statement, ref_set: &HashSet, shadow: &HashSet, out: &mut HashSet, +) { + match stmt { + Statement::ExpressionStatement(es) => collect_capture_names_expr(&es.expression, ref_set, shadow, out), + Statement::ReturnStatement(rs) => { + if let Some(a) = &rs.argument { + collect_capture_names_expr(a, ref_set, shadow, out); + } + } + Statement::VariableDeclaration(vd) => { + for d in &vd.declarations { + // 绑定 pattern 的计算键是运行时求值表达式,其引用须纳入捕获。 + collect_capture_names_binding_keys(&d.id, ref_set, shadow, out); + if let Some(init) = &d.init { + collect_capture_names_expr(init, ref_set, shadow, out); + } + } + } + Statement::FunctionDeclaration(fd) => { + let body: &[Statement] = fd.body.as_ref().map(|b| &b.statements[..]).unwrap_or(&[]); + let mut inner = shadow.clone(); + inner.extend(collect_fn_param_names(&fd.params)); + inner.extend(collect_own_binding_names(&[], body)); + collect_fn_default_names(&fd.params, ref_set, shadow, out); + collect_capture_names_shadowed(body, ref_set, &inner, out); + } + Statement::ClassDeclaration(cd) => { + // 类体(构造器/方法体、字段键与值、静态块)是嵌套作用域: + // 类名遮蔽外层绑定,方法形参与方法体局部进一步遮蔽。 + let mut class_shadow = shadow.clone(); + if let Some(id) = &cd.id { + class_shadow.insert(id.name.as_str().to_string()); + } + collect_class_capture_names(&cd.body, ref_set, &class_shadow, out); + } + Statement::IfStatement(is) => { + collect_capture_names_expr(&is.test, ref_set, shadow, out); + collect_capture_names_stmt(&is.consequent, ref_set, shadow, out); + if let Some(alt) = &is.alternate { + collect_capture_names_stmt(alt, ref_set, shadow, out); + } + } + Statement::ForStatement(fs) => { + if let Some(init) = &fs.init { + if let Some(e) = init.as_expression() { + collect_capture_names_expr(e, ref_set, shadow, out); + } + if let oxide_parser::ForStatementInit::VariableDeclaration(vd) = init { + for d in &vd.declarations { + collect_capture_names_binding_keys(&d.id, ref_set, shadow, out); + if let Some(i) = &d.init { + collect_capture_names_expr(i, ref_set, shadow, out); + } + } + } + } + if let Some(t) = &fs.test { + collect_capture_names_expr(t, ref_set, shadow, out); + } + if let Some(u) = &fs.update { + collect_capture_names_expr(u, ref_set, shadow, out); + } + collect_capture_names_stmt(&fs.body, ref_set, shadow, out); + } + Statement::WhileStatement(w) => { + collect_capture_names_expr(&w.test, ref_set, shadow, out); + collect_capture_names_stmt(&w.body, ref_set, shadow, out); + } + Statement::DoWhileStatement(d) => { + collect_capture_names_stmt(&d.body, ref_set, shadow, out); + collect_capture_names_expr(&d.test, ref_set, shadow, out); + } + Statement::ForInStatement(fi) => { + collect_capture_names_expr(&fi.right, ref_set, shadow, out); + // left 的 var 声明遮蔽外层同名绑定,body 内引用不视为捕获外层。 + let mut for_shadow = shadow.clone(); + collect_for_left_decl_names(&fi.left, &mut for_shadow); + if let oxide_parser::ForStatementLeft::VariableDeclaration(vd) = &fi.left { + for d in &vd.declarations { + collect_capture_names_binding_keys(&d.id, ref_set, shadow, out); + } + } + collect_capture_names_shadowed(std::slice::from_ref(&fi.body), ref_set, &for_shadow, out); + } + Statement::ForOfStatement(fo) => { + collect_capture_names_expr(&fo.right, ref_set, shadow, out); + let mut for_shadow = shadow.clone(); + collect_for_left_decl_names(&fo.left, &mut for_shadow); + if let oxide_parser::ForStatementLeft::VariableDeclaration(vd) = &fo.left { + for d in &vd.declarations { + collect_capture_names_binding_keys(&d.id, ref_set, shadow, out); + } + } + collect_capture_names_shadowed(std::slice::from_ref(&fo.body), ref_set, &for_shadow, out); + } + Statement::BlockStatement(b) => collect_capture_names_shadowed(&b.body, ref_set, shadow, out), + Statement::TryStatement(ts) => { + for s in &ts.block.body { + 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 { + collect_capture_names_binding_pattern(¶m.pattern, ref_set, shadow, out, &mut catch_shadow); + } + for s in &h.body.body { + collect_capture_names_stmt(s, ref_set, &catch_shadow, out); + } + } + if let Some(f) = &ts.finalizer { + for s in &f.body { + collect_capture_names_stmt(s, ref_set, shadow, out); + } + } + } + Statement::ExportNamedDeclaration(exp) => { + if let Some(decl) = &exp.declaration { + match decl { + oxide_parser::Declaration::VariableDeclaration(vd) => { + for d in &vd.declarations { + collect_capture_names_binding_keys(&d.id, ref_set, shadow, out); + if let Some(init) = &d.init { + collect_capture_names_expr(init, ref_set, shadow, out); + } + } + } + oxide_parser::Declaration::FunctionDeclaration(fd) => { + let body: &[Statement] = fd.body.as_ref().map(|b| &b.statements[..]).unwrap_or(&[]); + let mut inner = shadow.clone(); + inner.extend(collect_fn_param_names(&fd.params)); + inner.extend(collect_own_binding_names(&[], body)); + collect_fn_default_names(&fd.params, ref_set, shadow, out); + collect_capture_names_shadowed(body, ref_set, &inner, out); + } + oxide_parser::Declaration::ClassDeclaration(cd) => { + let mut class_shadow = shadow.clone(); + if let Some(id) = &cd.id { + class_shadow.insert(id.name.as_str().to_string()); + } + collect_class_capture_names(&cd.body, ref_set, &class_shadow, out); + } + _ => {} + } + } + } + Statement::ExportDefaultDeclaration(exp) => match &exp.declaration { + oxide_parser::ExportDefaultDeclarationKind::FunctionDeclaration(fd) => { + let body: &[Statement] = fd.body.as_ref().map(|b| &b.statements[..]).unwrap_or(&[]); + let mut inner = shadow.clone(); + inner.extend(collect_fn_param_names(&fd.params)); + inner.extend(collect_own_binding_names(&[], body)); + collect_fn_default_names(&fd.params, ref_set, shadow, out); + collect_capture_names_shadowed(body, ref_set, &inner, out); + } + oxide_parser::ExportDefaultDeclarationKind::ClassDeclaration(cd) => { + let mut class_shadow = shadow.clone(); + if let Some(id) = &cd.id { + class_shadow.insert(id.name.as_str().to_string()); + } + collect_class_capture_names(&cd.body, ref_set, &class_shadow, out); + } + other => { + if let Some(e) = other.as_expression() { + collect_capture_names_expr(e, ref_set, shadow, out); + } + } + }, + Statement::ThrowStatement(ts) => collect_capture_names_expr(&ts.argument, ref_set, shadow, out), + Statement::SwitchStatement(sw) => { + collect_capture_names_expr(&sw.discriminant, ref_set, shadow, out); + for case in &sw.cases { + for s in &case.consequent { + collect_capture_names_stmt(s, ref_set, shadow, out); + } + } + } + Statement::LabeledStatement(ls) => collect_capture_names_stmt(&ls.body, ref_set, shadow, out), + Statement::WithStatement(ws) => { + collect_capture_names_expr(&ws.object, ref_set, shadow, out); + collect_capture_names_stmt(&ws.body, ref_set, shadow, out); + } + _ => {} + } +} + +/// 收集类体对 `ref_set` 的引用:方法/构造器体、字段键与值、静态块。 +/// 方法形参与方法体局部声明遮蔽外层绑定(捕获判定用)。 +pub(crate) fn collect_class_capture_names( + class_body: &ClassBody, ref_set: &HashSet, class_shadow: &HashSet, out: &mut HashSet, +) { + for element in &class_body.body { + match element { + ClassElement::MethodDefinition(method) => { + let mut inner = class_shadow.clone(); + inner.extend(collect_fn_param_names(&method.value.params)); + let body: &[Statement] = method.value.body.as_ref().map(|b| &b.statements[..]).unwrap_or(&[]); + inner.extend(collect_own_binding_names(&[], body)); + collect_fn_default_names(&method.value.params, ref_set, class_shadow, out); + collect_capture_names_shadowed(body, ref_set, &inner, out); + } + ClassElement::PropertyDefinition(prop) => { + if let Some(expr) = prop.key.as_expression() { + collect_capture_names_expr(expr, ref_set, class_shadow, out); + } + if let Some(value) = &prop.value { + collect_capture_names_expr(value, ref_set, class_shadow, out); + } + } + ClassElement::StaticBlock(block) => { + collect_capture_names_shadowed(&block.body, ref_set, class_shadow, out); + } + _ => {} + } + } +} + +/// 遍历 catch 参数解构模式:收集模式内表达式引用(默认值等),声明名写入 +/// `catch_shadow` 遮蔽 catch 作用域。 +pub(crate) fn collect_capture_names_binding_pattern( + 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 p in ap.elements.iter().flatten() { + collect_capture_names_binding_pattern(p, ref_set, shadow, out, catch_shadow); + } + if let Some(rest) = &ap.rest { + collect_capture_names_binding_pattern(&rest.argument, ref_set, shadow, out, catch_shadow); + } + } + oxide_parser::BindingPattern::ObjectPattern(op) => { + for prop in &op.properties { + // 计算键是运行时求值表达式,其引用须纳入捕获。 + if prop.computed { + collect_capture_names_expr(prop.key.to_expression(), ref_set, shadow, out); + } + collect_capture_names_binding_pattern(&prop.value, ref_set, shadow, out, catch_shadow); + } + if let Some(rest) = &op.rest { + collect_capture_names_binding_pattern(&rest.argument, ref_set, shadow, out, catch_shadow); + } + } + oxide_parser::BindingPattern::AssignmentPattern(ap) => { + collect_capture_names_expr(&ap.right, ref_set, shadow, out); + collect_capture_names_binding_pattern(&ap.left, ref_set, shadow, out, catch_shadow); + } + } +} + +/// 遍历绑定 pattern 的运行时求值表达式引用:计算键(`{[k]: a}` 的键)与内嵌 +/// 默认值(`{a = x}` 的 x)都是模式内求值的表达式,嵌套函数引用外层绑定时须 +/// 纳入捕获(与赋值侧/对象字面量/类字段键遍历同口径)。 +pub(crate) fn collect_capture_names_binding_keys( + pattern: &oxide_parser::BindingPattern, ref_set: &HashSet, shadow: &HashSet, + out: &mut HashSet, +) { + match pattern { + oxide_parser::BindingPattern::BindingIdentifier(_) => {} + oxide_parser::BindingPattern::ArrayPattern(ap) => { + for p in ap.elements.iter().flatten() { + collect_capture_names_binding_keys(p, ref_set, shadow, out); + } + if let Some(rest) = &ap.rest { + collect_capture_names_binding_keys(&rest.argument, ref_set, shadow, out); + } + } + oxide_parser::BindingPattern::ObjectPattern(op) => { + for prop in &op.properties { + if prop.computed { + collect_capture_names_expr(prop.key.to_expression(), ref_set, shadow, out); + } + collect_capture_names_binding_keys(&prop.value, ref_set, shadow, out); + } + if let Some(rest) = &op.rest { + collect_capture_names_binding_keys(&rest.argument, ref_set, shadow, out); + } + } + oxide_parser::BindingPattern::AssignmentPattern(ap) => { + // 内嵌默认值表达式引用外层绑定须捕获(与 binding_pattern/赋值侧 + // maybe_default 的 init 扫描同口径);left 继续递归模式键。 + collect_capture_names_expr(&ap.right, ref_set, shadow, out); + collect_capture_names_binding_keys(&ap.left, ref_set, shadow, out); + } + } +} + +/// 扫描赋值目标中的引用(标识符写名,成员目标扫对象/键,解构目标递归元素)。 +pub(crate) fn collect_capture_names_assign_target( + target: &oxide_parser::AssignmentTarget, ref_set: &HashSet, shadow: &HashSet, + out: &mut HashSet, +) { + match target { + oxide_parser::AssignmentTarget::AssignmentTargetIdentifier(ati) => { + let name = ati.name.as_str(); + if ref_set.contains(name) && !shadow.contains(name) { + out.insert(ati.name.to_string()); + } + } + oxide_parser::AssignmentTarget::StaticMemberExpression(m) => { + collect_capture_names_expr(&m.object, ref_set, shadow, out); + } + oxide_parser::AssignmentTarget::ComputedMemberExpression(m) => { + collect_capture_names_expr(&m.object, ref_set, shadow, out); + collect_capture_names_expr(&m.expression, ref_set, shadow, out); + } + oxide_parser::AssignmentTarget::ArrayAssignmentTarget(a) => { + for e in a.elements.iter().flatten() { + collect_capture_names_maybe_default_target(e, ref_set, shadow, out); + } + if let Some(rest) = &a.rest { + collect_capture_names_assign_target(&rest.target, ref_set, shadow, out); + } + } + oxide_parser::AssignmentTarget::ObjectAssignmentTarget(o) => { + for prop in &o.properties { + if let oxide_parser::AssignmentTargetProperty::AssignmentTargetPropertyIdentifier(id) = prop { + if ref_set.contains(id.binding.name.as_str()) && !shadow.contains(id.binding.name.as_str()) { + out.insert(id.binding.name.to_string()); + } + if let Some(init) = &id.init { + collect_capture_names_expr(init, ref_set, shadow, out); + } + } else if let oxide_parser::AssignmentTargetProperty::AssignmentTargetPropertyProperty(p) = prop { + if let Some(name_expr) = p.name.as_expression() { + collect_capture_names_expr(name_expr, ref_set, shadow, out); + } + collect_capture_names_maybe_default_target(&p.binding, ref_set, shadow, out); + } + } + if let Some(rest) = &o.rest { + collect_capture_names_assign_target(&rest.target, ref_set, shadow, out); + } + } + _ => {} + } +} + +/// 解构赋值元素可能是 `AssignmentTarget` 或带默认值的包装(后者多一层 `init`)。 +pub(crate) fn collect_capture_names_maybe_default_target( + target: &oxide_parser::AssignmentTargetMaybeDefault, ref_set: &HashSet, shadow: &HashSet, + out: &mut HashSet, +) { + use oxide_parser::AssignmentTargetMaybeDefault as MaybeDefault; + match target { + MaybeDefault::AssignmentTargetWithDefault(d) => { + collect_capture_names_expr(&d.init, ref_set, shadow, out); + collect_capture_names_assign_target(&d.binding, ref_set, shadow, out); + } + MaybeDefault::AssignmentTargetIdentifier(ati) => { + let name = ati.name.as_str(); + if ref_set.contains(name) && !shadow.contains(name) { + out.insert(ati.name.to_string()); + } + } + MaybeDefault::StaticMemberExpression(m) => { + collect_capture_names_expr(&m.object, ref_set, shadow, out); + } + MaybeDefault::ComputedMemberExpression(m) => { + collect_capture_names_expr(&m.object, ref_set, shadow, out); + collect_capture_names_expr(&m.expression, ref_set, shadow, out); + } + MaybeDefault::ArrayAssignmentTarget(a) => { + for e in a.elements.iter().flatten() { + collect_capture_names_maybe_default_target(e, ref_set, shadow, out); + } + } + MaybeDefault::ObjectAssignmentTarget(o) => { + for prop in &o.properties { + if let oxide_parser::AssignmentTargetProperty::AssignmentTargetPropertyIdentifier(id) = prop { + if ref_set.contains(id.binding.name.as_str()) && !shadow.contains(id.binding.name.as_str()) { + out.insert(id.binding.name.to_string()); + } + if let Some(init) = &id.init { + collect_capture_names_expr(init, ref_set, shadow, out); + } + } else if let oxide_parser::AssignmentTargetProperty::AssignmentTargetPropertyProperty(p) = prop { + if let Some(name_expr) = p.name.as_expression() { + collect_capture_names_expr(name_expr, ref_set, shadow, out); + } + collect_capture_names_maybe_default_target(&p.binding, ref_set, shadow, out); + } + } + } + _ => {} + } +} + +/// 扫描一元更新目标(`++x` / `obj.x++`)中的引用。 +pub(crate) fn collect_capture_names_simple_target( + target: &oxide_parser::SimpleAssignmentTarget, ref_set: &HashSet, shadow: &HashSet, + out: &mut HashSet, +) { + match target { + oxide_parser::SimpleAssignmentTarget::AssignmentTargetIdentifier(ati) => { + let name = ati.name.as_str(); + if ref_set.contains(name) && !shadow.contains(name) { + out.insert(ati.name.to_string()); + } + } + oxide_parser::SimpleAssignmentTarget::StaticMemberExpression(m) => { + collect_capture_names_expr(&m.object, ref_set, shadow, out); + } + oxide_parser::SimpleAssignmentTarget::ComputedMemberExpression(m) => { + collect_capture_names_expr(&m.object, ref_set, shadow, out); + collect_capture_names_expr(&m.expression, ref_set, shadow, out); + } + _ => {} + } +} + +/// 收集函数参数默认值表达式里的引用(子层 upvalue 判定;参数名遮蔽)。 +pub(crate) fn collect_fn_default_names( + params: &oxide_parser::FormalParameters, ref_set: &HashSet, shadow: &HashSet, + out: &mut HashSet, +) { + for p in ¶ms.items { + if let Some(init) = &p.initializer { + collect_capture_names_expr(init, ref_set, shadow, out); + } + let mut param_shadow = shadow.clone(); + collect_capture_names_binding_pattern(&p.pattern, ref_set, shadow, out, &mut param_shadow); + } +} + +pub(crate) fn collect_capture_names_expr( + expr: &Expression, ref_set: &HashSet, shadow: &HashSet, out: &mut HashSet, +) { + match expr { + Expression::Identifier(id) => { + let name = id.name.as_str(); + if ref_set.contains(name) && !shadow.contains(name) { + out.insert(id.name.to_string()); + } + } + Expression::AssignmentExpression(ae) => { + // 赋值目标里的引用也须捕获:标识符目标写名,成员/解构目标扫描其对象/元素。 + collect_capture_names_assign_target(&ae.left, ref_set, shadow, out); + collect_capture_names_expr(&ae.right, ref_set, shadow, out); + } + Expression::UpdateExpression(ue) => { + collect_capture_names_simple_target(&ue.argument, ref_set, shadow, out); + } + Expression::FunctionExpression(fe) => { + let body: &[Statement] = fe.body.as_ref().map(|b| &b.statements[..]).unwrap_or(&[]); + let mut inner = shadow.clone(); + inner.extend(collect_fn_param_names(&fe.params)); + inner.extend(collect_own_binding_names(&[], body)); + collect_fn_default_names(&fe.params, ref_set, shadow, out); + collect_capture_names_shadowed(body, ref_set, &inner, out); + } + Expression::ArrowFunctionExpression(ae) => { + let mut inner = shadow.clone(); + inner.extend(collect_fn_param_names(&ae.params)); + inner.extend(collect_own_binding_names(&[], &ae.body.statements)); + collect_fn_default_names(&ae.params, ref_set, shadow, out); + collect_capture_names_shadowed(&ae.body.statements, ref_set, &inner, out); + } + Expression::ClassExpression(class) => { + // 类表达式:方法/构造器体与字段表达式是嵌套作用域,引用须捕获。 + let mut class_shadow = shadow.clone(); + if let Some(id) = &class.id { + class_shadow.insert(id.name.as_str().to_string()); + } + collect_class_capture_names(&class.body, ref_set, &class_shadow, out); + } + Expression::BinaryExpression(be) => { + collect_capture_names_expr(&be.left, ref_set, shadow, out); + collect_capture_names_expr(&be.right, ref_set, shadow, out); + } + Expression::UnaryExpression(ue) => collect_capture_names_expr(&ue.argument, ref_set, shadow, out), + Expression::CallExpression(ce) => { + collect_capture_names_expr(&ce.callee, ref_set, shadow, out); + for a in &ce.arguments { + collect_capture_names_arg(a, ref_set, shadow, out); + } + } + Expression::NewExpression(ne) => { + collect_capture_names_expr(&ne.callee, ref_set, shadow, out); + for a in &ne.arguments { + collect_capture_names_arg(a, ref_set, shadow, out); + } + } + Expression::SequenceExpression(se) => { + for e in &se.expressions { + collect_capture_names_expr(e, ref_set, shadow, out); + } + } + Expression::ConditionalExpression(ce) => { + collect_capture_names_expr(&ce.test, ref_set, shadow, out); + collect_capture_names_expr(&ce.consequent, ref_set, shadow, out); + collect_capture_names_expr(&ce.alternate, ref_set, shadow, out); + } + Expression::ArrayExpression(ae) => { + for e in &ae.elements { + if let Some(e) = e.as_expression() { + collect_capture_names_expr(e, ref_set, shadow, out); + } + } + } + Expression::LogicalExpression(le) => { + collect_capture_names_expr(&le.left, ref_set, shadow, out); + collect_capture_names_expr(&le.right, ref_set, shadow, out); + } + Expression::ComputedMemberExpression(m) => { + collect_capture_names_expr(&m.object, ref_set, shadow, out); + collect_capture_names_expr(&m.expression, ref_set, shadow, out); + } + Expression::StaticMemberExpression(m) => collect_capture_names_expr(&m.object, ref_set, shadow, out), + Expression::PrivateFieldExpression(m) => collect_capture_names_expr(&m.object, ref_set, shadow, out), + Expression::ParenthesizedExpression(p) => collect_capture_names_expr(&p.expression, ref_set, shadow, out), + Expression::TemplateLiteral(tl) => { + for e in &tl.expressions { + collect_capture_names_expr(e, ref_set, shadow, out); + } + } + Expression::TaggedTemplateExpression(tt) => { + collect_capture_names_expr(&tt.tag, ref_set, shadow, out); + for e in &tt.quasi.expressions { + collect_capture_names_expr(e, ref_set, shadow, out); + } + } + Expression::ObjectExpression(o) => { + for prop in &o.properties { + match prop { + oxide_parser::ObjectPropertyKind::ObjectProperty(p) => { + if p.computed { + collect_capture_names_expr(p.key.to_expression(), ref_set, shadow, out); + } + collect_capture_names_expr(&p.value, ref_set, shadow, out); + } + oxide_parser::ObjectPropertyKind::SpreadProperty(spread) => { + collect_capture_names_expr(&spread.argument, ref_set, shadow, out); + } + } + } + } + // 生成器让出表达式:被让出的值里引用的父变量须纳入捕获,否则生成器体经 + // LOAD_VAR 读调用方寄存器残留(挂起恢复后寄存器已被覆盖)。 + Expression::YieldExpression(ye) => { + if let Some(a) = &ye.argument { + collect_capture_names_expr(a, ref_set, shadow, out); + } + } + // await 表达式:被等待的值里引用的父变量须纳入捕获(与 yield 同因—— + // 异步体挂起恢复后寄存器已被覆盖,只能经 cell 读取)。 + Expression::AwaitExpression(ae) => { + collect_capture_names_expr(&ae.argument, ref_set, shadow, out); + } + Expression::ChainExpression(c) => collect_capture_names_chain(&c.expression, ref_set, shadow, out), + _ => {} + } +} + +pub(crate) fn collect_capture_names_chain( + element: &oxide_parser::ChainElement, ref_set: &HashSet, shadow: &HashSet, + out: &mut HashSet, +) { + match element { + oxide_parser::ChainElement::StaticMemberExpression(m) => { + collect_capture_names_expr(&m.object, ref_set, shadow, out); + } + oxide_parser::ChainElement::ComputedMemberExpression(m) => { + collect_capture_names_expr(&m.object, ref_set, shadow, out); + collect_capture_names_expr(&m.expression, ref_set, shadow, out); + } + oxide_parser::ChainElement::PrivateFieldExpression(m) => { + collect_capture_names_expr(&m.object, ref_set, shadow, out); + } + oxide_parser::ChainElement::CallExpression(call) => { + collect_capture_names_expr(&call.callee, ref_set, shadow, out); + for a in &call.arguments { + collect_capture_names_arg(a, ref_set, shadow, out); + } + } + _ => {} + } +} + +/// 遍历调用实参:静态实参与 spread 内部表达式都纳入捕获扫描。 +pub(crate) fn collect_capture_names_arg( + arg: &oxide_parser::Argument, ref_set: &HashSet, shadow: &HashSet, out: &mut HashSet, +) { + if let Some(e) = arg.as_expression() { + collect_capture_names_expr(e, ref_set, shadow, out); + } else if let oxide_parser::Argument::SpreadElement(sp) = arg { + collect_capture_names_expr(&sp.argument, ref_set, shadow, out); + } +} diff --git a/crates/oxide_emit/src/capture/upvalues.rs b/crates/oxide_emit/src/capture/upvalues.rs new file mode 100644 index 00000000..efc4bfd8 --- /dev/null +++ b/crates/oxide_emit/src/capture/upvalues.rs @@ -0,0 +1,48 @@ +//! 闭包捕获分析,子函数 upvalue 分析:子函数体对父被捕获绑定的引用 +//! → Vec(排序对齐 cell_idx,enclosing_reg 留 0 待 +//! assemble_ir 填充)。 + +use std::collections::{BTreeMap, HashSet}; + +use oxide_bytecode::module::UpvalueCapture; +use oxide_parser::Statement; + +use super::scanner::{collect_capture_names_expr, collect_capture_names_shadowed}; + +/// 分析子函数 body:引用父级被捕获绑定的名字 → upvalue_captures。 +/// 名字若在父 `captured_bindings`(父 own cell)则 `cell_idx` 索引定义方表; +/// 若在父 `upvalue_captures`(父自身从更外层捕获)则链式标记 `parent_uv_idx`, +/// 运行时从父闭包 upvalues 取 cell。enclosing_reg 由父 emit 完成后填充。 +pub(crate) fn collect_upvalue_names( + body_stmts: &[Statement], extra_exprs: &[&oxide_parser::Expression], parent_captured: &BTreeMap, + parent_upvalues: &[UpvalueCapture], sub_own: &HashSet, +) -> Vec { + let mut parent_names: HashSet = parent_captured.keys().cloned().collect(); + for u in parent_upvalues { + parent_names.insert(u.name.clone()); + } + let mut names = HashSet::new(); + collect_capture_names_shadowed(body_stmts, &parent_names, sub_own, &mut names); + // 参数默认值表达式(不在 body_stmts)里的嵌套函数引用也会捕获父变量。 + for expr in extra_exprs { + collect_capture_names_expr(expr, &parent_names, sub_own, &mut names); + } + // HashSet 迭代序带随机种子(进程级非确定),必须排序使 upvalue_captures 的顺序与 + // 父 captured_bindings 的 cell_idx(BTreeMap 名字序)对齐——否则 LOAD_UPVALUE 的 + // a 槽 uv_idx 编码与 cell_idx 错位,读错 upvalue。 + let mut names: Vec = names.into_iter().collect(); + names.sort(); + names + .into_iter() + .map(|name| { + let parent_uv_idx = parent_upvalues.iter().position(|u| u.name == name).map(|i| i as u8); + let cell_idx = parent_captured.get(&name).copied().unwrap_or(0); + UpvalueCapture { + name, + enclosing_reg: 0, // assemble_ir 时从父符号表填充 + cell_idx, + parent_uv_idx, + } + }) + .collect() +} diff --git a/crates/oxide_emit/src/closure.rs b/crates/oxide_emit/src/closure.rs deleted file mode 100644 index ac8c0bc9..00000000 --- a/crates/oxide_emit/src/closure.rs +++ /dev/null @@ -1,1383 +0,0 @@ -//! 闭包捕获分析(AST 级,emit 前完成,时序无关)。 -//! -//! 收集本函数绑定的名字(own_bindings)与被嵌套函数捕获的名字 -//! (captured_bindings → cell_idx,按名排序稳定跨 run),为 MAKE_CELL / -//! CELL_GET / CELL_SET 与子函数 upvalue cell_idx 提供统一依据。 - -use std::collections::{BTreeMap, HashSet}; - -use oxide_bytecode::module::UpvalueCapture; -use oxide_parser::{ClassBody, ClassElement, Expression, Statement, VariableDeclarationKind}; - -use crate::Emitter; - -impl Emitter { - fn collect_fn_param_names(&self, params: &oxide_parser::FormalParameters) -> HashSet { - let mut names = HashSet::new(); - for p in ¶ms.items { - self.collect_binding_pattern_names(&p.pattern, &mut names); - } - // rest 形参也是本函数作用域绑定,遮蔽外层同名变量。 - if let Some(rest) = ¶ms.rest { - self.collect_binding_pattern_names(&rest.rest.argument, &mut names); - } - names - } - - /// 递归收集 binding pattern 内全部绑定标识符名(解构 `[a, b]` / `{x: y}` 嵌套)。 - pub(crate) fn collect_binding_pattern_names( - &self, pattern: &oxide_parser::BindingPattern, out: &mut HashSet, - ) { - match pattern { - oxide_parser::BindingPattern::BindingIdentifier(bi) => { - out.insert(bi.name.to_string()); - } - oxide_parser::BindingPattern::ArrayPattern(ap) => { - for p in ap.elements.iter().flatten() { - self.collect_binding_pattern_names(p, out); - } - if let Some(rest) = &ap.rest { - self.collect_binding_pattern_names(&rest.argument, out); - } - } - oxide_parser::BindingPattern::ObjectPattern(op) => { - for prop in &op.properties { - self.collect_binding_pattern_names(&prop.value, out); - } - if let Some(rest) = &op.rest { - self.collect_binding_pattern_names(&rest.argument, out); - } - } - oxide_parser::BindingPattern::AssignmentPattern(ap) => { - self.collect_binding_pattern_names(&ap.left, out); - } - } - } - - /// 收集 for-in/for-of 头部声明(`var x` / 解构 pattern)绑定的名字。 - fn collect_for_left_decl_names(&self, left: &oxide_parser::ForStatementLeft, out: &mut HashSet) { - if let oxide_parser::ForStatementLeft::VariableDeclaration(vd) = left { - for d in &vd.declarations { - self.collect_binding_pattern_names(&d.id, out); - } - } - } - - /// 收集语句树中全部 `var` 声明名(var 提升到函数/程序作用域,递归进嵌套块)。 - /// 供函数/程序入口批量 MAKE_CELL(undefined) 使用(var 入口实例化语义)。 - pub(crate) fn collect_var_binding_names(&self, stmts: &[Statement]) -> HashSet { - let mut names = HashSet::new(); - self.collect_var_names_stmt(stmts, &mut names); - names - } - - fn collect_var_names_stmt(&self, stmts: &[Statement], out: &mut HashSet) { - for stmt in stmts { - match stmt { - Statement::VariableDeclaration(vd) => { - if matches!(vd.kind, VariableDeclarationKind::Var) { - for d in &vd.declarations { - self.collect_binding_pattern_names(&d.id, out); - } - } - } - Statement::BlockStatement(b) => self.collect_var_names_stmt(&b.body, out), - Statement::IfStatement(is) => { - self.collect_var_names_stmt(std::slice::from_ref(&is.consequent), out); - if let Some(alt) = &is.alternate { - self.collect_var_names_stmt(std::slice::from_ref(alt), out); - } - } - Statement::WhileStatement(w) => self.collect_var_names_stmt(std::slice::from_ref(&w.body), out), - Statement::DoWhileStatement(d) => self.collect_var_names_stmt(std::slice::from_ref(&d.body), out), - Statement::ForStatement(f) => { - if let Some(oxide_parser::ForStatementInit::VariableDeclaration(vd)) = &f.init { - if matches!(vd.kind, VariableDeclarationKind::Var) { - for d in &vd.declarations { - self.collect_binding_pattern_names(&d.id, out); - } - } - } - self.collect_var_names_stmt(std::slice::from_ref(&f.body), out); - } - Statement::ForInStatement(fi) => { - if let oxide_parser::ForStatementLeft::VariableDeclaration(vd) = &fi.left { - // 仅 var 头名提升到函数作用域,let/const 头名是迭代级绑定。 - if matches!(vd.kind, VariableDeclarationKind::Var) { - self.collect_for_left_decl_names(&fi.left, out); - } - } - self.collect_var_names_stmt(std::slice::from_ref(&fi.body), out); - } - Statement::ForOfStatement(fo) => { - if let oxide_parser::ForStatementLeft::VariableDeclaration(vd) = &fo.left { - // 仅 var 头名提升到函数作用域,let/const 头名是迭代级绑定。 - if matches!(vd.kind, VariableDeclarationKind::Var) { - self.collect_for_left_decl_names(&fo.left, out); - } - } - self.collect_var_names_stmt(std::slice::from_ref(&fo.body), out); - } - Statement::SwitchStatement(sw) => { - for case in &sw.cases { - self.collect_var_names_stmt(&case.consequent, out); - } - } - Statement::TryStatement(ts) => { - self.collect_var_names_stmt(&ts.block.body, out); - if let Some(h) = &ts.handler { - self.collect_var_names_stmt(&h.body.body, out); - } - if let Some(f) = &ts.finalizer { - self.collect_var_names_stmt(&f.body, out); - } - } - Statement::LabeledStatement(ls) => self.collect_var_names_stmt(std::slice::from_ref(&ls.body), out), - Statement::WithStatement(ws) => self.collect_var_names_stmt(std::slice::from_ref(&ws.body), out), - Statement::ExportNamedDeclaration(exp) => { - if let Some(oxide_parser::Declaration::VariableDeclaration(vd)) = &exp.declaration { - if matches!(vd.kind, VariableDeclarationKind::Var) { - for d in &vd.declarations { - self.collect_binding_pattern_names(&d.id, out); - } - } - } - } - _ => {} - } - } - } - - /// 收集语句列表**直接子级**函数声明的绑定名(顶层函数声明是全局 var 绑定, - /// 裸读/裸写与 var 名同路由全局对象属性)。不递归进块:块内函数声明是块 - /// 作用域,不参与全局对象同步;`export default function` 是 lexical 绑定,不纳。 - pub(crate) fn collect_top_level_function_names(&self, stmts: &[Statement]) -> HashSet { - let mut names = HashSet::new(); - for stmt in stmts { - if let Statement::FunctionDeclaration(fd) = stmt { - if let Some(id) = &fd.id { - names.insert(id.name.to_string()); - } - } - } - names - } - - /// 同 [`collect_top_level_function_names`] 的收集面,但按**声明序**返回 Vec - /// (供 GDI 检查阶段逆序遍历逐名去重,规范"逆序首见 = 源序最后声明")。 - pub(crate) fn collect_top_level_function_names_ordered(&self, stmts: &[Statement]) -> Vec { - let mut names = Vec::new(); - for stmt in stmts { - if let Statement::FunctionDeclaration(fd) = stmt { - if let Some(id) = &fd.id { - names.push(id.name.to_string()); - } - } - } - names - } - - /// 收集当前函数作用域声明的绑定名(参数 + 变量/函数声明,含嵌套 block,不含嵌套函数体)。 - pub(crate) fn collect_own_binding_names(&self, param_names: &[&str], stmts: &[Statement]) -> HashSet { - let mut names = HashSet::new(); - for p in param_names { - names.insert(p.to_string()); - } - self.collect_decl_names_stmt(stmts, &mut names); - names - } - - fn collect_decl_names_stmt(&self, stmts: &[Statement], out: &mut HashSet) { - for stmt in stmts { - match stmt { - Statement::VariableDeclaration(vd) => { - for d in &vd.declarations { - self.collect_binding_pattern_names(&d.id, out); - } - } - Statement::FunctionDeclaration(fd) => { - if let Some(id) = &fd.id { - out.insert(id.name.to_string()); - } - } - // class 名是本作用域 const 绑定:须计入 own_bindings,否则嵌套函数 - // 引用类名时捕获分析缺失 → 落符号表兜底(TDZ 误报或读父寄存器残留)。 - Statement::ClassDeclaration(cd) => { - if let Some(id) = &cd.id { - out.insert(id.name.to_string()); - } - } - // import 绑定是模块作用域 const 绑定,须计入 own_bindings 供 - // 嵌套函数 cell 捕获。 - Statement::ImportDeclaration(imp) => { - if let Some(specifiers) = &imp.specifiers { - for sp in specifiers { - match sp { - oxide_parser::ImportDeclarationSpecifier::ImportSpecifier(s) => { - out.insert(s.local.name.to_string()); - } - oxide_parser::ImportDeclarationSpecifier::ImportDefaultSpecifier(s) => { - out.insert(s.local.name.to_string()); - } - oxide_parser::ImportDeclarationSpecifier::ImportNamespaceSpecifier(s) => { - out.insert(s.local.name.to_string()); - } - } - } - } - } - Statement::ExportNamedDeclaration(exp) => { - if let Some(decl) = &exp.declaration { - match decl { - oxide_parser::Declaration::VariableDeclaration(vd) => { - for d in &vd.declarations { - self.collect_binding_pattern_names(&d.id, out); - } - } - oxide_parser::Declaration::FunctionDeclaration(fd) => { - if let Some(id) = &fd.id { - out.insert(id.name.to_string()); - } - } - oxide_parser::Declaration::ClassDeclaration(cd) => { - if let Some(id) = &cd.id { - out.insert(id.name.to_string()); - } - } - _ => {} - } - } - } - Statement::ExportDefaultDeclaration(exp) => match &exp.declaration { - oxide_parser::ExportDefaultDeclarationKind::FunctionDeclaration(fd) => { - if let Some(id) = &fd.id { - out.insert(id.name.to_string()); - } - } - oxide_parser::ExportDefaultDeclarationKind::ClassDeclaration(cd) => { - if let Some(id) = &cd.id { - out.insert(id.name.to_string()); - } - } - _ => {} - }, - Statement::BlockStatement(b) => self.collect_decl_names_stmt(&b.body, out), - Statement::IfStatement(is) => { - self.collect_decl_names_stmt(std::slice::from_ref(&is.consequent), out); - if let Some(alt) = &is.alternate { - self.collect_decl_names_stmt(std::slice::from_ref(alt), out); - } - } - Statement::WhileStatement(w) => self.collect_decl_names_stmt(std::slice::from_ref(&w.body), out), - Statement::DoWhileStatement(d) => self.collect_decl_names_stmt(std::slice::from_ref(&d.body), out), - Statement::ForStatement(f) => { - if let Some(oxide_parser::ForStatementInit::VariableDeclaration(vd)) = &f.init { - for d in &vd.declarations { - if let oxide_parser::BindingPattern::BindingIdentifier(bi) = &d.id { - out.insert(bi.name.to_string()); - } - } - } - self.collect_decl_names_stmt(std::slice::from_ref(&f.body), out); - } - // for-in / for-of 头部的 var 声明是本函数局部绑定(遮蔽外层同名), - // 须计入 own_bindings,否则闭包捕获分析会误判为捕获外层变量。 - Statement::ForInStatement(fi) => { - if let oxide_parser::ForStatementLeft::VariableDeclaration(_) = &fi.left { - self.collect_for_left_decl_names(&fi.left, out); - } - self.collect_decl_names_stmt(std::slice::from_ref(&fi.body), out); - } - Statement::ForOfStatement(fo) => { - if let oxide_parser::ForStatementLeft::VariableDeclaration(_) = &fo.left { - self.collect_for_left_decl_names(&fo.left, out); - } - self.collect_decl_names_stmt(std::slice::from_ref(&fo.body), out); - } - Statement::SwitchStatement(sw) => { - for case in &sw.cases { - self.collect_decl_names_stmt(&case.consequent, out); - } - } - Statement::TryStatement(ts) => { - self.collect_decl_names_stmt(&ts.block.body, out); - if let Some(h) = &ts.handler { - self.collect_decl_names_stmt(&h.body.body, out); - } - if let Some(f) = &ts.finalizer { - self.collect_decl_names_stmt(&f.body, out); - } - } - Statement::LabeledStatement(ls) => self.collect_decl_names_stmt(std::slice::from_ref(&ls.body), out), - Statement::WithStatement(ws) => self.collect_decl_names_stmt(std::slice::from_ref(&ws.body), out), - _ => {} - } - } - } - - fn collect_capture_names_shadowed( - &self, stmts: &[Statement], ref_set: &HashSet, shadow: &HashSet, out: &mut HashSet, - ) { - for stmt in stmts { - self.collect_capture_names_stmt(stmt, ref_set, shadow, out); - } - } - - fn collect_capture_names_stmt( - &self, stmt: &Statement, ref_set: &HashSet, shadow: &HashSet, out: &mut HashSet, - ) { - match stmt { - Statement::ExpressionStatement(es) => self.collect_capture_names_expr(&es.expression, ref_set, shadow, out), - Statement::ReturnStatement(rs) => { - if let Some(a) = &rs.argument { - self.collect_capture_names_expr(a, ref_set, shadow, out); - } - } - Statement::VariableDeclaration(vd) => { - for d in &vd.declarations { - // 绑定 pattern 的计算键是运行时求值表达式,其引用须纳入捕获。 - self.collect_capture_names_binding_keys(&d.id, ref_set, shadow, out); - if let Some(init) = &d.init { - self.collect_capture_names_expr(init, ref_set, shadow, out); - } - } - } - Statement::FunctionDeclaration(fd) => { - let body: &[Statement] = fd.body.as_ref().map(|b| &b.statements[..]).unwrap_or(&[]); - let mut inner = shadow.clone(); - inner.extend(self.collect_fn_param_names(&fd.params)); - inner.extend(self.collect_own_binding_names(&[], body)); - self.collect_fn_default_names(&fd.params, ref_set, shadow, out); - self.collect_capture_names_shadowed(body, ref_set, &inner, out); - } - Statement::ClassDeclaration(cd) => { - // 类体(构造器/方法体、字段键与值、静态块)是嵌套作用域: - // 类名遮蔽外层绑定,方法形参与方法体局部进一步遮蔽。 - let mut class_shadow = shadow.clone(); - if let Some(id) = &cd.id { - class_shadow.insert(id.name.as_str().to_string()); - } - self.collect_class_capture_names(&cd.body, ref_set, &class_shadow, out); - } - Statement::IfStatement(is) => { - self.collect_capture_names_expr(&is.test, ref_set, shadow, out); - self.collect_capture_names_stmt(&is.consequent, ref_set, shadow, out); - if let Some(alt) = &is.alternate { - self.collect_capture_names_stmt(alt, ref_set, shadow, out); - } - } - Statement::ForStatement(fs) => { - if let Some(init) = &fs.init { - if let Some(e) = init.as_expression() { - self.collect_capture_names_expr(e, ref_set, shadow, out); - } - if let oxide_parser::ForStatementInit::VariableDeclaration(vd) = init { - for d in &vd.declarations { - self.collect_capture_names_binding_keys(&d.id, ref_set, shadow, out); - if let Some(i) = &d.init { - self.collect_capture_names_expr(i, ref_set, shadow, out); - } - } - } - } - if let Some(t) = &fs.test { - self.collect_capture_names_expr(t, ref_set, shadow, out); - } - if let Some(u) = &fs.update { - self.collect_capture_names_expr(u, ref_set, shadow, out); - } - self.collect_capture_names_stmt(&fs.body, ref_set, shadow, out); - } - Statement::WhileStatement(w) => { - self.collect_capture_names_expr(&w.test, ref_set, shadow, out); - self.collect_capture_names_stmt(&w.body, ref_set, shadow, out); - } - Statement::DoWhileStatement(d) => { - self.collect_capture_names_stmt(&d.body, ref_set, shadow, out); - self.collect_capture_names_expr(&d.test, ref_set, shadow, out); - } - Statement::ForInStatement(fi) => { - self.collect_capture_names_expr(&fi.right, ref_set, shadow, out); - // left 的 var 声明遮蔽外层同名绑定,body 内引用不视为捕获外层。 - let mut for_shadow = shadow.clone(); - self.collect_for_left_decl_names(&fi.left, &mut for_shadow); - if let oxide_parser::ForStatementLeft::VariableDeclaration(vd) = &fi.left { - for d in &vd.declarations { - self.collect_capture_names_binding_keys(&d.id, ref_set, shadow, out); - } - } - self.collect_capture_names_shadowed(std::slice::from_ref(&fi.body), ref_set, &for_shadow, out); - } - Statement::ForOfStatement(fo) => { - self.collect_capture_names_expr(&fo.right, ref_set, shadow, out); - let mut for_shadow = shadow.clone(); - self.collect_for_left_decl_names(&fo.left, &mut for_shadow); - if let oxide_parser::ForStatementLeft::VariableDeclaration(vd) = &fo.left { - for d in &vd.declarations { - self.collect_capture_names_binding_keys(&d.id, ref_set, shadow, out); - } - } - self.collect_capture_names_shadowed(std::slice::from_ref(&fo.body), ref_set, &for_shadow, out); - } - Statement::BlockStatement(b) => self.collect_capture_names_shadowed(&b.body, ref_set, shadow, out), - Statement::TryStatement(ts) => { - for s in &ts.block.body { - 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, &catch_shadow, out); - } - } - if let Some(f) = &ts.finalizer { - for s in &f.body { - self.collect_capture_names_stmt(s, ref_set, shadow, out); - } - } - } - Statement::ExportNamedDeclaration(exp) => { - if let Some(decl) = &exp.declaration { - match decl { - oxide_parser::Declaration::VariableDeclaration(vd) => { - for d in &vd.declarations { - self.collect_capture_names_binding_keys(&d.id, ref_set, shadow, out); - if let Some(init) = &d.init { - self.collect_capture_names_expr(init, ref_set, shadow, out); - } - } - } - oxide_parser::Declaration::FunctionDeclaration(fd) => { - let body: &[Statement] = fd.body.as_ref().map(|b| &b.statements[..]).unwrap_or(&[]); - let mut inner = shadow.clone(); - inner.extend(self.collect_fn_param_names(&fd.params)); - inner.extend(self.collect_own_binding_names(&[], body)); - self.collect_fn_default_names(&fd.params, ref_set, shadow, out); - self.collect_capture_names_shadowed(body, ref_set, &inner, out); - } - oxide_parser::Declaration::ClassDeclaration(cd) => { - let mut class_shadow = shadow.clone(); - if let Some(id) = &cd.id { - class_shadow.insert(id.name.as_str().to_string()); - } - self.collect_class_capture_names(&cd.body, ref_set, &class_shadow, out); - } - _ => {} - } - } - } - Statement::ExportDefaultDeclaration(exp) => match &exp.declaration { - oxide_parser::ExportDefaultDeclarationKind::FunctionDeclaration(fd) => { - let body: &[Statement] = fd.body.as_ref().map(|b| &b.statements[..]).unwrap_or(&[]); - let mut inner = shadow.clone(); - inner.extend(self.collect_fn_param_names(&fd.params)); - inner.extend(self.collect_own_binding_names(&[], body)); - self.collect_fn_default_names(&fd.params, ref_set, shadow, out); - self.collect_capture_names_shadowed(body, ref_set, &inner, out); - } - oxide_parser::ExportDefaultDeclarationKind::ClassDeclaration(cd) => { - let mut class_shadow = shadow.clone(); - if let Some(id) = &cd.id { - class_shadow.insert(id.name.as_str().to_string()); - } - self.collect_class_capture_names(&cd.body, ref_set, &class_shadow, out); - } - other => { - if let Some(e) = other.as_expression() { - self.collect_capture_names_expr(e, ref_set, shadow, out); - } - } - }, - Statement::ThrowStatement(ts) => self.collect_capture_names_expr(&ts.argument, ref_set, shadow, out), - Statement::SwitchStatement(sw) => { - self.collect_capture_names_expr(&sw.discriminant, ref_set, shadow, out); - for case in &sw.cases { - for s in &case.consequent { - self.collect_capture_names_stmt(s, ref_set, shadow, out); - } - } - } - Statement::LabeledStatement(ls) => self.collect_capture_names_stmt(&ls.body, ref_set, shadow, out), - Statement::WithStatement(ws) => { - self.collect_capture_names_expr(&ws.object, ref_set, shadow, out); - self.collect_capture_names_stmt(&ws.body, ref_set, shadow, out); - } - _ => {} - } - } - - /// 收集类体对 `ref_set` 的引用:方法/构造器体、字段键与值、静态块。 - /// 方法形参与方法体局部声明遮蔽外层绑定(捕获判定用)。 - fn collect_class_capture_names( - &self, class_body: &ClassBody, ref_set: &HashSet, class_shadow: &HashSet, - out: &mut HashSet, - ) { - for element in &class_body.body { - match element { - ClassElement::MethodDefinition(method) => { - let mut inner = class_shadow.clone(); - inner.extend(self.collect_fn_param_names(&method.value.params)); - let body: &[Statement] = method.value.body.as_ref().map(|b| &b.statements[..]).unwrap_or(&[]); - inner.extend(self.collect_own_binding_names(&[], body)); - self.collect_fn_default_names(&method.value.params, ref_set, class_shadow, out); - self.collect_capture_names_shadowed(body, ref_set, &inner, out); - } - ClassElement::PropertyDefinition(prop) => { - if let Some(expr) = prop.key.as_expression() { - self.collect_capture_names_expr(expr, ref_set, class_shadow, out); - } - if let Some(value) = &prop.value { - self.collect_capture_names_expr(value, ref_set, class_shadow, out); - } - } - ClassElement::StaticBlock(block) => { - self.collect_capture_names_shadowed(&block.body, ref_set, class_shadow, out); - } - _ => {} - } - } - } - - /// 遍历 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 p in ap.elements.iter().flatten() { - 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 { - // 计算键是运行时求值表达式,其引用须纳入捕获。 - if prop.computed { - self.collect_capture_names_expr(prop.key.to_expression(), ref_set, shadow, out); - } - 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); - } - } - } - - /// 遍历绑定 pattern 的运行时求值表达式引用:计算键(`{[k]: a}` 的键)与内嵌 - /// 默认值(`{a = x}` 的 x)都是模式内求值的表达式,嵌套函数引用外层绑定时须 - /// 纳入捕获(与赋值侧/对象字面量/类字段键遍历同口径)。 - fn collect_capture_names_binding_keys( - &self, pattern: &oxide_parser::BindingPattern, ref_set: &HashSet, shadow: &HashSet, - out: &mut HashSet, - ) { - match pattern { - oxide_parser::BindingPattern::BindingIdentifier(_) => {} - oxide_parser::BindingPattern::ArrayPattern(ap) => { - for p in ap.elements.iter().flatten() { - self.collect_capture_names_binding_keys(p, ref_set, shadow, out); - } - if let Some(rest) = &ap.rest { - self.collect_capture_names_binding_keys(&rest.argument, ref_set, shadow, out); - } - } - oxide_parser::BindingPattern::ObjectPattern(op) => { - for prop in &op.properties { - if prop.computed { - self.collect_capture_names_expr(prop.key.to_expression(), ref_set, shadow, out); - } - self.collect_capture_names_binding_keys(&prop.value, ref_set, shadow, out); - } - if let Some(rest) = &op.rest { - self.collect_capture_names_binding_keys(&rest.argument, ref_set, shadow, out); - } - } - oxide_parser::BindingPattern::AssignmentPattern(ap) => { - // 内嵌默认值表达式引用外层绑定须捕获(与 binding_pattern/赋值侧 - // maybe_default 的 init 扫描同口径);left 继续递归模式键。 - self.collect_capture_names_expr(&ap.right, ref_set, shadow, out); - self.collect_capture_names_binding_keys(&ap.left, ref_set, shadow, out); - } - } - } - - /// 扫描赋值目标中的引用(标识符写名,成员目标扫对象/键,解构目标递归元素)。 - fn collect_capture_names_assign_target( - &self, target: &oxide_parser::AssignmentTarget, ref_set: &HashSet, shadow: &HashSet, - out: &mut HashSet, - ) { - match target { - oxide_parser::AssignmentTarget::AssignmentTargetIdentifier(ati) => { - let name = ati.name.as_str(); - if ref_set.contains(name) && !shadow.contains(name) { - out.insert(ati.name.to_string()); - } - } - oxide_parser::AssignmentTarget::StaticMemberExpression(m) => { - self.collect_capture_names_expr(&m.object, ref_set, shadow, out); - } - oxide_parser::AssignmentTarget::ComputedMemberExpression(m) => { - self.collect_capture_names_expr(&m.object, ref_set, shadow, out); - self.collect_capture_names_expr(&m.expression, ref_set, shadow, out); - } - oxide_parser::AssignmentTarget::ArrayAssignmentTarget(a) => { - for e in a.elements.iter().flatten() { - self.collect_capture_names_maybe_default_target(e, ref_set, shadow, out); - } - if let Some(rest) = &a.rest { - self.collect_capture_names_assign_target(&rest.target, ref_set, shadow, out); - } - } - oxide_parser::AssignmentTarget::ObjectAssignmentTarget(o) => { - for prop in &o.properties { - if let oxide_parser::AssignmentTargetProperty::AssignmentTargetPropertyIdentifier(id) = prop { - if ref_set.contains(id.binding.name.as_str()) && !shadow.contains(id.binding.name.as_str()) { - out.insert(id.binding.name.to_string()); - } - if let Some(init) = &id.init { - self.collect_capture_names_expr(init, ref_set, shadow, out); - } - } else if let oxide_parser::AssignmentTargetProperty::AssignmentTargetPropertyProperty(p) = prop { - if let Some(name_expr) = p.name.as_expression() { - self.collect_capture_names_expr(name_expr, ref_set, shadow, out); - } - self.collect_capture_names_maybe_default_target(&p.binding, ref_set, shadow, out); - } - } - if let Some(rest) = &o.rest { - self.collect_capture_names_assign_target(&rest.target, ref_set, shadow, out); - } - } - _ => {} - } - } - - /// 解构赋值元素可能是 `AssignmentTarget` 或带默认值的包装(后者多一层 `init`)。 - fn collect_capture_names_maybe_default_target( - &self, target: &oxide_parser::AssignmentTargetMaybeDefault, ref_set: &HashSet, - shadow: &HashSet, out: &mut HashSet, - ) { - use oxide_parser::AssignmentTargetMaybeDefault as MaybeDefault; - match target { - MaybeDefault::AssignmentTargetWithDefault(d) => { - self.collect_capture_names_expr(&d.init, ref_set, shadow, out); - self.collect_capture_names_assign_target(&d.binding, ref_set, shadow, out); - } - MaybeDefault::AssignmentTargetIdentifier(ati) => { - let name = ati.name.as_str(); - if ref_set.contains(name) && !shadow.contains(name) { - out.insert(ati.name.to_string()); - } - } - MaybeDefault::StaticMemberExpression(m) => { - self.collect_capture_names_expr(&m.object, ref_set, shadow, out); - } - MaybeDefault::ComputedMemberExpression(m) => { - self.collect_capture_names_expr(&m.object, ref_set, shadow, out); - self.collect_capture_names_expr(&m.expression, ref_set, shadow, out); - } - MaybeDefault::ArrayAssignmentTarget(a) => { - for e in a.elements.iter().flatten() { - self.collect_capture_names_maybe_default_target(e, ref_set, shadow, out); - } - } - MaybeDefault::ObjectAssignmentTarget(o) => { - for prop in &o.properties { - if let oxide_parser::AssignmentTargetProperty::AssignmentTargetPropertyIdentifier(id) = prop { - if ref_set.contains(id.binding.name.as_str()) && !shadow.contains(id.binding.name.as_str()) { - out.insert(id.binding.name.to_string()); - } - if let Some(init) = &id.init { - self.collect_capture_names_expr(init, ref_set, shadow, out); - } - } else if let oxide_parser::AssignmentTargetProperty::AssignmentTargetPropertyProperty(p) = prop { - if let Some(name_expr) = p.name.as_expression() { - self.collect_capture_names_expr(name_expr, ref_set, shadow, out); - } - self.collect_capture_names_maybe_default_target(&p.binding, ref_set, shadow, out); - } - } - } - _ => {} - } - } - - /// 扫描一元更新目标(`++x` / `obj.x++`)中的引用。 - fn collect_capture_names_simple_target( - &self, target: &oxide_parser::SimpleAssignmentTarget, ref_set: &HashSet, shadow: &HashSet, - out: &mut HashSet, - ) { - match target { - oxide_parser::SimpleAssignmentTarget::AssignmentTargetIdentifier(ati) => { - let name = ati.name.as_str(); - if ref_set.contains(name) && !shadow.contains(name) { - out.insert(ati.name.to_string()); - } - } - oxide_parser::SimpleAssignmentTarget::StaticMemberExpression(m) => { - self.collect_capture_names_expr(&m.object, ref_set, shadow, out); - } - oxide_parser::SimpleAssignmentTarget::ComputedMemberExpression(m) => { - self.collect_capture_names_expr(&m.object, ref_set, shadow, out); - self.collect_capture_names_expr(&m.expression, ref_set, shadow, out); - } - _ => {} - } - } - - /// 收集函数参数默认值表达式里的引用(子层 upvalue 判定;参数名遮蔽)。 - fn collect_fn_default_names( - &self, params: &oxide_parser::FormalParameters, ref_set: &HashSet, shadow: &HashSet, - out: &mut HashSet, - ) { - for p in ¶ms.items { - if let Some(init) = &p.initializer { - self.collect_capture_names_expr(init, ref_set, shadow, out); - } - let mut param_shadow = shadow.clone(); - self.collect_capture_names_binding_pattern(&p.pattern, ref_set, shadow, out, &mut param_shadow); - } - } - - fn collect_capture_names_expr( - &self, expr: &Expression, ref_set: &HashSet, shadow: &HashSet, out: &mut HashSet, - ) { - match expr { - Expression::Identifier(id) => { - let name = id.name.as_str(); - if ref_set.contains(name) && !shadow.contains(name) { - out.insert(id.name.to_string()); - } - } - Expression::AssignmentExpression(ae) => { - // 赋值目标里的引用也须捕获:标识符目标写名,成员/解构目标扫描其对象/元素。 - self.collect_capture_names_assign_target(&ae.left, ref_set, shadow, out); - self.collect_capture_names_expr(&ae.right, ref_set, shadow, out); - } - Expression::UpdateExpression(ue) => { - self.collect_capture_names_simple_target(&ue.argument, ref_set, shadow, out); - } - Expression::FunctionExpression(fe) => { - let body: &[Statement] = fe.body.as_ref().map(|b| &b.statements[..]).unwrap_or(&[]); - let mut inner = shadow.clone(); - inner.extend(self.collect_fn_param_names(&fe.params)); - inner.extend(self.collect_own_binding_names(&[], body)); - self.collect_fn_default_names(&fe.params, ref_set, shadow, out); - self.collect_capture_names_shadowed(body, ref_set, &inner, out); - } - Expression::ArrowFunctionExpression(ae) => { - let mut inner = shadow.clone(); - inner.extend(self.collect_fn_param_names(&ae.params)); - inner.extend(self.collect_own_binding_names(&[], &ae.body.statements)); - self.collect_fn_default_names(&ae.params, ref_set, shadow, out); - self.collect_capture_names_shadowed(&ae.body.statements, ref_set, &inner, out); - } - Expression::ClassExpression(class) => { - // 类表达式:方法/构造器体与字段表达式是嵌套作用域,引用须捕获。 - let mut class_shadow = shadow.clone(); - if let Some(id) = &class.id { - class_shadow.insert(id.name.as_str().to_string()); - } - self.collect_class_capture_names(&class.body, ref_set, &class_shadow, out); - } - Expression::BinaryExpression(be) => { - self.collect_capture_names_expr(&be.left, ref_set, shadow, out); - self.collect_capture_names_expr(&be.right, ref_set, shadow, out); - } - Expression::UnaryExpression(ue) => self.collect_capture_names_expr(&ue.argument, ref_set, shadow, out), - Expression::CallExpression(ce) => { - self.collect_capture_names_expr(&ce.callee, ref_set, shadow, out); - for a in &ce.arguments { - self.collect_capture_names_arg(a, ref_set, shadow, out); - } - } - Expression::NewExpression(ne) => { - self.collect_capture_names_expr(&ne.callee, ref_set, shadow, out); - for a in &ne.arguments { - self.collect_capture_names_arg(a, ref_set, shadow, out); - } - } - Expression::SequenceExpression(se) => { - for e in &se.expressions { - self.collect_capture_names_expr(e, ref_set, shadow, out); - } - } - Expression::ConditionalExpression(ce) => { - self.collect_capture_names_expr(&ce.test, ref_set, shadow, out); - self.collect_capture_names_expr(&ce.consequent, ref_set, shadow, out); - self.collect_capture_names_expr(&ce.alternate, ref_set, shadow, out); - } - Expression::ArrayExpression(ae) => { - for e in &ae.elements { - if let Some(e) = e.as_expression() { - self.collect_capture_names_expr(e, ref_set, shadow, out); - } - } - } - Expression::LogicalExpression(le) => { - self.collect_capture_names_expr(&le.left, ref_set, shadow, out); - self.collect_capture_names_expr(&le.right, ref_set, shadow, out); - } - Expression::ComputedMemberExpression(m) => { - self.collect_capture_names_expr(&m.object, ref_set, shadow, out); - self.collect_capture_names_expr(&m.expression, ref_set, shadow, out); - } - Expression::StaticMemberExpression(m) => self.collect_capture_names_expr(&m.object, ref_set, shadow, out), - Expression::PrivateFieldExpression(m) => self.collect_capture_names_expr(&m.object, ref_set, shadow, out), - Expression::ParenthesizedExpression(p) => { - self.collect_capture_names_expr(&p.expression, ref_set, shadow, out) - } - Expression::TemplateLiteral(tl) => { - for e in &tl.expressions { - self.collect_capture_names_expr(e, ref_set, shadow, out); - } - } - Expression::TaggedTemplateExpression(tt) => { - self.collect_capture_names_expr(&tt.tag, ref_set, shadow, out); - for e in &tt.quasi.expressions { - self.collect_capture_names_expr(e, ref_set, shadow, out); - } - } - Expression::ObjectExpression(o) => { - for prop in &o.properties { - match prop { - oxide_parser::ObjectPropertyKind::ObjectProperty(p) => { - if p.computed { - self.collect_capture_names_expr(p.key.to_expression(), ref_set, shadow, out); - } - self.collect_capture_names_expr(&p.value, ref_set, shadow, out); - } - oxide_parser::ObjectPropertyKind::SpreadProperty(spread) => { - self.collect_capture_names_expr(&spread.argument, ref_set, shadow, out); - } - } - } - } - // 生成器让出表达式:被让出的值里引用的父变量须纳入捕获,否则生成器体经 - // LOAD_VAR 读调用方寄存器残留(挂起恢复后寄存器已被覆盖)。 - Expression::YieldExpression(ye) => { - if let Some(a) = &ye.argument { - self.collect_capture_names_expr(a, ref_set, shadow, out); - } - } - // await 表达式:被等待的值里引用的父变量须纳入捕获(与 yield 同因—— - // 异步体挂起恢复后寄存器已被覆盖,只能经 cell 读取)。 - Expression::AwaitExpression(ae) => { - self.collect_capture_names_expr(&ae.argument, ref_set, shadow, out); - } - Expression::ChainExpression(c) => self.collect_capture_names_chain(&c.expression, ref_set, shadow, out), - _ => {} - } - } - - fn collect_capture_names_chain( - &self, element: &oxide_parser::ChainElement, ref_set: &HashSet, shadow: &HashSet, - out: &mut HashSet, - ) { - match element { - oxide_parser::ChainElement::StaticMemberExpression(m) => { - self.collect_capture_names_expr(&m.object, ref_set, shadow, out); - } - oxide_parser::ChainElement::ComputedMemberExpression(m) => { - self.collect_capture_names_expr(&m.object, ref_set, shadow, out); - self.collect_capture_names_expr(&m.expression, ref_set, shadow, out); - } - oxide_parser::ChainElement::PrivateFieldExpression(m) => { - self.collect_capture_names_expr(&m.object, ref_set, shadow, out); - } - oxide_parser::ChainElement::CallExpression(call) => { - self.collect_capture_names_expr(&call.callee, ref_set, shadow, out); - for a in &call.arguments { - self.collect_capture_names_arg(a, ref_set, shadow, out); - } - } - _ => {} - } - } - - /// 遍历调用实参:静态实参与 spread 内部表达式都纳入捕获扫描。 - fn collect_capture_names_arg( - &self, arg: &oxide_parser::Argument, ref_set: &HashSet, shadow: &HashSet, - out: &mut HashSet, - ) { - if let Some(e) = arg.as_expression() { - self.collect_capture_names_expr(e, ref_set, shadow, out); - } else if let oxide_parser::Argument::SpreadElement(sp) = arg { - self.collect_capture_names_expr(&sp.argument, ref_set, shadow, out); - } - } - - /// 分析本函数:哪些绑定被任意深度嵌套函数捕获 → captured_bindings。 - pub(crate) fn collect_captured_bindings( - &self, stmts: &[Statement], extra_exprs: &[&oxide_parser::Expression], own: &HashSet, - ) -> BTreeMap { - let mut names = HashSet::new(); - for stmt in stmts { - self.collect_captured_stmt(stmt, own, &mut names); - } - // 参数默认值表达式(不在 body_stmts 内)里的嵌套函数引用也要纳入捕获, - // 否则默认值内 IIFE 引用全局/外层变量走 LOAD_VAR 读寄存器残留(B022 扩展)。 - for expr in extra_exprs { - self.collect_captured_expr(expr, own, &mut names); - } - // 名字排序分配 cell_idx(稳定跨 run,父 MAKE_CELL 与子 upvalue 统一引用) - let mut sorted: Vec = names.into_iter().collect(); - sorted.sort(); - sorted.into_iter().enumerate().map(|(i, n)| (n, i as u8)).collect() - } - - /// 收集函数参数默认值表达式里的嵌套函数引用(父层 captured/子层 upvalue 判定)。 - fn collect_fn_default_captured( - &self, params: &oxide_parser::FormalParameters, own: &HashSet, out: &mut HashSet, - ) { - let empty_shadow = HashSet::new(); - for p in ¶ms.items { - if let Some(init) = &p.initializer { - self.collect_capture_names_expr(init, own, &empty_shadow, out); - } - // 形参模式的运行时求值表达式(计算键/内嵌默认值)在子作用域求值, - // 其标识符引用须纳入父层 MAKE_CELL 判定。 - self.collect_captured_pattern_runtime_exprs(&p.pattern, own, out); - } - } - - /// 遍历绑定 pattern 内全部运行时求值表达式(计算键与 AssignmentPattern 默认值): - /// 这些表达式在子作用域(嵌套函数形参绑定时)求值,引用的父层绑定须建 cell 供 - /// 子函数 upvalue 读取——与 `collect_capture_names_expr` 同口径(标识符比对)。 - fn collect_captured_pattern_runtime_exprs( - &self, pattern: &oxide_parser::BindingPattern, own: &HashSet, out: &mut HashSet, - ) { - let empty_shadow = HashSet::new(); - match pattern { - oxide_parser::BindingPattern::BindingIdentifier(_) => {} - oxide_parser::BindingPattern::ArrayPattern(ap) => { - for p in ap.elements.iter().flatten() { - self.collect_captured_pattern_runtime_exprs(p, own, out); - } - if let Some(rest) = &ap.rest { - self.collect_captured_pattern_runtime_exprs(&rest.argument, own, out); - } - } - oxide_parser::BindingPattern::ObjectPattern(op) => { - for prop in &op.properties { - if prop.computed { - self.collect_capture_names_expr(prop.key.to_expression(), own, &empty_shadow, out); - } - self.collect_captured_pattern_runtime_exprs(&prop.value, own, out); - } - if let Some(rest) = &op.rest { - self.collect_captured_pattern_runtime_exprs(&rest.argument, own, out); - } - } - oxide_parser::BindingPattern::AssignmentPattern(ap) => { - self.collect_capture_names_expr(&ap.right, own, &empty_shadow, out); - self.collect_captured_pattern_runtime_exprs(&ap.left, own, out); - } - } - } - - /// 只从嵌套函数节点进入扫描(本函数直接引用不算捕获)。 - 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_fn_default_captured(&fd.params, own, out); - // 函数参数与体内部声明遮蔽父级绑定:体内对这些名字的引用不算捕获父级。 - let mut fn_shadow = HashSet::new(); - fn_shadow.extend(self.collect_fn_param_names(&fd.params)); - fn_shadow.extend(self.collect_own_binding_names(&[], body)); - self.collect_capture_names_shadowed(body, own, &fn_shadow, out); - } - Statement::ClassDeclaration(cd) => { - // 类构造器/方法体与字段表达式引用的父级绑定须建 cell,供子模块 upvalue 捕获。 - let mut class_shadow = HashSet::new(); - if let Some(id) = &cd.id { - class_shadow.insert(id.name.as_str().to_string()); - } - self.collect_class_capture_names(&cd.body, own, &class_shadow, out); - } - Statement::ExpressionStatement(es) => self.collect_captured_expr(&es.expression, own, out), - Statement::ReturnStatement(rs) => { - if let Some(a) = &rs.argument { - self.collect_captured_expr(a, own, out); - } - } - Statement::VariableDeclaration(vd) => { - for d in &vd.declarations { - // 绑定 pattern 的计算键是运行时求值表达式,其引用须纳入捕获判定。 - self.collect_captured_binding_keys(&d.id, own, out); - if let Some(init) = &d.init { - self.collect_captured_expr(init, own, out); - } - } - } - Statement::IfStatement(is) => { - self.collect_captured_expr(&is.test, own, out); - self.collect_captured_stmt(&is.consequent, own, out); - if let Some(alt) = &is.alternate { - self.collect_captured_stmt(alt, own, out); - } - } - Statement::ForStatement(fs) => { - if let Some(init) = &fs.init { - if let Some(e) = init.as_expression() { - self.collect_captured_expr(e, own, out); - } - if let oxide_parser::ForStatementInit::VariableDeclaration(vd) = init { - for d in &vd.declarations { - self.collect_captured_binding_keys(&d.id, own, out); - if let Some(i) = &d.init { - self.collect_captured_expr(i, own, out); - } - } - } - } - if let Some(t) = &fs.test { - self.collect_captured_expr(t, own, out); - } - if let Some(u) = &fs.update { - self.collect_captured_expr(u, own, out); - } - self.collect_captured_stmt(&fs.body, own, out); - } - Statement::WhileStatement(w) => { - self.collect_captured_expr(&w.test, own, out); - self.collect_captured_stmt(&w.body, own, out); - } - Statement::DoWhileStatement(d) => { - self.collect_captured_stmt(&d.body, own, out); - self.collect_captured_expr(&d.test, own, out); - } - Statement::ForInStatement(fi) => { - self.collect_captured_expr(&fi.right, own, out); - if let oxide_parser::ForStatementLeft::VariableDeclaration(vd) = &fi.left { - for d in &vd.declarations { - self.collect_captured_binding_keys(&d.id, own, out); - } - } - self.collect_captured_stmt(&fi.body, own, out); - } - Statement::ForOfStatement(fo) => { - self.collect_captured_expr(&fo.right, own, out); - if let oxide_parser::ForStatementLeft::VariableDeclaration(vd) = &fo.left { - for d in &vd.declarations { - self.collect_captured_binding_keys(&d.id, own, out); - } - } - self.collect_captured_stmt(&fo.body, own, out); - } - Statement::BlockStatement(b) => { - for s in &b.body { - self.collect_captured_stmt(s, own, out); - } - } - Statement::TryStatement(ts) => { - for s in &ts.block.body { - 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); - } - } - if let Some(f) = &ts.finalizer { - for s in &f.body { - self.collect_captured_stmt(s, own, out); - } - } - } - Statement::ThrowStatement(ts) => self.collect_captured_expr(&ts.argument, own, out), - Statement::SwitchStatement(sw) => { - self.collect_captured_expr(&sw.discriminant, own, out); - for case in &sw.cases { - for s in &case.consequent { - self.collect_captured_stmt(s, own, out); - } - } - } - Statement::LabeledStatement(ls) => self.collect_captured_stmt(&ls.body, own, out), - Statement::WithStatement(ws) => { - self.collect_captured_expr(&ws.object, own, out); - self.collect_captured_stmt(&ws.body, own, out); - } - _ => {} - } - } - - /// 遍历 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 p in ap.elements.iter().flatten() { - 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 { - // 计算键表达式(本作用域 catch 参数求值,含 IIFE 等嵌套函数)引用 - // 本函数绑定走寄存器,只须扫描键内嵌套函数表达式。 - if prop.computed { - self.collect_captured_expr(prop.key.to_expression(), own, out); - } - 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); - } - } - } - - /// 遍历绑定 pattern 的运行时求值表达式引用:计算键(`{[k]: a}` 的键)与内嵌 - /// 默认值(`{a = x}` 的 x),供父层捕获判定(声明语句/for 头的模式与 catch/ - /// 默认值路径同口径)。 - fn collect_captured_binding_keys( - &self, pattern: &oxide_parser::BindingPattern, own: &HashSet, out: &mut HashSet, - ) { - match pattern { - oxide_parser::BindingPattern::BindingIdentifier(_) => {} - oxide_parser::BindingPattern::ArrayPattern(ap) => { - for p in ap.elements.iter().flatten() { - self.collect_captured_binding_keys(p, own, out); - } - if let Some(rest) = &ap.rest { - self.collect_captured_binding_keys(&rest.argument, own, out); - } - } - oxide_parser::BindingPattern::ObjectPattern(op) => { - for prop in &op.properties { - if prop.computed { - self.collect_captured_expr(prop.key.to_expression(), own, out); - } - self.collect_captured_binding_keys(&prop.value, own, out); - } - if let Some(rest) = &op.rest { - self.collect_captured_binding_keys(&rest.argument, own, out); - } - } - oxide_parser::BindingPattern::AssignmentPattern(ap) => { - // 内嵌默认值表达式引用外层绑定须建 cell(与 captured_binding_pattern - // 同口径);left 继续递归模式键。 - self.collect_captured_expr(&ap.right, own, out); - self.collect_captured_binding_keys(&ap.left, own, out); - } - } - } - - fn collect_captured_expr(&self, expr: &Expression, own: &HashSet, out: &mut HashSet) { - match expr { - Expression::FunctionExpression(fe) => { - let body: &[Statement] = fe.body.as_ref().map(|b| &b.statements[..]).unwrap_or(&[]); - let mut inner = self.collect_fn_param_names(&fe.params); - inner.extend(self.collect_own_binding_names(&[], body)); - self.collect_fn_default_captured(&fe.params, own, out); - self.collect_capture_names_shadowed(body, own, &inner, out); - } - Expression::ArrowFunctionExpression(ae) => { - let mut inner = self.collect_fn_param_names(&ae.params); - inner.extend(self.collect_own_binding_names(&[], &ae.body.statements)); - self.collect_fn_default_captured(&ae.params, own, out); - self.collect_capture_names_shadowed(&ae.body.statements, own, &inner, out); - } - Expression::ClassExpression(class) => { - // 类表达式:构造器/方法体与字段表达式引用的父级绑定须建 cell。 - let mut class_shadow = HashSet::new(); - if let Some(id) = &class.id { - class_shadow.insert(id.name.as_str().to_string()); - } - self.collect_class_capture_names(&class.body, own, &class_shadow, out); - } - Expression::CallExpression(ce) => { - self.collect_captured_expr(&ce.callee, own, out); - for a in &ce.arguments { - self.collect_captured_arg(a, own, out); - } - } - Expression::BinaryExpression(be) => { - self.collect_captured_expr(&be.left, own, out); - self.collect_captured_expr(&be.right, own, out); - } - Expression::UnaryExpression(ue) => self.collect_captured_expr(&ue.argument, own, out), - Expression::LogicalExpression(le) => { - self.collect_captured_expr(&le.left, own, out); - self.collect_captured_expr(&le.right, own, out); - } - Expression::ConditionalExpression(ce) => { - self.collect_captured_expr(&ce.test, own, out); - self.collect_captured_expr(&ce.consequent, own, out); - self.collect_captured_expr(&ce.alternate, own, out); - } - Expression::SequenceExpression(se) => { - for e in &se.expressions { - self.collect_captured_expr(e, own, out); - } - } - Expression::AssignmentExpression(ae) => { - // 只扫右侧:左侧赋值目标是本函数绑定,不引用嵌套函数; - // 若目标含嵌套函数表达式(如 `[f()] = ...`),由其自身递归处理。 - self.collect_captured_expr(&ae.right, own, out); - } - Expression::UpdateExpression(_ue) => {} // 一元更新目标不引用嵌套函数,无需捕获 - Expression::ArrayExpression(ae) => { - for e in &ae.elements { - if let Some(e) = e.as_expression() { - self.collect_captured_expr(e, own, out); - } - } - } - Expression::ObjectExpression(o) => { - for prop in &o.properties { - match prop { - oxide_parser::ObjectPropertyKind::ObjectProperty(p) => { - if p.computed { - self.collect_captured_expr(p.key.to_expression(), own, out); - } - self.collect_captured_expr(&p.value, own, out); - } - oxide_parser::ObjectPropertyKind::SpreadProperty(spread) => { - self.collect_captured_expr(&spread.argument, own, out); - } - } - } - } - Expression::NewExpression(ne) => { - self.collect_captured_expr(&ne.callee, own, out); - for a in &ne.arguments { - self.collect_captured_arg(a, own, out); - } - } - Expression::ComputedMemberExpression(m) => { - self.collect_captured_expr(&m.object, own, out); - self.collect_captured_expr(&m.expression, own, out); - } - Expression::StaticMemberExpression(m) => self.collect_captured_expr(&m.object, own, out), - Expression::PrivateFieldExpression(m) => self.collect_captured_expr(&m.object, own, out), - Expression::TemplateLiteral(tl) => { - for e in &tl.expressions { - self.collect_captured_expr(e, own, out); - } - } - Expression::TaggedTemplateExpression(tt) => { - self.collect_captured_expr(&tt.tag, own, out); - for e in &tt.quasi.expressions { - self.collect_captured_expr(e, own, out); - } - } - Expression::ParenthesizedExpression(p) => self.collect_captured_expr(&p.expression, own, out), - Expression::YieldExpression(ye) => { - if let Some(a) = &ye.argument { - self.collect_captured_expr(a, own, out); - } - } - Expression::AwaitExpression(ae) => self.collect_captured_expr(&ae.argument, own, out), - Expression::ChainExpression(c) => self.collect_captured_chain(&c.expression, own, out), - _ => {} - } - } - - fn collect_captured_chain( - &self, element: &oxide_parser::ChainElement, own: &HashSet, out: &mut HashSet, - ) { - match element { - oxide_parser::ChainElement::StaticMemberExpression(m) => { - self.collect_captured_expr(&m.object, own, out); - } - oxide_parser::ChainElement::ComputedMemberExpression(m) => { - self.collect_captured_expr(&m.object, own, out); - self.collect_captured_expr(&m.expression, own, out); - } - oxide_parser::ChainElement::PrivateFieldExpression(m) => { - self.collect_captured_expr(&m.object, own, out); - } - oxide_parser::ChainElement::CallExpression(c) => { - self.collect_captured_expr(&c.callee, own, out); - for a in &c.arguments { - self.collect_captured_arg(a, own, out); - } - } - _ => {} - } - } - - /// 遍历调用实参:静态实参与 spread 内部表达式都纳入捕获判定。 - fn collect_captured_arg(&self, arg: &oxide_parser::Argument, own: &HashSet, out: &mut HashSet) { - if let Some(e) = arg.as_expression() { - self.collect_captured_expr(e, own, out); - } else if let oxide_parser::Argument::SpreadElement(sp) = arg { - self.collect_captured_expr(&sp.argument, own, out); - } - } - - /// 分析子函数 body:引用父级被捕获绑定的名字 → upvalue_captures。 - /// 名字若在父 `captured_bindings`(父 own cell)则 `cell_idx` 索引定义方表; - /// 若在父 `upvalue_captures`(父自身从更外层捕获)则链式标记 `parent_uv_idx`, - /// 运行时从父闭包 upvalues 取 cell。enclosing_reg 由父 emit 完成后填充。 - pub(crate) fn collect_upvalue_names( - &self, body_stmts: &[Statement], extra_exprs: &[&oxide_parser::Expression], - parent_captured: &BTreeMap, parent_upvalues: &[UpvalueCapture], sub_own: &HashSet, - ) -> Vec { - let mut parent_names: HashSet = parent_captured.keys().cloned().collect(); - for u in parent_upvalues { - parent_names.insert(u.name.clone()); - } - let mut names = HashSet::new(); - self.collect_capture_names_shadowed(body_stmts, &parent_names, sub_own, &mut names); - // 参数默认值表达式(不在 body_stmts)里的嵌套函数引用也会捕获父变量。 - for expr in extra_exprs { - self.collect_capture_names_expr(expr, &parent_names, sub_own, &mut names); - } - // HashSet 迭代序带随机种子(进程级非确定),必须排序使 upvalue_captures 的顺序与 - // 父 captured_bindings 的 cell_idx(BTreeMap 名字序)对齐——否则 LOAD_UPVALUE 的 - // a 槽 uv_idx 编码与 cell_idx 错位,读错 upvalue。 - let mut names: Vec = names.into_iter().collect(); - names.sort(); - names - .into_iter() - .map(|name| { - let parent_uv_idx = parent_upvalues.iter().position(|u| u.name == name).map(|i| i as u8); - let cell_idx = parent_captured.get(&name).copied().unwrap_or(0); - UpvalueCapture { - name, - enclosing_reg: 0, // assemble_ir 时从父符号表填充 - cell_idx, - parent_uv_idx, - } - }) - .collect() - } -} diff --git a/crates/oxide_emit/src/function_body.rs b/crates/oxide_emit/src/function_body.rs index 490538cd..e6d5c17e 100644 --- a/crates/oxide_emit/src/function_body.rs +++ b/crates/oxide_emit/src/function_body.rs @@ -2,7 +2,7 @@ //! (参数 prologue、参数默认值与闭包捕获分析、双 sub-pass 语句发射)。 //! //! 两类型经 lib.rs 重导出供各语法域构造实参;编译链为 `Emitter` 方法, -//! 捕获分析经 `self.*` 调用 closure 族,与所在文件无关。 +//! 捕获分析经自由函数调用 capture 族,与所在文件无关。 use std::collections::HashSet; @@ -13,6 +13,10 @@ use oxide_ir::operand::{LabelId, Operand}; use oxide_ir::IRFunction; use oxide_parser::{Expression, Statement, VariableDeclarationKind}; +use crate::capture::{ + collect_binding_pattern_names, collect_captured_bindings, collect_own_binding_names, collect_upvalue_names, + collect_var_binding_names, +}; use crate::compile_ctx::{CompileCtx, FieldBuffer}; use crate::symbol_table::{Binding, ScopeKind}; use crate::Emitter; @@ -299,7 +303,7 @@ impl Emitter { for spec in param_specs { param_names.insert(spec.register_name().to_string()); if let ParamSpec::Pattern { pattern, .. } = spec { - self.collect_binding_pattern_names(pattern, &mut param_names); + collect_binding_pattern_names(pattern, &mut param_names); } } ctx.param_names = param_names; @@ -527,10 +531,10 @@ impl Emitter { ParamSpec::Rest { .. } => {} } } - ctx.own_bindings = self.collect_own_binding_names(¶m_names, body_stmts); + ctx.own_bindings = collect_own_binding_names(¶m_names, body_stmts); for spec in param_specs { if let ParamSpec::Pattern { pattern, .. } = spec { - self.collect_binding_pattern_names(pattern, &mut ctx.own_bindings); + collect_binding_pattern_names(pattern, &mut ctx.own_bindings); } } @@ -548,13 +552,13 @@ impl Emitter { // 字段初始化表达式(值表达式)与参数默认值一并纳入捕获分析。 let mut capture_exprs: Vec<&oxide_parser::Expression> = param_defaults.clone(); capture_exprs.extend_from_slice(extra_capture_exprs); - ctx.captured_bindings = self.collect_captured_bindings(body_stmts, &capture_exprs, &ctx.own_bindings); + ctx.captured_bindings = collect_captured_bindings(body_stmts, &capture_exprs, &ctx.own_bindings); // 自由变量分析:收集 upvalue 捕获(类方法也是普通函数,可捕获外层变量)。 if matches!( body_context, FunctionBodyContext::Ordinary | FunctionBodyContext::Arrow | FunctionBodyContext::ClassElement ) { - ctx.current_upvalue_captures = self.collect_upvalue_names( + ctx.current_upvalue_captures = collect_upvalue_names( body_stmts, &capture_exprs, &parent_ctx.captured_bindings, @@ -659,8 +663,7 @@ impl Emitter { // 只是赋值;否则声明语句前创建的闭包读取占位 cell → TDZ 误报。参数与 // arguments 已在上方初始化(跳过以免覆盖参数值);let/const/class 保持 // TDZ 语义不动。声明语句的 MAKE_CELL 按占位更新语义覆盖此初值。 - let var_names: Vec = self - .collect_var_binding_names(body_stmts) + let var_names: Vec = collect_var_binding_names(body_stmts) .into_iter() .filter(|n| !param_names.contains(&n.as_str()) && n != "arguments") .filter(|n| ctx.captured_bindings.contains_key(n)) diff --git a/crates/oxide_emit/src/lib.rs b/crates/oxide_emit/src/lib.rs index 058be711..64f11463 100644 --- a/crates/oxide_emit/src/lib.rs +++ b/crates/oxide_emit/src/lib.rs @@ -5,8 +5,8 @@ //! `oxide_ir::lower` 降为 bytecode。语法按域拆分:`expr/`、`stmt/`、`class/`、 //! `shared/`;作用域与闭包捕获分析在 emit 前完成,消除符号表时序依赖。 +mod capture; pub mod class; -pub mod closure; mod compile_ctx; pub mod emit; pub mod emit_ctx; diff --git a/crates/oxide_emit/src/module.rs b/crates/oxide_emit/src/module.rs index 7b7e05e7..cb87df4d 100644 --- a/crates/oxide_emit/src/module.rs +++ b/crates/oxide_emit/src/module.rs @@ -7,6 +7,7 @@ use std::collections::HashSet; use std::path::Path; +use crate::capture::{collect_captured_bindings, collect_own_binding_names}; use crate::expr::call::pack_arg_regs; use crate::{CompileCtx, Emitter}; use oxc_allocator::Box; @@ -171,8 +172,8 @@ impl Emitter { let _ = self.predeclare_lexical_declarations(body, ctx, false); // 闭包捕获分析(import 绑定名纳入 own_bindings,供嵌套函数 cell 捕获)。 - ctx.own_bindings = self.collect_own_binding_names(&[], body); - ctx.captured_bindings = self.collect_captured_bindings(body, &[], &ctx.own_bindings); + ctx.own_bindings = collect_own_binding_names(&[], body); + ctx.captured_bindings = collect_captured_bindings(body, &[], &ctx.own_bindings); // —— 模块命名空间对象 —— let ns_reg = self.emit_module_call(ctx, "__moduleObject", &[])?; diff --git a/crates/oxide_emit/src/prepass/block_fn.rs b/crates/oxide_emit/src/prepass/block_fn.rs index e52e93ec..cb00a671 100644 --- a/crates/oxide_emit/src/prepass/block_fn.rs +++ b/crates/oxide_emit/src/prepass/block_fn.rs @@ -4,6 +4,7 @@ use std::collections::HashSet; +use crate::capture::collect_binding_pattern_names; use crate::Emitter; use oxide_parser::{Declaration, Statement, VariableDeclarationKind}; @@ -98,7 +99,7 @@ impl Emitter { Statement::VariableDeclaration(vd) => { if !matches!(vd.kind, VariableDeclarationKind::Var) { for d in &vd.declarations { - self.collect_binding_pattern_names(&d.id, names); + collect_binding_pattern_names(&d.id, names); } } } @@ -111,7 +112,7 @@ impl Emitter { if let Some(oxide_parser::ForStatementInit::VariableDeclaration(decl)) = &fs.init { if !matches!(decl.kind, VariableDeclarationKind::Var) { for d in &decl.declarations { - self.collect_binding_pattern_names(&d.id, names); + collect_binding_pattern_names(&d.id, names); } } } @@ -121,7 +122,7 @@ impl Emitter { if let oxide_parser::ForStatementLeft::VariableDeclaration(decl) = &fi.left { if !matches!(decl.kind, VariableDeclarationKind::Var) { for d in &decl.declarations { - self.collect_binding_pattern_names(&d.id, names); + collect_binding_pattern_names(&d.id, names); } } } @@ -131,7 +132,7 @@ impl Emitter { if let oxide_parser::ForStatementLeft::VariableDeclaration(decl) = &fo.left { if !matches!(decl.kind, VariableDeclarationKind::Var) { for d in &decl.declarations { - self.collect_binding_pattern_names(&d.id, names); + collect_binding_pattern_names(&d.id, names); } } } @@ -141,7 +142,7 @@ impl Emitter { // catch 参数是 handler 环境的词法绑定。 if let Some(handler) = &ts.handler { if let Some(param) = &handler.param { - self.collect_binding_pattern_names(¶m.pattern, names); + collect_binding_pattern_names(¶m.pattern, names); } self.collect_lexical_name_suppressions(&handler.body.body, names); } @@ -178,7 +179,7 @@ impl Emitter { if let Some(Declaration::VariableDeclaration(vd)) = &exp.declaration { if !matches!(vd.kind, VariableDeclarationKind::Var) { for d in &vd.declarations { - self.collect_binding_pattern_names(&d.id, names); + collect_binding_pattern_names(&d.id, names); } } } diff --git a/crates/oxide_emit/src/program.rs b/crates/oxide_emit/src/program.rs index e61b365a..6d2da9eb 100644 --- a/crates/oxide_emit/src/program.rs +++ b/crates/oxide_emit/src/program.rs @@ -16,6 +16,10 @@ use oxide_ir::operand::Operand; use oxide_ir::IRFunction; use oxide_parser::Statement; +use crate::capture::{ + collect_captured_bindings, collect_own_binding_names, collect_top_level_function_names, + collect_top_level_function_names_ordered, collect_var_binding_names, +}; use crate::compile_ctx::CompileCtx; use crate::Emitter; @@ -220,7 +224,7 @@ impl Emitter { /// - 仅遍历语句列表直接子级具名函数声明(生成器/异步声明同节点类型,天然 /// 覆盖);块内函数声明与 `export default function` 不入全局检查面。 pub(crate) fn emit_gdi_func_decl_checks(&self, stmts: &[Statement], ctx: &mut CompileCtx) { - let names = self.collect_top_level_function_names_ordered(stmts); + let names = collect_top_level_function_names_ordered(stmts); let mut seen = HashSet::new(); for name in names.iter().rev() { // 逆序首见即源序最后声明者(规范去重口径),重名只查一次。 @@ -262,7 +266,7 @@ impl Emitter { // 严格 eval 代码函数声明绑定 eval 自身 lexical 环境、不触全局、不抛,门禁 // 随 !is_strict 关闭,其写点抑制在声明发射处。 if ctx.is_eval_script && !ctx.is_strict { - for name in self.collect_top_level_function_names(&program.body) { + for name in collect_top_level_function_names(&program.body) { if NON_WRITABLE_GLOBAL_BUILTINS.contains(&name.as_str()) { let _ = self.emit_throw_error( "TypeError", @@ -312,15 +316,15 @@ impl Emitter { } // 闭包捕获分析(AST 级,emit 前确定) - ctx.own_bindings = self.collect_own_binding_names(&[], &program.body); + ctx.own_bindings = collect_own_binding_names(&[], &program.body); // 顶层已声明名(A 侧单一真值):裸读走全局对象属性、裸写走描述符感知 // A 侧写,不落镜像 cell——从捕获集剔除,使嵌套函数经继承 scope-0 直连全局。 // 集 = 顶层 var 名 ∪ 顶层函数声明名:函数值是编译闭包,编译期不可得, // 其 A 侧值由首 sub-pass 以真闭包建立,先于任何用户代码。 // 仅在此顶层调用点过滤:嵌套函数的局部同名遮蔽是独立绑定,其调用点不过滤。 - let var_names = self.collect_var_binding_names(&program.body); + let var_names = collect_var_binding_names(&program.body); let mut tier_names = var_names.clone(); - tier_names.extend(self.collect_top_level_function_names(&program.body)); + tier_names.extend(collect_top_level_function_names(&program.body)); // 块级函数泄漏名并入:求值期写回与头写同走全局对象属性(A 侧单一真值)。 for name in &block_fn_names { if !ctx.block_fn_suppressed.contains(name) && !CompileCtx::is_non_writable_global_builtin(name) { @@ -328,7 +332,7 @@ impl Emitter { } } ctx.global_tier_names = tier_names; - ctx.captured_bindings = self.collect_captured_bindings(&program.body, &[], &ctx.own_bindings); + ctx.captured_bindings = collect_captured_bindings(&program.body, &[], &ctx.own_bindings); ctx.captured_bindings.retain(|n, _| !ctx.global_tier_names.contains(n)); // 顶层 var 入口实例化:被捕获的 var 名统一 MAKE_CELL(undefined),使 var @@ -364,7 +368,7 @@ impl Emitter { // 预载全局属性值),既有属性零动作,值幂等保留。 // 序言名集 = 顶层 var 名 ∪ 顶层块级函数泄漏名(web-compat 外层绑定同样 // 在求值前实例化,同走 define-if-absent)。 - let mut gdi_var_names = self.collect_var_binding_names(&program.body); + let mut gdi_var_names = collect_var_binding_names(&program.body); gdi_var_names.extend( block_fn_names .iter() diff --git a/crates/oxide_emit/src/stmt/iteration/for_in.rs b/crates/oxide_emit/src/stmt/iteration/for_in.rs index 1518f329..04145537 100644 --- a/crates/oxide_emit/src/stmt/iteration/for_in.rs +++ b/crates/oxide_emit/src/stmt/iteration/for_in.rs @@ -6,6 +6,7 @@ use std::collections::HashSet; +use crate::capture::collect_binding_pattern_names; use crate::{CompileCtx, Emitter}; use oxide_bytecode::opcode::OpCode; use oxide_ir::inst::Inst; @@ -30,7 +31,7 @@ impl Emitter { } let mut names = HashSet::new(); for d in &decl.declarations { - self.collect_binding_pattern_names(&d.id, &mut names); + collect_binding_pattern_names(&d.id, &mut names); } let mut v: Vec = names.into_iter().collect(); v.sort();