feat: with 语句、成员位/移位复合赋值、CALL_NATIVE 无目标修复

with 语句:新增 emit 支持,with 体内自由标识符动态解析(对象属性优先,
回退外层),支持读/写/复合赋值/自增自减/delete/var 初始化动态化,
TO_OBJECT opcode 处理原始值对象,顶层 this 绑定全局对象。

复合赋值:新增 6 个 COMPOUND_MEMBER_BIT_* opcode 支持成员位/移位复合赋值,
修复 computed member 复合赋值覆盖 bug,with 内标识符复合赋值动态化。

CALL_NATIVE:实现全局 isNaN/isFinite 并绑定,用户覆盖 builtin 名时
回退通用调用路径而非报错,局部遮蔽 builtin 名走普通 CALL。

test262: with 34 pass(基线 0),compound-assignment 320 pass(基线 223)
This commit is contained in:
2026-08-09 07:22:46 +08:00
parent 826d9fd0a2
commit 5611d90ad0
23 changed files with 829 additions and 137 deletions
+40
View File
@@ -175,6 +175,9 @@ pub struct CompileCtx {
/// 消除符号表时序依赖与 cell 索引错位。
pub(crate) captured_bindings: BTreeMap<String, u8>,
pub(crate) const_overflow: bool,
/// with 语句作用域栈:元素为 (with 对象寄存器, 打开时的作用域深度)。
/// 非空时 with 体内的自由标识符需动态解析(先查对象属性,回退外层)。
pub(crate) with_stack: Vec<(u32, usize)>,
}
/// 函数体编译上下文:决定 `this`/`super` 绑定与参数前导(prologue)形态。
@@ -255,6 +258,7 @@ impl CompileCtx {
own_bindings: HashSet::new(),
captured_bindings: BTreeMap::new(),
const_overflow: false,
with_stack: Vec::new(),
}
}
@@ -475,10 +479,45 @@ impl CompileCtx {
self.scopes.builtin_reg_map.iter().any(|(n, _)| n == name)
}
/// 内置名是否被局部声明遮蔽(`var parseInt = ...` 等)。
/// builtin_reg_map 记录的是全局内置槽;若该名在静态作用域另有绑定,则调用应解析局部。
pub(crate) fn is_local_shadowing_builtin(&self, name: &str) -> bool {
if let Some(reg) = self.scopes.symbols.lookup_any(name) {
let is_builtin_slot = self.scopes.builtin_reg_map.iter().any(|(n, r)| n == name && *r == reg);
return !is_builtin_slot;
}
false
}
pub(crate) fn is_known_builtin(name: &str) -> bool {
BUILTIN_GLOBALS.contains(&name)
}
/// 进入 with 语句体:记录对象寄存器与当前作用域深度,供动态标识符解析。
pub(crate) fn push_with(&mut self, obj_reg: u32) {
let depth = self.scopes.symbols.scopes.len();
self.with_stack.push((obj_reg, depth));
}
/// 离开 with 语句体。
pub(crate) fn pop_with(&mut self) {
self.with_stack.pop();
}
/// 最内层 with 对象寄存器;无 with 时为 None。
pub(crate) fn innermost_with_obj(&self) -> Option<u32> {
self.with_stack.last().map(|&(reg, _)| reg)
}
/// 指定名字是否在 with 语句体**内**(with 打开之后的块作用域)声明。
/// with 内声明优先于对象属性;with 之前的外层声明被对象遮蔽。
pub(crate) fn is_with_internal_binding(&self, name: &str) -> bool {
let Some(&(_, depth)) = self.with_stack.last() else {
return false;
};
matches!(self.scopes.symbols.lookup_any_binding(name), Some((_, idx)) if idx >= depth)
}
fn builtin_reg_floor(&self) -> u32 {
self.scopes
.builtin_reg_map
@@ -945,6 +984,7 @@ impl Emitter {
Statement::BreakStatement(b) => self.emit_break_statement(b, ctx),
Statement::ContinueStatement(c) => self.emit_continue_statement(c, ctx),
Statement::LabeledStatement(ls) => self.emit_labeled_statement(ls, ctx),
Statement::WithStatement(_) => self.emit_with_domain(stmt, ctx),
_ => Ok(None),
}
}