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);
|
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() {
|
let this_value = if ctor_obj.is_derived_constructor() {
|
||||||
JsValue::undefined()
|
JsValue::undefined()
|
||||||
} else {
|
} else {
|
||||||
@@ -926,9 +923,6 @@ impl Vm {
|
|||||||
}
|
}
|
||||||
Ok(false)
|
Ok(false)
|
||||||
} else if super_obj.sub_module_index() > 0 {
|
} 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(
|
self.push_bytecode_frame(
|
||||||
super_ctor,
|
super_ctor,
|
||||||
derived_this,
|
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]
|
#[test]
|
||||||
fn test_array_length_range_error() {
|
fn test_array_length_range_error() {
|
||||||
let result = eval("new Array(4294967295)");
|
let result = eval("new Array(4294967295)");
|
||||||
|
|||||||
Reference in New Issue
Block a user