fix: NEW_SPREAD/SUPER_SPREAD 构造深递归统一走压帧入口可捕获深度检查

收敛后普通 NEW/SUPER 深递归经 push_bytecode_frame 深度检查抛可捕获
RangeError,而 NEW_SPREAD/SUPER_SPREAD 仍保留显式引擎 Err(不可捕获),
构造路径行为分叉。删除两处显式检查,交由统一入口处理:spread 变体与
普通路径一致抛可捕获 RangeError。补浅深度配置下 NEW/NEW_SPREAD 深递归
try/catch 可捕获断言(普通 NEW 作对照锚点)。
This commit is contained in:
2026-08-15 12:13:36 +08:00
parent 354ab2f192
commit 41f030dfc8
2 changed files with 42 additions and 6 deletions
-6
View File
@@ -833,9 +833,6 @@ impl Vm {
{
return self.raise_type_error("g is not a constructor").map(|_| true);
}
if self.frames.len() >= self.kernel_core.config.max_call_depth {
return Err(self.error_message_text("RangeError", "Maximum call stack size exceeded"));
}
let this_value = if ctor_obj.is_derived_constructor() {
JsValue::undefined()
} else {
@@ -926,9 +923,6 @@ impl Vm {
}
Ok(false)
} else if super_obj.sub_module_index() > 0 {
if self.frames.len() >= self.kernel_core.config.max_call_depth {
return Err(self.error_message_text("RangeError", "Maximum call stack size exceeded"));
}
self.push_bytecode_frame(
super_ctor,
derived_this,
+42
View File
@@ -179,6 +179,48 @@ fn test_recursive_getter_throws_range_error() {
);
}
/// 浅调用深度配置下执行源码:NEW/NEW_SPREAD 深递归无需堆满默认 1024 层即可命中
/// 深度上限,输出与 `eval` 同构(字符串结果取其内容)。
fn eval_shallow(source: &str, depth: usize) -> String {
let allocator = Allocator::default();
let program = oxide_parser::parse(&allocator, source).unwrap();
let module = Compiler::new().compile(&program).unwrap();
let mut cfg = KernelConfig::minimal();
cfg.max_call_depth = depth;
let mut vm = Vm::with_kernel_core(KernelCore::new(cfg));
match vm.run(&module) {
Ok(val) => {
if val.is_string() {
vm.lookup_str(val).unwrap_or_default().to_string()
} else {
format!("{val}")
}
}
Err(e) => format!("vm error: {e}"),
}
}
#[test]
fn test_new_deep_recursion_throws_catchable_range_error() {
// NEW 深递归经统一压帧入口抛可捕获 RangeError:try/catch 能接住(非引擎错误)。
let result = eval_shallow(
"function f(){ return new f(); } try { f(); 'no-throw'; } catch(e){ 'caught:'+e.name; }",
8,
);
assert_eq!(result, "caught:RangeError", "NEW 深递归应可捕获,got: {result}");
}
#[test]
fn test_new_spread_deep_recursion_throws_catchable_range_error() {
// NEW_SPREAD 深递归与普通 NEW 同构:构造路径统一收敛到压帧入口的深度检查,
// 不得再走显式引擎 Err(不可捕获)。spread 变体与普通路径行为须一致。
let result = eval_shallow(
"function f(){ return new f(...[1]); } try { f(); 'no-throw'; } catch(e){ 'caught:'+e.name; }",
8,
);
assert_eq!(result, "caught:RangeError", "NEW_SPREAD 深递归应可捕获,got: {result}");
}
#[test]
fn test_array_length_range_error() {
let result = eval("new Array(4294967295)");