mirror of
https://github.com/pjh456/OxideJS.git
synced 2026-10-24 10:41:11 +08:00
fix: 异常值通道配对——忽略调用槽配对、unwind 接住清槽、生成器参数初始化不覆盖异常值
This commit is contained in:
@@ -747,14 +747,24 @@ impl Vm {
|
||||
&& self.sub_modules[sub_idx].is_generator
|
||||
&& self.sub_modules[sub_idx].is_async
|
||||
{
|
||||
let gen_pc = self.pc;
|
||||
let gen = self.create_async_generator_object(callee, this_value, &args)?;
|
||||
self.regs[0] = gen;
|
||||
// 参数初始化抛错已就地展开(unwind 改写 pc 至 catch):异常值已
|
||||
// 写入 catch 参数,再写结果寄存器会覆盖之——仅在初始化成功(pc 未动)
|
||||
// 时交付生成器对象。
|
||||
if self.pc == gen_pc {
|
||||
self.regs[0] = gen;
|
||||
}
|
||||
return Ok(false);
|
||||
}
|
||||
// 生成器函数调用返回迭代器对象,不执行函数体。
|
||||
if sub_idx < self.sub_modules.len() && self.sub_modules[sub_idx].is_generator {
|
||||
let gen_pc = self.pc;
|
||||
let gen = self.create_generator_object(callee, this_value, &args)?;
|
||||
self.regs[0] = gen;
|
||||
// 参数初始化抛错已就地展开时不得覆盖 catch 参数(同上)。
|
||||
if self.pc == gen_pc {
|
||||
self.regs[0] = gen;
|
||||
}
|
||||
return Ok(false);
|
||||
}
|
||||
// 异步函数调用返回 capability promise,立即同步执行 body 到首个 await。
|
||||
|
||||
@@ -1579,7 +1579,10 @@ fn close_agg_iterator(vm: &mut Vm, iterator: JsValue) {
|
||||
let iter_obj = unsafe { &*iterator.as_js_object_ptr() };
|
||||
if let Ok(ret) = vm.ordinary_get(iter_obj, return_si, iterator) {
|
||||
if oxide_builtins::iterator::is_callable(ret) {
|
||||
// return() 的抛错被忽略,其值不得外泄进槽覆盖在途异常。
|
||||
let saved_uncaught = vm.last_uncaught_value.take();
|
||||
let _ = vm.call_function_sync(ret, iterator, &[]);
|
||||
vm.last_uncaught_value = saved_uncaught;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2123,6 +2123,9 @@ impl oxide_runtime_api::VmHost for Vm {
|
||||
fn take_uncaught_value(&mut self) -> Option<JsValue> {
|
||||
self.last_uncaught_value.take()
|
||||
}
|
||||
fn restore_uncaught_value(&mut self, value: Option<JsValue>) {
|
||||
self.last_uncaught_value = value;
|
||||
}
|
||||
fn property_key_si(&mut self, val: JsValue) -> u32 {
|
||||
// Object-key conversion (to_string_full) failures degrade to the empty key here:
|
||||
// this trait path is used by Reflect/Object builtins; computed property access
|
||||
|
||||
@@ -45,14 +45,24 @@ impl Vm {
|
||||
.collect();
|
||||
// 异步生成器函数调用返回异步生成器迭代器对象。
|
||||
if is_generator && is_async {
|
||||
let gen_pc = self.pc;
|
||||
let gen = self.create_async_generator_object(callee, this_value, &args)?;
|
||||
self.regs[0] = gen;
|
||||
// 参数初始化抛错已就地展开(unwind 改写 pc 至 catch):异常值已
|
||||
// 写入 catch 参数,再写结果寄存器会覆盖之——仅在初始化成功(pc 未动)
|
||||
// 时交付生成器对象。
|
||||
if self.pc == gen_pc {
|
||||
self.regs[0] = gen;
|
||||
}
|
||||
return Ok(false);
|
||||
}
|
||||
// 生成器函数调用返回迭代器对象,不执行函数体。
|
||||
if is_generator {
|
||||
let gen_pc = self.pc;
|
||||
let gen = self.create_generator_object(callee, this_value, &args)?;
|
||||
self.regs[0] = gen;
|
||||
// 参数初始化抛错已就地展开时不得覆盖 catch 参数(同上)。
|
||||
if self.pc == gen_pc {
|
||||
self.regs[0] = gen;
|
||||
}
|
||||
return Ok(false);
|
||||
}
|
||||
// 异步函数调用返回 capability promise,立即同步执行 body 到首个 await。
|
||||
|
||||
@@ -656,11 +656,14 @@ impl Vm {
|
||||
return Err("FOR_OF_DONE iterator is not an object".into());
|
||||
}
|
||||
|
||||
// 调用 next()/读 done 前清空异常值槽:跨调用残留不得污染本指令的取槽。
|
||||
self.last_uncaught_value = None;
|
||||
let iter_obj = unsafe { &*iterator.as_js_object_ptr() };
|
||||
let next_si = self.kernel_core.perm_interner().intern("next").0;
|
||||
let next_fn = match self.ordinary_get(iter_obj, next_si, iterator) {
|
||||
Ok(v) => v,
|
||||
// 错误路径只经 throw_for_of_error 传播,不写 rd(rd 保持循环决策位,
|
||||
// 异常展开后指令流离开循环,残留值无效)。
|
||||
Err(e) => return self.throw_for_of_error(e),
|
||||
};
|
||||
let result = match self.call_function_sync(next_fn, iterator, &[]) {
|
||||
@@ -694,6 +697,7 @@ impl Vm {
|
||||
let value_si = self.kernel_core.perm_interner().intern("value").0;
|
||||
self.regs[rd] = match self.ordinary_get(result_obj, value_si, result) {
|
||||
Ok(v) => v,
|
||||
// 错误路径只经 throw_for_of_error 传播,不写 rd(同上)。
|
||||
Err(e) => return self.throw_for_of_error(e),
|
||||
};
|
||||
Ok(())
|
||||
@@ -710,6 +714,8 @@ impl Vm {
|
||||
};
|
||||
self.exception_value = Some(exc);
|
||||
self.pending_error_kind = Some(self.thrown_error_kind(exc));
|
||||
// 无论取到原值还是重建错误对象,异常必须展开传播,不得静默返回 Ok——
|
||||
// 否则 for-of 循环继续推进形成不终止。
|
||||
self.unwind()
|
||||
}
|
||||
|
||||
@@ -764,9 +770,13 @@ impl Vm {
|
||||
if suppress_return_error {
|
||||
let saved_exc = self.exception_value;
|
||||
let saved_kind = self.pending_error_kind;
|
||||
// 忽略调用期间的原始异常值一并暂存:return() 自身抛错按契约被在途
|
||||
// 异常替代,其值不得外泄进槽供后续 take 误取。
|
||||
let saved_uncaught = self.last_uncaught_value.take();
|
||||
let _ = self.call_function_sync(return_fn, iterator, &[]);
|
||||
self.exception_value = saved_exc;
|
||||
self.pending_error_kind = saved_kind;
|
||||
self.last_uncaught_value = saved_uncaught;
|
||||
} else {
|
||||
let inner = match self.call_function_sync(return_fn, iterator, &[]) {
|
||||
Ok(v) => v,
|
||||
|
||||
@@ -522,6 +522,8 @@ impl Vm {
|
||||
handler.finally_active = true;
|
||||
self.try_stack.push(handler);
|
||||
self.pc = finally_pc;
|
||||
// 在途异常已进入 finally 处理流程:槽作废,防残留值被后续 take 误取。
|
||||
self.last_uncaught_value = None;
|
||||
return Ok(());
|
||||
}
|
||||
if let Some(catch_pc) = handler.catch_pc {
|
||||
@@ -529,6 +531,8 @@ impl Vm {
|
||||
let exc = self.exception_value.take().unwrap_or(JsValue::undefined());
|
||||
self.regs[0] = exc;
|
||||
self.pc = catch_pc;
|
||||
// 在途异常已写入 catch 参数:槽作废,防残留值被后续 take 误取。
|
||||
self.last_uncaught_value = None;
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user