mirror of
https://github.com/pjh456/OxideJS.git
synced 2026-10-23 18:21:13 +08:00
docs: 统一循环与声明写点的注释措辞
This commit is contained in:
@@ -109,10 +109,13 @@ impl Emitter {
|
||||
// 脚本顶层 var:同步写全局对象,使 globalThis.x 反射声明值。
|
||||
if ctx.is_global_scope && matches!(kind, VariableDeclarationKind::Var) {
|
||||
if CompileCtx::is_known_builtin(name) {
|
||||
// builtin 名保持 GDI 零动作写点(序言镜像值语义),不扩 strict 面。
|
||||
// 内置名保持 GlobalDeclarationInstantiation(脚本顶层声明实例化)
|
||||
// 序言的零动作写点——属性已存在时不改动值、仅缺失时新建;槽内保留
|
||||
// 求值开始前预载的全局属性值(镜像值),本路径不扩大 strict 抛错面。
|
||||
self.emit_global_prop_write(name, src_reg, ctx);
|
||||
} else {
|
||||
// 用户名既有属性面:声明带初始化是 PutValue,0x98 带 strict 分派。
|
||||
// 用户名的既有属性面:声明带初始化是 PutValue 语义,经
|
||||
// `DEFINE_GLOBAL_PROP_C`(`0x98`)并带 strict 分派。
|
||||
self.emit_global_put_write(name, src_reg, ctx);
|
||||
}
|
||||
}
|
||||
@@ -149,7 +152,7 @@ impl Emitter {
|
||||
return Ok(());
|
||||
}
|
||||
if is_tier {
|
||||
// 顶层已声明 var 解构赋值目标:值落全局对象属性(A 侧单一真值)。
|
||||
// 顶层已声明 var 解构赋值目标:值写入全局对象属性——顶层 var 值的唯一存储是全局对象属性,引擎侧不另存副本。
|
||||
self.emit_tier_global_write(name, src_reg, ctx);
|
||||
return Ok(());
|
||||
}
|
||||
@@ -360,7 +363,7 @@ impl Emitter {
|
||||
return Ok(());
|
||||
}
|
||||
if is_tier {
|
||||
// 顶层已声明 var 解构赋值目标:值落全局对象属性(A 侧单一真值)。
|
||||
// 顶层已声明 var 解构赋值目标:值写入全局对象属性——顶层 var 值的唯一存储是全局对象属性,引擎侧不另存副本。
|
||||
self.emit_tier_global_write(name, src_reg, ctx);
|
||||
return Ok(());
|
||||
}
|
||||
@@ -453,7 +456,7 @@ impl Emitter {
|
||||
return Ok(());
|
||||
}
|
||||
if is_tier {
|
||||
// 顶层已声明 var 对象解构赋值:值落全局对象属性(A 侧单一真值)。
|
||||
// 顶层已声明 var 解构赋值目标:值写入全局对象属性——顶层 var 值的唯一存储是全局对象属性,引擎侧不另存副本。
|
||||
self.emit_tier_global_write(name, prop_reg, ctx);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -49,12 +49,16 @@ impl Emitter {
|
||||
} else {
|
||||
self.materialize_function_declaration(fd, &name, ctx)?
|
||||
};
|
||||
// 块内函数声明求值写回外层 var 绑定(sloppy web-compat):预声明期为该
|
||||
// 名实例化的外层 var 绑定(函数作用域)在此写入块槽位里的函数对象,
|
||||
// 求值一次写回一次(循环体内每迭代覆写头绑定)。形参/词法声明同名
|
||||
// (抑制集)与顶层只读三常量名不写回(对不可写属性 put 在 sloppy 下
|
||||
// 永不成功,跳过与执行等价);顶层 A 侧补全局对象属性写(与 for 头写
|
||||
// 同形)。
|
||||
// 块内函数声明求值后按三种情形处理:
|
||||
//
|
||||
// sloppy 模式下按浏览器/web 实现惯例为块级函数声明建外层 var 绑定并写回:
|
||||
// 预声明期为该名实例化的函数作用域 var 绑定在此写入块槽位里的函数对象,
|
||||
// 求值一次写回一次(循环体内每迭代覆写头绑定)。
|
||||
//
|
||||
// 形参或函数作用域树内同名词法声明(抑制集)不写回:该名被同名声明遮蔽。
|
||||
//
|
||||
// 顶层不可写内置名不写回:sloppy 下对其赋值(put)永不成功,跳过与执行等价;
|
||||
// 顶层情形另补全局对象属性写(与 for-in 循环头的顶层写同形)。
|
||||
if !ctx.is_strict
|
||||
&& ctx.scopes.symbols.scopes.len() > 1
|
||||
&& !ctx.block_fn_suppressed.contains(&name)
|
||||
@@ -68,10 +72,10 @@ impl Emitter {
|
||||
Operand::Reg(var_reg),
|
||||
Operand::None,
|
||||
));
|
||||
// 顶层 A 侧同步写以外层绑定是否落全局作用域为准:此处块内
|
||||
// Let 绑定已占内层作用域,按名解析(is_global_tier_name)会
|
||||
// 命中块绑定误判为非顶层;嵌套函数作用域同名局部 var 不在
|
||||
// 全局 ctx 上,经 is_global_scope 门禁不走全局对象写。
|
||||
// 全局对象属性写以「外层绑定的作用域层级是否为 0(全局作用域)」判定,
|
||||
// 不按名字解析:此处块内 Let 绑定已占内层作用域,按名解析
|
||||
// (`is_global_tier_name`)会命中块绑定误判为非顶层;嵌套函数作用域
|
||||
// 的同名局部 var 不在全局 ctx 上,经 `is_global_scope` 门禁不走全局对象写。
|
||||
if ctx.is_global_scope && var_target == 0 && ctx.global_tier_names.contains(&name) {
|
||||
self.emit_tier_global_write(&name, var_reg, ctx);
|
||||
}
|
||||
@@ -79,8 +83,9 @@ impl Emitter {
|
||||
}
|
||||
// 脚本顶层(非块内)函数声明:同步写全局对象,使 globalThis 可反射函数名。
|
||||
// 块内声明不走本臂(其全局可见性只经上方外层 var 写回面建立)。
|
||||
// 严格 eval 代码函数声明绑定 eval 自身 lexical 环境、不落全局对象:抑制 A
|
||||
// 侧写(局部绑定读面未暴露),同时避免不可写全局内置在 0x98 上误抛 strict。
|
||||
// 严格 eval 代码的函数声明绑定 eval 自身词法环境、不落全局对象:抑制全局对象属性写
|
||||
// (局部绑定读面未暴露),同时避免不可写全局内置名在 `DEFINE_GLOBAL_PROP_C`(`0x98`,
|
||||
// 严格 eval 路径经此指令)上误抛 strict `TypeError`。
|
||||
if ctx.is_global_scope && ctx.scopes.symbols.scopes.len() == 1 && !(ctx.is_eval_script && ctx.is_strict) {
|
||||
self.emit_global_func_bind_write(&name, var_reg, ctx);
|
||||
}
|
||||
|
||||
@@ -44,8 +44,9 @@ impl Emitter {
|
||||
let n_labeled = ctx.take_pending_loop_labels(end_label, update_label);
|
||||
// 循环头声明中被嵌套函数捕获的 let/const 绑定:每迭代 fresh cell。
|
||||
let mut fresh_bindings: Vec<(String, u8)> = Vec::new();
|
||||
// 循环头 let/const 声明名:update 段是 per-iteration 可变绑定
|
||||
// (规范 §14.7.4.4 CreatePerIterationEnvironment 用 CreateMutableBinding),
|
||||
// 循环头 let/const 声明名:update 段是 per-iteration 可变绑定(规范
|
||||
// §14.7.4.4 CreatePerIterationEnvironment 用 CreateMutableBinding)——
|
||||
// 规范允许 update 段写 let/const 循环变量,每迭代新建一个可变绑定;
|
||||
// 编译期 const 写检查对 update 段豁免,故记录全部声明名(含未被捕获者)。
|
||||
let mut update_names: Vec<String> = Vec::new();
|
||||
if let Some(init) = &fr.init {
|
||||
@@ -137,9 +138,10 @@ impl Emitter {
|
||||
let body_result = self.emit_statement(&fr.body, ctx)?;
|
||||
ctx.labels.set_label_pos(update_label, ctx.insts.len());
|
||||
if let Some(update) = &fr.update {
|
||||
// update 段写寄存器(而非 cell):被捕获的 let/const 循环变量每迭代 fresh,
|
||||
// update 写寄存器供下一迭代 fresh 拷贝——否则 CELL_SET 会污染本迭代闭包
|
||||
// 捕获的 cell。未捕获者本就走寄存器,一并登记以豁免 update 段的 const 检查。
|
||||
// update 段写循环变量寄存器、不写 cell:被捕获的 let/const 循环变量每迭代
|
||||
// 新分配 cell,寄存器值供其拷入(否则 CELL_SET 会污染本迭代闭包捕获的
|
||||
// cell);未捕获者本就走寄存器,一并登记以豁免 update 段的 const 检查。
|
||||
// 机制见 `compile_ctx.rs` 的 `register_update_names` 字段文档。
|
||||
let prev = std::mem::take(&mut ctx.register_update_names);
|
||||
ctx.register_update_names = update_names;
|
||||
self.emit_expression(update, ctx)?;
|
||||
|
||||
@@ -58,8 +58,9 @@ impl Emitter {
|
||||
let tdz_idx = next;
|
||||
next = next.saturating_add(1);
|
||||
ctx.captured_bindings.insert(name.clone(), tdz_idx);
|
||||
// 未初始化标志走 b 槽:a 槽 Imm 的高字节会覆写 b 槽,故标志并入
|
||||
// 立即数高字节,dispatch 侧按 a/b 分槽取回。
|
||||
// MAKE_CELL 的 16 位立即数:低字节是 cell 索引,高字节 bit 0 是
|
||||
// 未初始化标记。标志折入立即数高字节(0x0100),dispatch 侧按字节
|
||||
// 拆回两字段。
|
||||
let undef_reg = self.emit_undefined(ctx);
|
||||
ctx.inst(Inst::new(
|
||||
OpCode::MAKE_CELL,
|
||||
@@ -73,8 +74,8 @@ impl Emitter {
|
||||
}
|
||||
|
||||
/// 右值区求值完毕后把覆盖从 TDZ cell 切到体区 fresh cell:每头名分配新
|
||||
/// cell 并改写映射,头发射捕获臂与体区读/捕获自然命中(每迭代
|
||||
/// MAKE_CELL_FRESH 建新 cell,本迭代闭包捕获新 cell)。
|
||||
/// cell 并改写映射,头发射捕获臂与体区读/捕获自然命中。每迭代新分配一个
|
||||
/// cell;机制见 `compile_ctx.rs` 的 `register_update_names` 字段文档。
|
||||
pub(crate) fn switch_for_head_env_to_body(&self, env: &mut ForHeadEnv, ctx: &mut CompileCtx) {
|
||||
let mut next = ctx.captured_bindings.values().copied().max().map_or(0, |m| m.saturating_add(1));
|
||||
for (name, _, _, body_idx) in &mut env.entries {
|
||||
@@ -140,9 +141,9 @@ impl Emitter {
|
||||
let is_const = matches!(decl.kind, VariableDeclarationKind::Const);
|
||||
let name = bi.name.as_str();
|
||||
let var_reg = ctx.alloc_reg();
|
||||
// var 声明:绑定已存在(顶层 var 预声明、GDI 序言预登记
|
||||
// builtin 名、同 scope 先前声明)时复用既有槽位,不重复
|
||||
// 声明;let/const 同 scope 重复声明仍报错。
|
||||
// var 声明:绑定已存在(顶层 var 预声明、
|
||||
// GlobalDeclarationInstantiation(脚本顶层声明实例化)序言预登记的内置名、
|
||||
// 同 scope 先前声明)时复用既有槽位,不重复声明;let/const 同 scope 重复声明仍报错。
|
||||
let target_reg = if matches!(decl.kind, VariableDeclarationKind::Var) {
|
||||
match ctx.declare(name, var_reg, decl.kind, is_const) {
|
||||
Ok(()) => var_reg,
|
||||
@@ -173,9 +174,9 @@ impl Emitter {
|
||||
Operand::Reg(key_reg),
|
||||
Operand::None,
|
||||
));
|
||||
// 顶层 for-in var 头:迭代值落全局对象属性(A 侧单一真值)。
|
||||
// 只读三常量已在上方拦截臂跳过;其余 builtin 名属性可写,
|
||||
// 迭代键照规范覆写既有全局属性。
|
||||
// 顶层 for-in var 头:迭代值写入全局对象属性——顶层 var 值的唯一存储是全局对象属性,引擎侧不另存副本。
|
||||
// 只读三常量(不可写全局内置)已在上方拦截臂跳过;其余内置名属性
|
||||
// 可写,迭代键照规范覆写既有全局属性。
|
||||
if self.is_global_tier_name(ctx, name) {
|
||||
self.emit_tier_global_write(name, key_reg, ctx);
|
||||
}
|
||||
@@ -203,9 +204,8 @@ impl Emitter {
|
||||
// 严格模式未声明写:抛 ReferenceError,跳过寄存器写(值无关)。
|
||||
self.emit_strict_undeclared_write(name, ctx)?;
|
||||
} else if is_tier {
|
||||
// 顶层 for-in 赋值头:迭代值落全局对象属性(A 侧单一真值)。
|
||||
// 只读三常量已在上方拦截臂跳过;其余 builtin 名属性可写,
|
||||
// 迭代键照规范覆写既有全局属性。
|
||||
// 顶层 for-in 赋值头:迭代值写入全局对象属性——顶层 var 值的唯一存储是全局对象属性,引擎侧不另存副本。
|
||||
// 同上:只读三常量已在拦截臂跳过,其余内置名属性可写。
|
||||
self.emit_tier_global_write(name, key_reg, ctx);
|
||||
} else {
|
||||
ctx.inst(Inst::new(
|
||||
|
||||
Reference in New Issue
Block a user