fix: 顶层 var 声明带初始化撞不可写全局用户属性 strict 抛 TypeError——用户名声明处写点改 session 解析 PutValue 语义,builtin 名保 GDI 写点;序言缺失分支全局不可扩展两模式对齐抛 TypeError

This commit is contained in:
2026-09-12 21:36:10 +00:00
parent 60274baca8
commit bf08803071
5 changed files with 201 additions and 5 deletions
+14
View File
@@ -1586,6 +1586,20 @@ impl Emitter {
}
}
/// 顶层 var 声明带初始化的 A 侧同步:PutValue 语义——既有不可写数据属性
/// strict 抛 TypeError / sloppy 静默 no-op;可写照原描述符仅更值。脚本与
/// eval 均经 session 解析全局对象,不依赖顶层 this。
///
/// # 边界与前提
/// - 仅顶层模块上下文调用;builtin 名不走本写点(保持 GDI 零动作写点)。
///
/// # 副作用
/// - 更新全局对象数据属性,失败面抛 TypeError(strict 不可写)。
pub(crate) fn emit_global_put_write(&self, name: &str, val_reg: u32, ctx: &mut CompileCtx) {
let idx = ctx.add_constant(Constant::String(name.to_string()));
ctx.inst(Inst::define_global_prop_c(Operand::Reg(val_reg), idx));
}
/// 名字是否为顶层已声明 var(A 侧单一真值):在顶层 var 名集内,且当前解析
/// 绑定落在全局作用域(scope 0)——嵌套函数内的局部同名遮蔽命中更高作用域,
/// 判定为局部而非顶层,走既有 cell/寄存器路径。
+7 -1
View File
@@ -108,7 +108,13 @@ impl Emitter {
ctx.init_var(name);
// 脚本顶层 var:同步写全局对象,使 globalThis.x 反射声明值。
if ctx.is_global_scope && matches!(kind, VariableDeclarationKind::Var) {
self.emit_global_prop_write(name, src_reg, ctx);
if CompileCtx::is_known_builtin(name) {
// builtin 名保持 GDI 零动作写点(序言镜像值语义),不扩 strict 面。
self.emit_global_prop_write(name, src_reg, ctx);
} else {
// 用户名既有属性面:声明带初始化是 PutValue,0x98 带 strict 分派。
self.emit_global_put_write(name, src_reg, ctx);
}
}
// REPL 持久模式:let/const 也写全局对象属性,使跨轮次读取可见。
if ctx.repl_persist && ctx.is_global_scope && !matches!(kind, VariableDeclarationKind::Var) {