fix: 被捕获词法绑定入口建 TDZ 占位 cell 并跳过陈旧静态守卫

This commit is contained in:
2026-09-20 09:08:44 +00:00
parent 9a502e634a
commit 1433d47329
7 changed files with 438 additions and 4 deletions
+29 -2
View File
@@ -14,8 +14,8 @@ 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,
collect_binding_pattern_names, collect_captured_bindings, collect_direct_lexical_names, collect_own_binding_names,
collect_upvalue_names, collect_var_binding_names,
};
use crate::compile_ctx::{CompileCtx, FieldBuffer};
use crate::symbol_table::{Binding, ScopeKind};
@@ -783,6 +783,33 @@ impl Emitter {
}
}
// 被捕获函数作用域词法(let/const/class)入口 TDZ 占位 cell:函数声明
// hoisting 先于声明语句执行时,闭包指向此未初始化 cell,声明前读写经
// 运行时抛真 TDZ;声明语句的 MAKE_CELL 按占位更新语义原位翻转。名集只取
// 直接子级(块级名不提升到函数作用域,与块内重执行 cell 族零交集),
// 排序保证发射序跨进程稳定。
let mut lex_names: Vec<String> = collect_direct_lexical_names(body_stmts)
.into_iter()
.filter(|n| !param_names.contains(&n.as_str()) && n != "arguments")
.filter(|n| ctx.captured_bindings.contains_key(n))
.collect();
lex_names.sort();
if !lex_names.is_empty() {
let undef_reg = self.emit_undefined(ctx);
for name in lex_names {
if let Some(&cell_idx) = ctx.captured_bindings.get(&name) {
// 未初始化标志折入 16 位立即数高字节(0x0100),dispatch 侧
// 按字节拆回两字段。
ctx.inst(Inst::new(
OpCode::MAKE_CELL,
Operand::Reg(undef_reg),
Operand::Imm(cell_idx as u16 | 0x0100),
Operand::None,
));
}
}
}
Ok(param_base)
}