fix: 绑定侧解构计算键参与闭包捕获遍历防静默错值

This commit is contained in:
2026-08-16 14:30:20 +08:00
parent 7de55b25d8
commit 84f84402ba
5 changed files with 306 additions and 10 deletions
+47
View File
@@ -22,6 +22,7 @@ impl Emitter {
Statement::ExpressionStatement(es) => self.pre_scan_builtin_expr(&es.expression, ctx),
Statement::VariableDeclaration(vd) => {
for d in &vd.declarations {
self.pre_scan_builtin_pattern(&d.id, ctx);
if let Some(init) = &d.init {
self.pre_scan_builtin_expr(init, ctx);
}
@@ -53,6 +54,7 @@ impl Emitter {
self.pre_scan_builtin_expr(e, ctx);
} else if let oxide_parser::ForStatementInit::VariableDeclaration(decl) = init {
for d in &decl.declarations {
self.pre_scan_builtin_pattern(&d.id, ctx);
if let Some(init_expr) = &d.init {
self.pre_scan_builtin_expr(init_expr, ctx);
}
@@ -68,10 +70,20 @@ impl Emitter {
self.pre_scan_builtin_stmt(&fs.body, ctx);
}
Statement::ForInStatement(fi) => {
if let oxide_parser::ForStatementLeft::VariableDeclaration(vd) = &fi.left {
for d in &vd.declarations {
self.pre_scan_builtin_pattern(&d.id, ctx);
}
}
self.pre_scan_builtin_expr(&fi.right, ctx);
self.pre_scan_builtin_stmt(&fi.body, ctx);
}
Statement::ForOfStatement(fo) => {
if let oxide_parser::ForStatementLeft::VariableDeclaration(vd) = &fo.left {
for d in &vd.declarations {
self.pre_scan_builtin_pattern(&d.id, ctx);
}
}
self.pre_scan_builtin_expr(&fo.right, ctx);
self.pre_scan_builtin_stmt(&fo.body, ctx);
}
@@ -94,6 +106,9 @@ impl Emitter {
self.pre_scan_builtin_stmt(s, ctx);
}
if let Some(handler) = &ts.handler {
if let Some(param) = &handler.param {
self.pre_scan_builtin_pattern(&param.pattern, ctx);
}
for s in &handler.body.body {
self.pre_scan_builtin_stmt(s, ctx);
}
@@ -122,6 +137,7 @@ impl Emitter {
Statement::ExportNamedDeclaration(exp) => {
if let Some(Declaration::VariableDeclaration(vd)) = &exp.declaration {
for d in &vd.declarations {
self.pre_scan_builtin_pattern(&d.id, ctx);
if let Some(init) = &d.init {
self.pre_scan_builtin_expr(init, ctx);
}
@@ -297,6 +313,37 @@ impl Emitter {
}
}
/// 遍历绑定 pattern 的计算键表达式(`{[k]: a}` 的键)里的 builtin 引用:
/// 模式键是运行时求值表达式,键内 builtin 标识符须预先登记固定槽位
/// (与对象字面量计算键预扫描同口径)。
fn pre_scan_builtin_pattern(&self, pattern: &BindingPattern, ctx: &mut CompileCtx) {
match pattern {
BindingPattern::BindingIdentifier(_) => {}
BindingPattern::ArrayPattern(ap) => {
for e in ap.elements.iter().flatten() {
self.pre_scan_builtin_pattern(e, ctx);
}
if let Some(rest) = &ap.rest {
self.pre_scan_builtin_pattern(&rest.argument, ctx);
}
}
BindingPattern::ObjectPattern(op) => {
for prop in &op.properties {
if prop.computed {
self.pre_scan_builtin_expr(prop.key.to_expression(), ctx);
}
self.pre_scan_builtin_pattern(&prop.value, ctx);
}
if let Some(rest) = &op.rest {
self.pre_scan_builtin_pattern(&rest.argument, ctx);
}
}
BindingPattern::AssignmentPattern(ap) => {
self.pre_scan_builtin_pattern(&ap.left, ctx);
}
}
}
pub(crate) fn predeclare_function_declarations(&self, statements: &[Statement], ctx: &mut CompileCtx) {
for statement in statements {
let function = match statement {