fix: 修复原生调用无限递归问题

This commit is contained in:
爱特每羊队
2026-06-09 21:07:49 +08:00
parent 99b768c060
commit 0a93cc4fef
2 changed files with 15 additions and 0 deletions
+6
View File
@@ -19,17 +19,23 @@ impl Vm {
pub(crate) fn dispatch_native_call( pub(crate) fn dispatch_native_call(
&mut self, obj: &JsObject, callee: JsValue, this_reg: u8, first_arg_reg: u8, arg_count: usize, &mut self, obj: &JsObject, callee: JsValue, this_reg: u8, first_arg_reg: u8, arg_count: usize,
) -> Result<(), String> { ) -> Result<(), String> {
if self.native_call_depth >= self.kernel.config.max_call_depth {
return Err("RangeError: Maximum call stack size exceeded".into());
}
let (args_buf, len) = Self::build_native_args(first_arg_reg, arg_count, this_reg); let (args_buf, len) = Self::build_native_args(first_arg_reg, arg_count, this_reg);
let args_slice = &args_buf[..len]; let args_slice = &args_buf[..len];
let func: NativeFn = unsafe { std::mem::transmute(obj.native_fn().unwrap()) }; let func: NativeFn = unsafe { std::mem::transmute(obj.native_fn().unwrap()) };
self.regs[254] = callee; self.regs[254] = callee;
self.native_call_depth += 1;
match func(self, args_slice) { match func(self, args_slice) {
Ok(val) => { Ok(val) => {
self.native_call_depth -= 1;
self.regs[0] = val; self.regs[0] = val;
Ok(()) Ok(())
} }
Err(err_val) => { Err(err_val) => {
self.native_call_depth -= 1;
let (error, kind) = if err_val.is_object() { let (error, kind) = if err_val.is_object() {
(err_val, self.thrown_error_kind(err_val)) (err_val, self.thrown_error_kind(err_val))
} else { } else {
+9
View File
@@ -93,6 +93,7 @@ pub struct Vm {
pub(crate) for_of_iters: Vec<*mut u8>, pub(crate) for_of_iters: Vec<*mut u8>,
pub(crate) root_reg_limit: u8, pub(crate) root_reg_limit: u8,
pub(crate) active_reg_limit: u8, pub(crate) active_reg_limit: u8,
pub(crate) native_call_depth: usize,
} }
impl Vm { impl Vm {
@@ -141,6 +142,7 @@ impl Vm {
for_of_iters: Vec::new(), for_of_iters: Vec::new(),
root_reg_limit: 0, root_reg_limit: 0,
active_reg_limit: 0, active_reg_limit: 0,
native_call_depth: 0,
} }
} }
@@ -171,6 +173,7 @@ impl Vm {
for_of_iters: Vec::new(), for_of_iters: Vec::new(),
root_reg_limit: 0, root_reg_limit: 0,
active_reg_limit: 0, active_reg_limit: 0,
native_call_depth: 0,
} }
} }
@@ -227,6 +230,7 @@ impl Vm {
self.exception_value = None; self.exception_value = None;
self.pending_exception = None; self.pending_exception = None;
self.pending_error_kind = None; self.pending_error_kind = None;
self.native_call_depth = 0;
} }
pub fn reset(&mut self) { pub fn reset(&mut self) {
@@ -482,6 +486,9 @@ impl Vm {
} }
if let Some(native_fn) = callee_obj.native_fn() { if let Some(native_fn) = callee_obj.native_fn() {
if self.native_call_depth >= self.kernel.config.max_call_depth {
return Err("RangeError: Maximum call stack size exceeded".into());
}
let saved_regs = self.regs; let saved_regs = self.regs;
let saved_this = self.regs[254]; let saved_this = self.regs[254];
let saved_callee = self.regs[253]; let saved_callee = self.regs[253];
@@ -496,7 +503,9 @@ impl Vm {
arg_regs[idx + 1] = 240 + idx as u8; arg_regs[idx + 1] = 240 + idx as u8;
} }
let func: NativeFn = unsafe { std::mem::transmute(native_fn) }; let func: NativeFn = unsafe { std::mem::transmute(native_fn) };
self.native_call_depth += 1;
let result = func(self, &arg_regs[..args.len().min(16) + 1]); let result = func(self, &arg_regs[..args.len().min(16) + 1]);
self.native_call_depth -= 1;
self.regs = saved_regs; self.regs = saved_regs;
self.regs[254] = saved_this; self.regs[254] = saved_this;
self.regs[253] = saved_callee; self.regs[253] = saved_callee;