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:
@@ -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,
|
||||
|
||||
@@ -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)");
|
||||
|
||||
Reference in New Issue
Block a user