diff --git a/Cargo.lock b/Cargo.lock index b982358b..cef2cdad 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1160,7 +1160,7 @@ dependencies = [ [[package]] name = "oxide_builtins" -version = "0.21.0" +version = "0.21.1" dependencies = [ "chrono", "fast-float", @@ -1185,7 +1185,7 @@ dependencies = [ [[package]] name = "oxide_bytecode" -version = "0.21.0" +version = "0.21.1" dependencies = [ "num-bigint", "oxide_log", @@ -1193,7 +1193,7 @@ dependencies = [ [[package]] name = "oxide_cfg" -version = "0.21.0" +version = "0.21.1" dependencies = [ "oxide_bytecode", "oxide_emit", @@ -1204,7 +1204,7 @@ dependencies = [ [[package]] name = "oxide_cli" -version = "0.21.0" +version = "0.21.1" dependencies = [ "ansi_term", "bumpalo", @@ -1228,7 +1228,7 @@ dependencies = [ [[package]] name = "oxide_code_cache" -version = "0.21.0" +version = "0.21.1" dependencies = [ "lru", "oxide_bytecode", @@ -1237,7 +1237,7 @@ dependencies = [ [[package]] name = "oxide_compiler" -version = "0.21.0" +version = "0.21.1" dependencies = [ "oxide_bytecode", "oxide_cfg", @@ -1258,7 +1258,7 @@ dependencies = [ [[package]] name = "oxide_dce" -version = "0.21.0" +version = "0.21.1" dependencies = [ "oxide_bytecode", "oxide_cfg", @@ -1272,7 +1272,7 @@ dependencies = [ [[package]] name = "oxide_emit" -version = "0.21.0" +version = "0.21.1" dependencies = [ "num-bigint", "oxc_allocator", @@ -1288,7 +1288,7 @@ dependencies = [ [[package]] name = "oxide_engine" -version = "0.21.0" +version = "0.21.1" dependencies = [ "oxide_bytecode", "oxide_compiler", @@ -1300,7 +1300,7 @@ dependencies = [ [[package]] name = "oxide_fold" -version = "0.21.0" +version = "0.21.1" dependencies = [ "num-bigint", "oxide_bytecode", @@ -1312,7 +1312,7 @@ dependencies = [ [[package]] name = "oxide_ir" -version = "0.21.0" +version = "0.21.1" dependencies = [ "oxide_bytecode", "oxide_log", @@ -1321,7 +1321,7 @@ dependencies = [ [[package]] name = "oxide_kernel" -version = "0.21.0" +version = "0.21.1" dependencies = [ "bumpalo", "dashmap", @@ -1335,7 +1335,7 @@ dependencies = [ [[package]] name = "oxide_liveness" -version = "0.21.0" +version = "0.21.1" dependencies = [ "oxide_bytecode", "oxide_cfg", @@ -1347,7 +1347,7 @@ dependencies = [ [[package]] name = "oxide_log" -version = "0.21.0" +version = "0.21.1" dependencies = [ "tracing", "tracing-appender", @@ -1356,11 +1356,11 @@ dependencies = [ [[package]] name = "oxide_net" -version = "0.21.0" +version = "0.21.1" [[package]] name = "oxide_parser" -version = "0.21.0" +version = "0.21.1" dependencies = [ "oxc_allocator", "oxc_ast", @@ -1375,7 +1375,7 @@ dependencies = [ [[package]] name = "oxide_regalloc" -version = "0.21.0" +version = "0.21.1" dependencies = [ "oxide_bytecode", "oxide_cfg", @@ -1391,7 +1391,7 @@ dependencies = [ [[package]] name = "oxide_runtime_api" -version = "0.21.0" +version = "0.21.1" dependencies = [ "num-bigint", "num-traits", @@ -1404,7 +1404,7 @@ dependencies = [ [[package]] name = "oxide_test262" -version = "0.21.0" +version = "0.21.1" dependencies = [ "oxide_bytecode", "oxide_compiler", @@ -1424,7 +1424,7 @@ dependencies = [ [[package]] name = "oxide_types" -version = "0.21.0" +version = "0.21.1" dependencies = [ "bumpalo", "dashmap", @@ -1437,7 +1437,7 @@ dependencies = [ [[package]] name = "oxide_vm" -version = "0.21.0" +version = "0.21.1" dependencies = [ "bumpalo", "chrono", diff --git a/Cargo.toml b/Cargo.toml index fe95894e..baf2643a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -25,7 +25,7 @@ members = [ ] [workspace.package] -version = "0.21.0" +version = "0.21.1" edition = "2021" license = "MIT" rust-version = "1.80" diff --git a/crates/oxide_builtins/src/iterator.rs b/crates/oxide_builtins/src/iterator.rs index b2285196..ef752071 100644 --- a/crates/oxide_builtins/src/iterator.rs +++ b/crates/oxide_builtins/src/iterator.rs @@ -2420,6 +2420,7 @@ fn get_iterator(vm: &mut H, value: JsValue) -> Result m, Err(err) => { @@ -2430,6 +2431,11 @@ fn get_iterator(vm: &mut H, value: JsValue) -> Result, /// 词法循环头(C-for / for-in / for-of)名集:头名索引由 ForHeadEnv 覆盖 /// 捕获映射分配(TDZ 占位与体区 fresh cell),声明点据此走映射回退而非 /// 就地追加新索引。begin 时并入、restore 时移除,嵌套循环成对。 @@ -304,6 +309,7 @@ impl CompileCtx { block_fn_entry_mats: Vec::new(), captured_bindings: BTreeMap::new(), next_cell_idx: 0, + per_iter_predeclared_cells: HashSet::new(), for_head_env_names: HashSet::new(), pending_for_head_names: HashSet::new(), global_tier_names: HashSet::new(), diff --git a/crates/oxide_emit/src/prepass/declare.rs b/crates/oxide_emit/src/prepass/declare.rs index f2869f86..4e3cb446 100644 --- a/crates/oxide_emit/src/prepass/declare.rs +++ b/crates/oxide_emit/src/prepass/declare.rs @@ -425,6 +425,11 @@ impl Emitter { { let idx = ctx.alloc_cell_idx(); ctx.set_binding_cell_idx(bi.name.as_str(), idx); + // 登记每迭代 TDZ 占位:循环体内块重执行时该 MAKE_CELL 每迭代 + // 新建未初始化 cell,声明点据此改发原位 MAKE_CELL(闭包捕获 + // 占位 cell 后跟随初始化),替换式 fresh 会孤儿化声明前创建的 + // 闭包(提升函数声明)致 TDZ 误报。 + ctx.per_iter_predeclared_cells.insert(idx); let undef_reg = self.emit_undefined(ctx); ctx.inst(Inst::new( OpCode::MAKE_CELL, diff --git a/crates/oxide_emit/src/shared/binding.rs b/crates/oxide_emit/src/shared/binding.rs index de0c8187..6e6f0a56 100644 --- a/crates/oxide_emit/src/shared/binding.rs +++ b/crates/oxide_emit/src/shared/binding.rs @@ -101,7 +101,15 @@ impl Emitter { // 绑定走回填索引,块级遮蔽绑定走预声明追加索引,catch 参数等块作用域 // 就地声明现场追加;词法循环头名走捕获映射回退。 if let Some(cell_idx) = ctx.resolve_bind_cell_idx(name) { - let op = if fresh_cell { OpCode::MAKE_CELL_FRESH } else { OpCode::MAKE_CELL }; + // 每迭代 TDZ 占位已建(块入口预声明)时改发原位 MAKE_CELL:占位 + // cell 是本迭代新 cell,声明前创建的闭包(提升函数声明)已捕获它, + // 原位更新使其跟随初始化;仅体区 fresh cell 场景(循环头绑定,占位 + // 一次性)发替换式 MAKE_CELL_FRESH。 + let op = if fresh_cell && !ctx.per_iter_predeclared_cells.contains(&cell_idx) { + OpCode::MAKE_CELL_FRESH + } else { + OpCode::MAKE_CELL + }; ctx.inst(Inst::new(op, Operand::Reg(src_reg), Operand::Imm(cell_idx as u16), Operand::None)); // C 风格 for 头绑定:cell 之外补写绑定寄存器——循环体/test/update 读寄存器, // 每迭代 fresh 拷贝的源也是寄存器(见 `CompileCtx::for_head_store_registers`)。 diff --git a/crates/oxide_emit/src/stmt/declaration/var.rs b/crates/oxide_emit/src/stmt/declaration/var.rs index fe0d5c8a..87108975 100644 --- a/crates/oxide_emit/src/stmt/declaration/var.rs +++ b/crates/oxide_emit/src/stmt/declaration/var.rs @@ -79,8 +79,13 @@ impl Emitter { // 被捕获绑定的 cell 在函数入口已实例化(undefined);声明语句 // 不赋值,仅首次声明刷新初值,已绑定的 cell 保留现值。 if !already_bound { - // 重执行迭代取新 cell,与 with-init 臂同一门控。 - let op = if reexec { OpCode::MAKE_CELL_FRESH } else { OpCode::MAKE_CELL }; + // 重执行迭代取新 cell,与 with-init 臂同一门控:块入口每迭代 + // TDZ 占位已建时原位更新,防孤儿化声明前创建的闭包。 + let op = if reexec && !ctx.per_iter_predeclared_cells.contains(&cell_idx) { + OpCode::MAKE_CELL_FRESH + } else { + OpCode::MAKE_CELL + }; ctx.inst(Inst::new(op, Operand::Reg(tmp), Operand::Imm(cell_idx as u16), Operand::None)); } } else if !already_bound { diff --git a/crates/oxide_vm/src/vm/call.rs b/crates/oxide_vm/src/vm/call.rs index 79b767d9..cdfb1568 100644 --- a/crates/oxide_vm/src/vm/call.rs +++ b/crates/oxide_vm/src/vm/call.rs @@ -303,8 +303,16 @@ impl Vm { // 窗口 = min(调用方活动寄存器, 存活上界);call_window=0 表示调用方全量 // (运行时发起路径 / 未编码的旧模块)。恢复按窗口回拷,active_reg_limit // 仍还原为调用方真实值(caller_active_reg_limit)。 + // native 调用在飞(native_call_depth > 0)时窗口扩到全量 254:native 实参 + // 暂存在调用点参数窗口(物理槽 252/253 一带),内层字节码调用复用同一 + // 参数窗口会踩掉外层 native 实参;窗口截断不覆盖参数窗口时 restore + // 不还原,外层 builtin 后续读实参得踩值。 let caller_active_reg_limit = self.active_reg_limit.max(1); - let caller_reg_limit = self.call_window_limit(caller_active_reg_limit, call_window); + let caller_reg_limit = if self.native_call_depth > 0 { + 254 + } else { + self.call_window_limit(caller_active_reg_limit, call_window) + }; let saved_reg_offset = self.save_stack.len() as u32; self.save_stack.extend_from_slice(&self.regs[..caller_reg_limit as usize]); let saved_this = self.regs[254]; diff --git a/crates/oxide_vm/src/vm_dispatch_misc.rs b/crates/oxide_vm/src/vm_dispatch_misc.rs index e334dadc..01f5178c 100644 --- a/crates/oxide_vm/src/vm_dispatch_misc.rs +++ b/crates/oxide_vm/src/vm_dispatch_misc.rs @@ -1032,8 +1032,15 @@ impl Vm { pub(crate) fn dispatch_for_of_init(&mut self, a: usize) -> Result<(), String> { vm_trace!("FOR_OF_INIT r{}={:?}", a, self.regs[a]); let iterable = self.regs[a]; + let pc_before = self.pc; match oxide_builtins::iterator::make_iterator_for_value(self, iterable) { Ok(iterator) => { + // 取迭代器期间源 getter 抛出:深度 0 的 raise_call_error 已就地 + // unwind(跳转 catch),pc 已改写——迭代器值无效,直接返回, + // 派发循环自 catch 点续行,不得再触碰迭代器栈。 + if self.pc != pc_before { + return Ok(()); + } // 内置包装器检测:Array/String/TA/Map/Set 走快路径(异步恒慢)。 // init 期把 inner 快照入条目,步内不重读 `__inner__` 槽。 let (kind, inner) = match oxide_builtins::iterator::builtin_iter_kind(self, iterator) { @@ -1044,6 +1051,12 @@ impl Vm { Ok(()) } Err(err) => { + // 取迭代器期间源 getter 抛出:深度 0 的 raise_call_error 已就地 + // unwind(跳转 catch),pc 已改写、handler 已弹出——不得再 unwind + //(二次展开无 handler 必报未捕获),派发循环自 catch 点续行。 + if self.pc != pc_before { + return Ok(()); + } self.exception_value = Some(err); self.pending_error_kind = Some(self.thrown_error_kind(err)); self.unwind() diff --git a/crates/oxide_vm/src/vm_runtime.rs b/crates/oxide_vm/src/vm_runtime.rs index 23628efd..a3c69ece 100644 --- a/crates/oxide_vm/src/vm_runtime.rs +++ b/crates/oxide_vm/src/vm_runtime.rs @@ -466,7 +466,15 @@ impl Vm { vm_trace!("call_bytecode: saving state pc={} depth={}", self.pc, self.frames.len()); // 窗口 = max(调用方活跃寄存器, callee 寄存器数):restore 只回拷窗口,正好 // 覆盖 callee 写入区(regs[0..n_registers] + 254/255)与调用方活动区。 - let window = self.active_reg_limit.max(sub.n_registers).max(1) as usize; + // native 调用在飞(native_call_depth > 0)时窗口扩到全量 254:native 实参 + // 暂存在调用点参数窗口(物理槽 252/253 一带,arg_window_base = 254 − max_nargs), + // 内层字节码调用复用同一参数窗口会踩掉外层 native 实参;窗口截断不覆盖 + // 参数窗口时 restore 不还原,外层 builtin 后续读实参得踩值。 + let window = if self.native_call_depth > 0 { + 254 + } else { + self.active_reg_limit.max(sub.n_registers).max(1) as usize + }; let saved = self.save_inline_state(window); // 只零填 callee 读区 regs[0..n_registers];高位残留调用方旧值无害