1005 lines
46 KiB
Rust
1005 lines
46 KiB
Rust
use crate::native::NativeFn;
|
||
use crate::vm::{native_fn_ptr_to_fn, FrameArgs, FrameContinuation, Vm};
|
||
use crate::{vm_debug, vm_trace};
|
||
use oxide_builtins::iterator::make_iterator_for_value;
|
||
use oxide_builtins::{builtins_debug, builtins_trace};
|
||
use oxide_bytecode::opcode;
|
||
use oxide_runtime_api::{to_boolean, NativeResult};
|
||
use oxide_types::object::{Cell, JsObject, PropAttributes};
|
||
use oxide_types::value::JsValue;
|
||
|
||
impl Vm {
|
||
#[inline(always)]
|
||
pub(crate) fn build_native_args(first_arg_reg: u8, arg_count: usize, this_reg: u8) -> ([u8; 257], usize) {
|
||
let mut args_buf = [0u8; 257];
|
||
args_buf[0] = this_reg;
|
||
let n = arg_count.min(256);
|
||
for i in 0..n {
|
||
args_buf[i + 1] = first_arg_reg.wrapping_add(i as u8);
|
||
}
|
||
(args_buf, n + 1)
|
||
}
|
||
|
||
#[inline(always)]
|
||
pub(crate) fn dispatch_native_call(
|
||
&mut self, obj: &JsObject, callee: JsValue, this_reg: u8, first_arg_reg: u8, arg_count: usize,
|
||
) -> Result<(), String> {
|
||
if self.native_call_depth >= self.kernel_core.config.max_call_depth {
|
||
return self.raise_error_kind("RangeError", "Maximum call stack size exceeded");
|
||
}
|
||
let (args_buf, len) = Self::build_native_args(first_arg_reg, arg_count, this_reg);
|
||
let args_slice = &args_buf[..len];
|
||
builtins_debug!("native_call depth={} args={}", self.native_call_depth, arg_count);
|
||
|
||
// SAFETY: native_fn 经 set_native_fn 以合法 NativeFn 指针设置;
|
||
// native_fn_ptr_to_fn 是 NativeFnPtr → NativeFn 的唯一强制转换点。
|
||
let func: NativeFn = unsafe { native_fn_ptr_to_fn(obj.native_fn().unwrap()) };
|
||
// regs[254] 是调用方的 `this` 寄存器,同时充当分发型 builtin
|
||
// (Function.prototype.bind/call/apply)读取的"当前 callee"槽。native 调用与
|
||
// 调用方共享扁平寄存器文件,因此先快照调用方 `this`,在 native 执行期间暴露
|
||
// callee,随后恢复——否则每次 native 调用都会把自己的函数对象留在调用方的
|
||
// `this` 寄存器里。
|
||
let saved_this = self.regs[254];
|
||
self.regs[254] = callee;
|
||
self.native_call_depth += 1;
|
||
let result = func(self, args_slice);
|
||
self.native_call_depth -= 1;
|
||
self.regs[254] = saved_this;
|
||
match result {
|
||
NativeResult::Ok(val) => {
|
||
builtins_trace!("native_call ok depth={}", self.native_call_depth);
|
||
self.regs[0] = val;
|
||
Ok(())
|
||
}
|
||
NativeResult::Err(err_val) => {
|
||
// 异常值原样保留:native 内部错误均为 Error 对象(走上方分支),
|
||
// 非对象值来自用户回调 throw 的原始异常(经 last_uncaught_value
|
||
// 恢复),按 ECMAScript 语义 catch 须收到原值,不得包装成 Error。
|
||
let kind = self.thrown_error_kind(err_val);
|
||
self.exception_value = Some(err_val);
|
||
self.pending_error_kind = Some(kind);
|
||
self.unwind()
|
||
}
|
||
NativeResult::TailCall { callee, this, args } => {
|
||
if callee.is_object() {
|
||
let obj = unsafe { &*callee.as_js_object_ptr() };
|
||
if obj.native_fn().is_some() {
|
||
match self.call_function_sync(callee, this, &args) {
|
||
Ok(val) => {
|
||
self.regs[0] = val;
|
||
return Ok(());
|
||
}
|
||
Err(_) => {
|
||
// call_function_sync 已把 native 错误展平为 String,
|
||
// 原始 JsValue 暂存在 last_uncaught_value——恢复为 JS 异常,
|
||
// 使外围 try/catch 能捕获(而非作为引擎错误上抛)。
|
||
let exc = self
|
||
.last_uncaught_value
|
||
.take()
|
||
.unwrap_or_else(|| oxide_builtins::error::create_error(self, "call failed"));
|
||
let kind = self.thrown_error_kind(exc);
|
||
self.exception_value = Some(exc);
|
||
self.pending_error_kind = Some(kind);
|
||
self.unwind()?;
|
||
return Ok(());
|
||
}
|
||
}
|
||
}
|
||
}
|
||
self.push_bytecode_frame(
|
||
callee,
|
||
this,
|
||
FrameArgs::Slice(&args),
|
||
None,
|
||
None,
|
||
JsValue::undefined(),
|
||
FrameContinuation::None,
|
||
0,
|
||
)
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
impl Vm {
|
||
pub(crate) fn dispatch_create_closure(&mut self, rd: usize, instr: u32) -> Result<(), String> {
|
||
let sub_idx = opcode::imm16(instr) as u32;
|
||
vm_trace!("CREATE_CLOSURE rd={} sub_idx={}", rd, sub_idx);
|
||
if sub_idx == 0 || (sub_idx as usize) >= self.sub_modules.len() {
|
||
// 逃逸闭包(函数对象在定义模块之外被创建)时 sub_idx 相对定义模块,
|
||
// 超出当前 sub_modules 上下文——按运行时错误处理而非索引越界 panic。
|
||
return Err(format!(
|
||
"CREATE_CLOSURE: sub_module_index {} out of bounds (max {})",
|
||
sub_idx,
|
||
self.sub_modules.len()
|
||
));
|
||
}
|
||
let sub = &self.sub_modules[sub_idx as usize];
|
||
let is_arrow = sub.is_arrow;
|
||
let is_class_constructor = sub.is_class_constructor;
|
||
let is_derived_constructor = sub.is_derived_constructor;
|
||
let needs_home_object = sub.needs_home_object;
|
||
let upvalue_captures = sub.upvalue_captures.clone();
|
||
let function_name = sub.function_name.clone();
|
||
let function_length = sub.function_length;
|
||
let result = self.create_function_object(
|
||
sub_idx,
|
||
is_arrow,
|
||
is_class_constructor,
|
||
is_derived_constructor,
|
||
needs_home_object,
|
||
);
|
||
// 函数名推断:emit 端在变量声明/对象属性赋值点设置 function_name。
|
||
let func_obj = unsafe { &mut *result.as_js_object_ptr() };
|
||
let length_si = self.length_si;
|
||
let name_si = self.kernel_core.perm_interner().intern("name").0;
|
||
// length/name 描述符均为不可写、不可枚举、可配置(SetFunctionLength /
|
||
// SetFunctionName 语义);length 先于 name 定义保证属性序 [prototype, length, name]。
|
||
let attrs = PropAttributes::new(false, false, true);
|
||
let length_val = JsValue::int(function_length as i32);
|
||
self.define_data_property(func_obj, length_si, length_val, attrs)?;
|
||
let name_val = function_name
|
||
.as_deref()
|
||
.map(|n| self.new_string(n))
|
||
.unwrap_or_else(|| self.new_string(""));
|
||
self.define_data_property(func_obj, name_si, name_val, attrs)?;
|
||
if !upvalue_captures.is_empty() {
|
||
// 链式捕获(parent_uv_idx):从父闭包(创建者)的 upvalues 取 cell。
|
||
let parent_upvalues: Vec<*mut Cell> = match self.current_callee() {
|
||
Some(callee) if callee.is_object() => unsafe { &*callee.as_js_object_ptr() }.upvalues_slice().to_vec(),
|
||
_ => Vec::new(),
|
||
};
|
||
if let Some(current_cells) = self.cell_stack.last_mut() {
|
||
let mut upvals = Box::new(Vec::with_capacity(upvalue_captures.len()));
|
||
for capture in &upvalue_captures {
|
||
let cell_ptr = if let Some(puv) = capture.parent_uv_idx {
|
||
parent_upvalues.get(puv as usize).copied().unwrap_or(std::ptr::null_mut())
|
||
} else {
|
||
let cell_idx = capture.cell_idx as usize;
|
||
if cell_idx >= current_cells.len() {
|
||
current_cells.resize(cell_idx + 1, std::ptr::null_mut());
|
||
}
|
||
// cell 可能尚未 MAKE_CELL(hoisting 顺序:CREATE_CLOSURE 先于
|
||
// MAKE_CELL)——建占位 Cell,后续 MAKE_CELL 更新同一 Cell 的值,
|
||
// 保证 upvalue 始终指向定义方表里的稳定 cell(而非调用方表)。
|
||
if current_cells[cell_idx].is_null() {
|
||
// 占位 Cell 保持未初始化(TDZ)直到 MAKE_CELL 置位;
|
||
// 若绑定为 var 则其初始化 MAKE_CELL 在函数序言先于任何读取执行。
|
||
current_cells[cell_idx] = self.gc_state.alloc_cell(JsValue::undefined(), false);
|
||
}
|
||
current_cells[cell_idx]
|
||
};
|
||
upvals.push(cell_ptr);
|
||
}
|
||
let func_obj = unsafe { &mut *result.as_js_object_ptr() };
|
||
func_obj.set_upvalues(upvals);
|
||
}
|
||
}
|
||
self.regs[rd] = result;
|
||
Ok(())
|
||
}
|
||
|
||
#[allow(dead_code)]
|
||
pub(crate) fn dispatch_make_cell(&mut self, rd: usize, instr: u32) -> Result<(), String> {
|
||
let cell_idx = opcode::imm16(instr) as usize;
|
||
let value = self.regs[rd];
|
||
let current = self.cell_stack.last_mut().unwrap();
|
||
while current.len() <= cell_idx {
|
||
current.push(std::ptr::null_mut());
|
||
}
|
||
if current[cell_idx].is_null() {
|
||
// 无占位 cell:新建。
|
||
current[cell_idx] = self.gc_state.alloc_cell(value, true);
|
||
} else {
|
||
// 更新占位 cell(CREATE_CLOSURE 已建),使闭包 upvalue 指向的
|
||
// cell 值跟随初始化;赋值即解除 TDZ。
|
||
unsafe {
|
||
let cell = &mut *current[cell_idx];
|
||
cell.value = value;
|
||
cell.set_initialized(true);
|
||
}
|
||
}
|
||
Ok(())
|
||
}
|
||
|
||
/// 无条件新建 cell 并替换 cell_stack[cell_idx],值为 `regs[rd]`。
|
||
///
|
||
/// 循环每迭代绑定用:把当前迭代值拷入新 cell,本迭代创建的闭包经
|
||
/// CREATE_CLOSURE 捕获新 cell(旧闭包仍指向旧 cell,值保持)。与
|
||
/// `dispatch_make_cell` 的唯一区别是恒新建、不复用占位 cell。
|
||
#[allow(dead_code)]
|
||
pub(crate) fn dispatch_make_cell_fresh(&mut self, rd: usize, instr: u32) -> Result<(), String> {
|
||
let cell_idx = opcode::imm16(instr) as usize;
|
||
let value = self.regs[rd];
|
||
let current = self.cell_stack.last_mut().unwrap();
|
||
while current.len() <= cell_idx {
|
||
current.push(std::ptr::null_mut());
|
||
}
|
||
current[cell_idx] = self.gc_state.alloc_cell(value, true);
|
||
Ok(())
|
||
}
|
||
|
||
#[allow(dead_code)]
|
||
pub(crate) fn dispatch_cell_get(&mut self, rd: usize, a: usize, b: usize) -> Result<(), String> {
|
||
let cell_idx = b;
|
||
let current = self.cell_stack.last_mut().unwrap();
|
||
while current.len() <= cell_idx {
|
||
current.push(std::ptr::null_mut());
|
||
}
|
||
if current[cell_idx].is_null() {
|
||
let val = self.regs[a];
|
||
current[cell_idx] = self.gc_state.alloc_cell(val, true);
|
||
}
|
||
let c = unsafe { &*current[cell_idx] };
|
||
if !c.is_initialized() {
|
||
return self.raise_error_kind("ReferenceError", "Cannot access variable before initialization");
|
||
}
|
||
self.regs[rd] = c.value;
|
||
Ok(())
|
||
}
|
||
|
||
#[allow(dead_code)]
|
||
pub(crate) fn dispatch_cell_set(&mut self, a: usize, b: usize) -> Result<(), String> {
|
||
let cell_idx = b;
|
||
let src_val = self.regs[a];
|
||
let current = self.cell_stack.last_mut().unwrap();
|
||
if cell_idx >= current.len() {
|
||
return Ok(());
|
||
}
|
||
let cell_ptr = current[cell_idx];
|
||
if cell_ptr.is_null() {
|
||
return Ok(());
|
||
}
|
||
unsafe {
|
||
let cell = &mut *cell_ptr;
|
||
// TDZ 写检查:cell 未初始化(捕获绑定声明点前)写抛 ReferenceError。
|
||
if !cell.is_initialized() {
|
||
return self.raise_error_kind("ReferenceError", "Cannot access variable before initialization");
|
||
}
|
||
cell.value = src_val;
|
||
cell.set_initialized(true);
|
||
}
|
||
Ok(())
|
||
}
|
||
|
||
/// 当前执行函数的闭包对象:普通路径取 frames 栈顶帧,inline(sync 回调)路径
|
||
/// frames 被隔离为空,取 `inline_callee`。
|
||
pub(crate) fn current_callee(&self) -> Option<JsValue> {
|
||
self.frames.last().map(|f| f.callee).or(self.inline_callee)
|
||
}
|
||
|
||
#[allow(dead_code)]
|
||
pub(crate) fn dispatch_load_upvalue(&mut self, rd: usize, instr: u32) -> Result<(), String> {
|
||
let uv_idx = opcode::imm16(instr) as usize;
|
||
if let Some(callee) = self.current_callee() {
|
||
if callee.is_object() {
|
||
let obj = unsafe { &*callee.as_js_object_ptr() };
|
||
let upvals = obj.upvalues_slice();
|
||
if uv_idx < upvals.len() {
|
||
let cell = upvals[uv_idx];
|
||
if !cell.is_null() {
|
||
let c = unsafe { &*cell };
|
||
if !c.is_initialized() {
|
||
return self
|
||
.raise_error_kind("ReferenceError", "Cannot access variable before initialization");
|
||
}
|
||
self.regs[rd] = c.value;
|
||
return Ok(());
|
||
}
|
||
}
|
||
}
|
||
}
|
||
// cell 尚未创建(hoisting 顺序:CREATE_CLOSURE 先于 MAKE_CELL),
|
||
// 用调用方寄存器值惰性创建 cell。
|
||
self.lazy_create_upvalue_cell(rd, uv_idx)
|
||
}
|
||
|
||
fn lazy_create_upvalue_cell(&mut self, rd: usize, uv_idx: usize) -> Result<(), String> {
|
||
if let Some(callee) = self.current_callee() {
|
||
if callee.is_object() {
|
||
let obj = unsafe { &mut *callee.as_js_object_ptr() };
|
||
let upvals = obj.upvalues_slice_mut();
|
||
if uv_idx < upvals.len() {
|
||
// 尝试从调用方 cell 表取初值(MAKE_CELL 在 CREATE_CLOSURE 之后执行)。
|
||
let val = if self.cell_stack.len() >= 2 {
|
||
let caller_cells = &self.cell_stack[self.cell_stack.len() - 2];
|
||
if uv_idx < caller_cells.len() && !caller_cells[uv_idx].is_null() {
|
||
unsafe { (*caller_cells[uv_idx]).value }
|
||
} else {
|
||
self.regs[rd]
|
||
}
|
||
} else {
|
||
self.regs[rd]
|
||
};
|
||
upvals[uv_idx] = self.gc_state.alloc_cell(val, true);
|
||
self.regs[rd] = unsafe { (*upvals[uv_idx]).value };
|
||
return Ok(());
|
||
}
|
||
}
|
||
}
|
||
self.regs[rd] = JsValue::undefined();
|
||
Ok(())
|
||
}
|
||
|
||
#[allow(dead_code)]
|
||
pub(crate) fn dispatch_store_upvalue(&mut self, rd: usize, a: usize, b: usize) -> Result<(), String> {
|
||
let const_flag = rd;
|
||
let uv_idx = b;
|
||
let src_val = self.regs[a];
|
||
if let Some(callee) = self.current_callee() {
|
||
if callee.is_object() {
|
||
let obj = unsafe { &mut *callee.as_js_object_ptr() };
|
||
let upvals = obj.upvalues_slice_mut();
|
||
if uv_idx < upvals.len() {
|
||
if !upvals[uv_idx].is_null() {
|
||
unsafe {
|
||
let cell = &mut *upvals[uv_idx];
|
||
// TDZ 写检查:cell 未初始化(捕获绑定声明点前)写抛 ReferenceError。
|
||
if !cell.is_initialized() {
|
||
self.raise_error_kind(
|
||
"ReferenceError",
|
||
"Cannot access variable before initialization",
|
||
)?;
|
||
return Ok(());
|
||
}
|
||
// const guard:TDZ 检查后 cell 必已初始化(存在性判定,与值无关),
|
||
// const 初始值为 undefined 时再赋值同样抛。
|
||
if const_flag != 0 {
|
||
self.raise_error_kind("TypeError", "Assignment to constant variable")?;
|
||
return Ok(());
|
||
}
|
||
cell.value = src_val;
|
||
cell.set_initialized(true);
|
||
}
|
||
vm_debug!("STORE_UPVALUE len={} wrote existing", upvals.len());
|
||
} else {
|
||
upvals[uv_idx] = self.gc_state.alloc_cell(src_val, true);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
Ok(())
|
||
}
|
||
}
|
||
|
||
impl Vm {
|
||
pub(crate) fn dispatch_create_regexp(&mut self, rd: usize, a: usize, b: usize) -> Result<Option<JsValue>, String> {
|
||
vm_trace!("CREATE_REGEXP rd={}", rd);
|
||
let pat_val = self.regs[a];
|
||
let flags_val = self.regs[b];
|
||
let ctor_ptr = self.session.builtin_world().regexp_constructor.as_ptr() as *mut JsObject;
|
||
let ctor = unsafe { &*ctor_ptr };
|
||
let Some(native_fn) = ctor.native_fn() else {
|
||
self.raise_error_kind("TypeError", "RegExp constructor unavailable")?;
|
||
return Ok(Some(JsValue::undefined()));
|
||
};
|
||
let saved_0 = self.regs[0];
|
||
let saved_1 = self.regs[1];
|
||
let saved_2 = self.regs[2];
|
||
self.regs[0] = JsValue::undefined();
|
||
self.regs[1] = pat_val;
|
||
self.regs[2] = flags_val;
|
||
let func = unsafe { native_fn_ptr_to_fn(native_fn) };
|
||
let result = match func(self, &[0, 1, 2]) {
|
||
NativeResult::Ok(v) => v,
|
||
NativeResult::Err(e) => {
|
||
// 保留原始错误对象与类型(非法正则字面量须抛 SyntaxError,非 TypeError)。
|
||
self.exception_value = Some(e);
|
||
self.pending_error_kind = Some(self.thrown_error_kind(e));
|
||
return self.unwind().map(|_| None);
|
||
}
|
||
NativeResult::TailCall { .. } => {
|
||
return Err(self.error_message_text("TypeError", "unexpected tail call"));
|
||
}
|
||
};
|
||
self.regs[0] = saved_0;
|
||
self.regs[1] = saved_1;
|
||
self.regs[2] = saved_2;
|
||
self.regs[rd] = result;
|
||
Ok(None)
|
||
}
|
||
|
||
pub(crate) fn dispatch_super_call(&mut self, rd: usize, a: usize) -> Result<bool, String> {
|
||
vm_debug!("SUPER_CALL depth={}", self.frames.len());
|
||
let first_arg_reg = a as u8;
|
||
let ext = self.bytecode[self.pc];
|
||
self.pc += 1;
|
||
let arg_count = (ext & 0xFF) as usize;
|
||
// ext 高 8 位 = 调用点存活上界(0 = 未编码/全量),压帧窗口按此截断。
|
||
let call_window = (ext >> 8) as u8;
|
||
|
||
let Some(frame) = self.frames.last() else {
|
||
self.raise_error_kind("ReferenceError", "super() used outside class constructor")?;
|
||
return Ok(true);
|
||
};
|
||
if !frame.is_derived_constructor {
|
||
self.raise_error_kind("ReferenceError", "super() used outside derived constructor")?;
|
||
return Ok(true);
|
||
}
|
||
if frame.super_called {
|
||
self.raise_error_kind("ReferenceError", "super() called more than once")?;
|
||
return Ok(true);
|
||
}
|
||
let Some(derived_this) = frame.constructed_this else {
|
||
self.raise_error_kind("ReferenceError", "super() without derived this")?;
|
||
return Ok(true);
|
||
};
|
||
let callee = frame.callee;
|
||
|
||
let new_target = self.regs[255];
|
||
if !new_target.is_object() {
|
||
self.raise_error_kind("TypeError", "super() new.target is not an object")?;
|
||
return Ok(true);
|
||
}
|
||
let new_target_obj = unsafe { &*new_target.as_js_object_ptr() };
|
||
// super 构造器取当前帧 callee(执行中的 derived 构造器)的原型,而非 newTarget:
|
||
// newTarget 跨 SUPER_CALL 压帧保持为最外层类,取其原型在中间 derived 层会
|
||
// 解析回同一父类,导致父帧被反复压入(多层继承栈溢出)。
|
||
if !callee.is_object() {
|
||
self.raise_error_kind("TypeError", "super() without constructor callee")?;
|
||
return Ok(true);
|
||
}
|
||
let callee_obj = unsafe { &*callee.as_js_object_ptr() };
|
||
let super_ctor = callee_obj.proto();
|
||
if !super_ctor.is_object() {
|
||
self.raise_error_kind("TypeError", "super constructor is not an object")?;
|
||
return Ok(true);
|
||
}
|
||
let super_obj = unsafe { &*super_ctor.as_js_object_ptr() };
|
||
if !super_obj.is_function() {
|
||
self.raise_error_kind("TypeError", "super constructor is not a function")?;
|
||
return Ok(true);
|
||
}
|
||
|
||
if super_obj.native_fn().is_some() {
|
||
self.regs[253] = derived_this;
|
||
self.regs[254] = super_ctor; // bind_dispatcher 把 regs[254] 当作包装 callee 读取
|
||
let (args_buf, len) = Self::build_native_args(first_arg_reg, arg_count, 253);
|
||
// SAFETY: native_fn 经 set_native_fn 以合法 NativeFn 指针设置;
|
||
// native_fn_ptr_to_fn 是 NativeFnPtr → NativeFn 的唯一强制转换点。
|
||
let func: NativeFn = unsafe { native_fn_ptr_to_fn(super_obj.native_fn().unwrap()) };
|
||
match func(self, &args_buf[..len]) {
|
||
NativeResult::Ok(val) => {
|
||
// super() 返回实例的 [[Prototype]] 须设为 new.target.prototype
|
||
//(native 构造器不知道 new.target,由调用方设置)。
|
||
let instance = if val.is_object() { val } else { derived_this };
|
||
if instance.is_object() {
|
||
self.set_constructed_proto(instance, new_target_obj)?;
|
||
}
|
||
self.regs[254] = instance;
|
||
self.regs[rd] = self.regs[254];
|
||
self.mark_super_called();
|
||
}
|
||
NativeResult::Err(err_val) => {
|
||
self.exception_value = Some(err_val);
|
||
self.pending_error_kind = Some(self.thrown_error_kind(err_val));
|
||
match self.unwind() {
|
||
Ok(()) => return Ok(true),
|
||
Err(e) => return Err(e),
|
||
}
|
||
}
|
||
NativeResult::TailCall { callee, this, args } => {
|
||
// 如 bound 函数:解析尾调用,用其返回值作为构造实例
|
||
// (或回退到 derived_this)。
|
||
match self.call_function_sync(callee, this, &args) {
|
||
Ok(val) => {
|
||
let instance = if val.is_object() { val } else { derived_this };
|
||
if instance.is_object() {
|
||
self.set_constructed_proto(instance, new_target_obj)?;
|
||
}
|
||
self.regs[254] = instance;
|
||
self.regs[rd] = self.regs[254];
|
||
self.mark_super_called();
|
||
}
|
||
Err(e) => return Err(e),
|
||
}
|
||
}
|
||
}
|
||
} else if super_obj.sub_module_index() > 0 {
|
||
let sub_idx = super_obj.sub_module_index() as usize;
|
||
if sub_idx >= self.sub_modules.len() {
|
||
return Err(format!(
|
||
"SUPER_CALL: sub_module_index {} out of bounds (max {})",
|
||
sub_idx,
|
||
self.sub_modules.len()
|
||
));
|
||
}
|
||
// 收敛到统一压帧入口:this = derived_this(super() 把实例交予父构造器),
|
||
// new.target 保持外层类;构造结果写回 regs[254]。
|
||
self.push_bytecode_frame(
|
||
super_ctor,
|
||
derived_this,
|
||
FrameArgs::RegRange {
|
||
first: first_arg_reg,
|
||
count: arg_count,
|
||
},
|
||
Some(254),
|
||
Some(derived_this),
|
||
new_target,
|
||
FrameContinuation::None,
|
||
call_window,
|
||
)?;
|
||
return Ok(true);
|
||
} else {
|
||
self.raise_error_kind("TypeError", "super constructor is not callable")?;
|
||
return Ok(true);
|
||
}
|
||
Ok(false)
|
||
}
|
||
|
||
/// super() 返回的构造实例其 [[Prototype]] 设为 new.target.prototype。
|
||
fn set_constructed_proto(&mut self, instance: JsValue, new_target_obj: &JsObject) -> Result<(), String> {
|
||
let proto_si = self.kernel_core.perm_interner().intern("prototype").0;
|
||
if let Some(proto_val) = self.resolve_property(new_target_obj, proto_si) {
|
||
if proto_val.is_object() {
|
||
let obj = unsafe { &mut *instance.as_js_object_ptr() };
|
||
obj.set_proto(proto_val).map_err(|e| e.to_string())?;
|
||
}
|
||
}
|
||
Ok(())
|
||
}
|
||
|
||
/// 置位当前 derived 帧的 super_called:native super 构造器同步返回后标记
|
||
/// super() 已成功调用(字节码父构造器路径由 do_return 在返回时置位)。
|
||
fn mark_super_called(&mut self) {
|
||
if let Some(frame) = self.frames.last_mut() {
|
||
if frame.is_derived_constructor {
|
||
frame.super_called = true;
|
||
}
|
||
}
|
||
}
|
||
|
||
pub(crate) fn dispatch_super_get_prop(&mut self, rd: usize, a: usize, b: usize) -> Result<bool, String> {
|
||
vm_trace!("SUPER_GET_PROP rd={} a={} b={}", rd, a, b);
|
||
let key_val = self.regs[b];
|
||
let prop_name_si = self.property_key_si(key_val)?;
|
||
let Some(frame) = self.frames.last() else {
|
||
self.raise_error_kind("ReferenceError", "super property used outside function")?;
|
||
return Ok(true);
|
||
};
|
||
if !frame.callee.is_object() {
|
||
self.raise_error_kind("ReferenceError", "super property has no home object")?;
|
||
return Ok(true);
|
||
}
|
||
let callee_obj = unsafe { &*frame.callee.as_js_object_ptr() };
|
||
let home_object = callee_obj.home_object();
|
||
if !home_object.is_object() {
|
||
self.raise_error_kind("ReferenceError", "super property has no home object")?;
|
||
return Ok(true);
|
||
}
|
||
let home_obj = unsafe { &*home_object.as_js_object_ptr() };
|
||
let super_base = home_obj.proto();
|
||
if !super_base.is_object() {
|
||
self.regs[rd] = JsValue::undefined();
|
||
} else {
|
||
let super_obj = unsafe { &*super_base.as_js_object_ptr() };
|
||
let val = self.ordinary_get_with_target(super_obj, prop_name_si, self.regs[a], rd as u8)?;
|
||
if self.accessor_frame_target_reg.take().is_none() {
|
||
self.regs[rd] = val;
|
||
}
|
||
}
|
||
Ok(false)
|
||
}
|
||
|
||
pub(crate) fn dispatch_set_home_object(&mut self, rd: usize, a: usize) -> Result<bool, String> {
|
||
vm_trace!("SET_HOME_OBJECT rd={} a={}", rd, a);
|
||
let func_val = self.regs[rd];
|
||
let home_val = self.regs[a];
|
||
if !func_val.is_object() || !home_val.is_object() {
|
||
self.raise_error_kind("TypeError", "SET_HOME_OBJECT expects function and object")?;
|
||
return Ok(true);
|
||
}
|
||
let home_val = self.promote_if_needed_for_write_ptr(func_val.as_js_object_ptr(), home_val);
|
||
let func_obj = unsafe { &mut *func_val.as_js_object_ptr() };
|
||
if !func_obj.is_function() {
|
||
self.raise_error_kind("TypeError", "SET_HOME_OBJECT target is not a function")?;
|
||
return Ok(true);
|
||
}
|
||
func_obj.set_home_object(home_val);
|
||
Ok(false)
|
||
}
|
||
}
|
||
|
||
impl Vm {
|
||
/// 解析 spread 调用系 ext:读走 `nstatic | (nspread<<8)` 首字与 `nstatic+nspread`
|
||
/// 个有序实参字(静态字 = 寄存器号,spread 字高位标记)。
|
||
fn read_spread_ext(&mut self) -> Vec<usize> {
|
||
let header = self.bytecode[self.pc];
|
||
self.pc += 1;
|
||
let nstatic = (header & 0xFF) as usize;
|
||
let nspread = (header >> 8) as usize;
|
||
let mut words = Vec::with_capacity(nstatic + nspread);
|
||
for _ in 0..nstatic + nspread {
|
||
words.push(self.bytecode[self.pc] as usize);
|
||
self.pc += 1;
|
||
}
|
||
words
|
||
}
|
||
|
||
/// 按源码求值序物化完整实参 Vec:静态字直接读寄存器,spread 字迭代展开。
|
||
///
|
||
/// # 步骤
|
||
/// 1. 静态实参逐个从寄存器读入;spread 源经 `make_iterator_for_value` 迭代追加。
|
||
/// 2. 迭代中途抛错 → 当前迭代器经 return() 关闭(IteratorClose),异常恢复为 JS
|
||
/// 异常后 unwind。
|
||
/// 3. 展开总数超过 u16 上限(arguments_count 字段)→ RangeError。
|
||
///
|
||
/// # 返回值
|
||
/// - `Ok(Some(vec))` 成功;
|
||
/// - `Ok(None)` 异常已展开(调用方按 continue 处理);
|
||
/// - `Err` 引擎错误直接传播。
|
||
fn materialize_spread_args(&mut self, words: &[usize]) -> Result<Option<Vec<JsValue>>, String> {
|
||
let mut args = Vec::with_capacity(words.len());
|
||
let next_si = self.kernel_core.perm_interner().intern("next").0;
|
||
let done_si = self.kernel_core.perm_interner().intern("done").0;
|
||
let value_si = self.kernel_core.perm_interner().intern("value").0;
|
||
for &w in words {
|
||
if w >> 31 == 1 {
|
||
let value = self.regs[w & 0x7FFF_FFFF];
|
||
let iterator = match make_iterator_for_value(self, value) {
|
||
Ok(it) => it,
|
||
Err(err) => {
|
||
self.exception_value = Some(err);
|
||
self.pending_error_kind = Some(self.thrown_error_kind(err));
|
||
return self.unwind().map(|_| None);
|
||
}
|
||
};
|
||
loop {
|
||
let iter_obj = unsafe { &*iterator.as_js_object_ptr() };
|
||
let next_fn = match self.ordinary_get(iter_obj, next_si, iterator) {
|
||
Ok(v) => v,
|
||
Err(e) => return self.spread_iter_error(iterator, e, "Error"),
|
||
};
|
||
let result = match self.call_function_sync(next_fn, iterator, &[]) {
|
||
Ok(v) => v,
|
||
Err(e) => return self.spread_iter_error(iterator, e, "Error"),
|
||
};
|
||
if !result.is_object() {
|
||
return self.spread_iter_error(
|
||
iterator,
|
||
self.error_message_text("TypeError", "iterator result is not an object"),
|
||
"TypeError",
|
||
);
|
||
}
|
||
let result_obj = unsafe { &*result.as_js_object_ptr() };
|
||
let done = match self.ordinary_get(result_obj, done_si, result) {
|
||
Ok(v) => to_boolean(v),
|
||
Err(e) => return self.spread_iter_error(iterator, e, "Error"),
|
||
};
|
||
if done {
|
||
break;
|
||
}
|
||
let val = match self.ordinary_get(result_obj, value_si, result) {
|
||
Ok(v) => v,
|
||
Err(e) => return self.spread_iter_error(iterator, e, "Error"),
|
||
};
|
||
args.push(val);
|
||
if args.len() > u16::MAX as usize {
|
||
self.raise_error_kind("RangeError", "Too many arguments in function call")?;
|
||
return Ok(None);
|
||
}
|
||
}
|
||
} else {
|
||
args.push(self.regs[w]);
|
||
if args.len() > u16::MAX as usize {
|
||
self.raise_error_kind("RangeError", "Too many arguments in function call")?;
|
||
return Ok(None);
|
||
}
|
||
}
|
||
}
|
||
Ok(Some(args))
|
||
}
|
||
|
||
/// spread 迭代中途异常:先关闭当前迭代器(suppress return 自身错误,保留在途异常),
|
||
/// 再把原异常(native 错误经 last_uncaught_value 恢复)重新抛出并展开。
|
||
fn spread_iter_error(
|
||
&mut self, iterator: JsValue, msg: String, fallback_kind: &'static str,
|
||
) -> Result<Option<Vec<JsValue>>, String> {
|
||
let exc = self
|
||
.last_uncaught_value
|
||
.take()
|
||
.unwrap_or_else(|| oxide_builtins::error::create_kind_error(self, fallback_kind, &msg));
|
||
self.close_for_of_iterator(iterator, true)?;
|
||
self.exception_value = Some(exc);
|
||
self.pending_error_kind = Some(self.thrown_error_kind(exc));
|
||
self.unwind().map(|_| None)
|
||
}
|
||
|
||
/// CALL_SPREAD:运行期物化完整实参后按目标分派(native 走值传递,字节码走帧)。
|
||
pub(crate) fn dispatch_call_spread(&mut self, rd: usize, a: usize, _b: usize) -> Result<bool, String> {
|
||
let callee = self.regs[rd];
|
||
let this_value = self.regs[a];
|
||
let words = self.read_spread_ext();
|
||
let args = match self.materialize_spread_args(&words)? {
|
||
Some(args) => args,
|
||
None => return Ok(true),
|
||
};
|
||
if callee.is_object() {
|
||
let obj_ptr = callee.as_js_object_ptr();
|
||
if !obj_ptr.is_null() {
|
||
let obj = unsafe { &*obj_ptr };
|
||
if obj.is_function() {
|
||
if obj.is_class_constructor() {
|
||
return self
|
||
.raise_type_error("class constructor cannot be invoked without 'new'")
|
||
.map(|_| true);
|
||
}
|
||
if obj.native_fn().is_some() {
|
||
match self.call_function_sync(callee, this_value, &args) {
|
||
Ok(v) => {
|
||
self.regs[0] = v;
|
||
return Ok(false);
|
||
}
|
||
Err(_) => {
|
||
let exc = self
|
||
.last_uncaught_value
|
||
.take()
|
||
.unwrap_or_else(|| oxide_builtins::error::create_error(self, "call failed"));
|
||
self.exception_value = Some(exc);
|
||
self.pending_error_kind = Some(self.thrown_error_kind(exc));
|
||
return self.unwind().map(|_| true);
|
||
}
|
||
}
|
||
} else if obj.sub_module_index() > 0 {
|
||
let sub_idx = obj.sub_module_index() as usize;
|
||
// 异步生成器函数调用返回异步生成器迭代器对象。
|
||
if sub_idx < self.sub_modules.len()
|
||
&& 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)?;
|
||
// 参数初始化抛错已就地展开(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)?;
|
||
// 参数初始化抛错已就地展开时不得覆盖 catch 参数(同上)。
|
||
if self.pc == gen_pc {
|
||
self.regs[0] = gen;
|
||
}
|
||
return Ok(false);
|
||
}
|
||
// 异步函数调用返回 capability promise,立即同步执行 body 到首个 await。
|
||
if sub_idx < self.sub_modules.len() && self.sub_modules[sub_idx].is_async {
|
||
let promise = self.create_async_object(callee, this_value, &args)?;
|
||
self.regs[0] = promise;
|
||
return Ok(false);
|
||
}
|
||
self.push_bytecode_frame(
|
||
callee,
|
||
this_value,
|
||
FrameArgs::Slice(&args),
|
||
None,
|
||
None,
|
||
JsValue::undefined(),
|
||
FrameContinuation::None,
|
||
0,
|
||
)?;
|
||
return Ok(true);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
self.raise_type_error("CALL target is not callable").map(|_| true)
|
||
}
|
||
|
||
/// NEW_EXPRESSION_SPREAD:物化实参后按构造函数目标分派(native 走值传递,字节码走帧)。
|
||
pub(crate) fn dispatch_new_expression_spread(&mut self, rd: usize, a: usize, _b: usize) -> Result<bool, String> {
|
||
let constructor_reg = a;
|
||
let constructor = self.regs[constructor_reg];
|
||
|
||
if !constructor.is_object() {
|
||
return self
|
||
.raise_type_error("NEW_EXPRESSION: constructor is not an object")
|
||
.map(|_| true);
|
||
}
|
||
let ctor_ptr = constructor.as_js_object_ptr();
|
||
if ctor_ptr.is_null() {
|
||
return self.raise_type_error("NEW_EXPRESSION: constructor is null").map(|_| true);
|
||
}
|
||
let ctor_obj = unsafe { &*ctor_ptr };
|
||
if !ctor_obj.is_function() {
|
||
return self
|
||
.raise_type_error("NEW_EXPRESSION: constructor is not a function")
|
||
.map(|_| true);
|
||
}
|
||
if ctor_obj.is_arrow() {
|
||
return self
|
||
.raise_type_error("arrow functions cannot be used as constructors")
|
||
.map(|_| true);
|
||
}
|
||
// native 方法(非构造器)不可 new;bound 包装除外(其构造语义转发到 target)。
|
||
if ctor_obj.native_fn().is_some()
|
||
&& ctor_obj.type_tag != oxide_types::object::JsObject::OBJ_TYPE_CONSTRUCTOR
|
||
&& ctor_obj.type_tag != oxide_types::object::JsObject::OBJ_TYPE_BOUND
|
||
{
|
||
return self.raise_type_error("object is not a constructor").map(|_| true);
|
||
}
|
||
|
||
let words = self.read_spread_ext();
|
||
let args = match self.materialize_spread_args(&words)? {
|
||
Some(args) => args,
|
||
None => return Ok(true),
|
||
};
|
||
|
||
// bound 包装:解包链后转发到最内层 target([[Construct]] 语义)。
|
||
if ctor_obj.type_tag == oxide_types::object::JsObject::OBJ_TYPE_BOUND {
|
||
let proto_ptr = &*self.object_prototype as *const JsObject as *mut JsObject;
|
||
let new_obj = self.alloc_object(JsObject::new_empty(
|
||
oxide_kernel::shape_forge::EMPTY_SHAPE_ID,
|
||
JsValue::from_js_object(proto_ptr),
|
||
));
|
||
return self.dispatch_new_bound(rd, constructor, new_obj, args, 0);
|
||
}
|
||
|
||
let proto_ptr = &*self.object_prototype as *const JsObject as *mut JsObject;
|
||
let new_obj = self.alloc_object(JsObject::new_empty(
|
||
oxide_kernel::shape_forge::EMPTY_SHAPE_ID,
|
||
JsValue::from_js_object(proto_ptr),
|
||
));
|
||
let proto_si = self.kernel_core.perm_interner().intern("prototype").0;
|
||
if let Some(proto_val) = self.resolve_property(ctor_obj, proto_si) {
|
||
if proto_val.is_object() {
|
||
let new_obj_mut = unsafe { &mut *new_obj };
|
||
let proto_obj_ptr = proto_val.as_js_object_ptr();
|
||
let _ = new_obj_mut.set_proto(JsValue::from_js_object(proto_obj_ptr));
|
||
}
|
||
}
|
||
let new_obj_val = JsValue::object(new_obj as *mut u8);
|
||
|
||
if ctor_obj.native_fn().is_some() {
|
||
// native 构造器:receiver 为新对象,值传递调用。
|
||
match self.call_function_sync(constructor, new_obj_val, &args) {
|
||
Ok(v) => {
|
||
self.regs[rd] = if v.is_object() { v } else { new_obj_val };
|
||
Ok(false)
|
||
}
|
||
Err(_) => {
|
||
let exc = self
|
||
.last_uncaught_value
|
||
.take()
|
||
.unwrap_or_else(|| oxide_builtins::error::create_error(self, "constructor call failed"));
|
||
self.exception_value = Some(exc);
|
||
self.pending_error_kind = Some(self.thrown_error_kind(exc));
|
||
self.unwind().map(|_| true)
|
||
}
|
||
}
|
||
} else if ctor_obj.sub_module_index() > 0 {
|
||
// 生成器函数不是构造器:`new g()` 抛 TypeError。
|
||
if (ctor_obj.sub_module_index() as usize) < self.sub_modules.len()
|
||
&& self.sub_modules[ctor_obj.sub_module_index() as usize].is_generator
|
||
{
|
||
return self.raise_type_error("g is not a constructor").map(|_| true);
|
||
}
|
||
// 异步函数不是构造器:`new f()` 抛 TypeError。
|
||
if (ctor_obj.sub_module_index() as usize) < self.sub_modules.len()
|
||
&& self.sub_modules[ctor_obj.sub_module_index() as usize].is_async
|
||
{
|
||
return self.raise_type_error("g is not a constructor").map(|_| true);
|
||
}
|
||
let this_value = if ctor_obj.is_derived_constructor() {
|
||
JsValue::undefined()
|
||
} else {
|
||
new_obj_val
|
||
};
|
||
self.push_bytecode_frame(
|
||
constructor,
|
||
this_value,
|
||
FrameArgs::Slice(&args),
|
||
Some(rd as u8),
|
||
Some(new_obj_val),
|
||
constructor,
|
||
FrameContinuation::None,
|
||
0,
|
||
)?;
|
||
Ok(true)
|
||
} else {
|
||
let error =
|
||
oxide_builtins::error::create_error(self, "NEW_EXPRESSION: bytecode constructors not yet supported");
|
||
self.exception_value = Some(error);
|
||
self.pending_error_kind = Some(self.thrown_error_kind(error));
|
||
self.unwind().map(|_| true)
|
||
}
|
||
}
|
||
|
||
/// SUPER_CALL_SPREAD:物化实参后按父构造器目标分派(native 走值传递,字节码走帧)。
|
||
pub(crate) fn dispatch_super_call_spread(&mut self, rd: usize, _a: usize) -> Result<bool, String> {
|
||
let words = self.read_spread_ext();
|
||
|
||
let Some(frame) = self.frames.last() else {
|
||
self.raise_error_kind("ReferenceError", "super() used outside class constructor")?;
|
||
return Ok(true);
|
||
};
|
||
if !frame.is_derived_constructor {
|
||
self.raise_error_kind("ReferenceError", "super() used outside derived constructor")?;
|
||
return Ok(true);
|
||
}
|
||
if frame.super_called {
|
||
self.raise_error_kind("ReferenceError", "super() called more than once")?;
|
||
return Ok(true);
|
||
}
|
||
let Some(derived_this) = frame.constructed_this else {
|
||
self.raise_error_kind("ReferenceError", "super() without derived this")?;
|
||
return Ok(true);
|
||
};
|
||
let callee = frame.callee;
|
||
|
||
let new_target = self.regs[255];
|
||
if !new_target.is_object() {
|
||
self.raise_error_kind("TypeError", "super() new.target is not an object")?;
|
||
return Ok(true);
|
||
}
|
||
let new_target_obj = unsafe { &*new_target.as_js_object_ptr() };
|
||
// 同 dispatch_super_call:super 构造器取当前帧 callee 的原型(newTarget
|
||
// 保持为最外层类,取其原型在中间 derived 层会反复压入同一父帧)。
|
||
if !callee.is_object() {
|
||
self.raise_error_kind("TypeError", "super() without constructor callee")?;
|
||
return Ok(true);
|
||
}
|
||
let callee_obj = unsafe { &*callee.as_js_object_ptr() };
|
||
let super_ctor = callee_obj.proto();
|
||
if !super_ctor.is_object() {
|
||
self.raise_error_kind("TypeError", "super constructor is not an object")?;
|
||
return Ok(true);
|
||
}
|
||
let super_obj = unsafe { &*super_ctor.as_js_object_ptr() };
|
||
if !super_obj.is_function() {
|
||
self.raise_error_kind("TypeError", "super constructor is not a function")?;
|
||
return Ok(true);
|
||
}
|
||
|
||
let args = match self.materialize_spread_args(&words)? {
|
||
Some(args) => args,
|
||
None => return Ok(true),
|
||
};
|
||
|
||
if super_obj.native_fn().is_some() {
|
||
match self.call_function_sync(super_ctor, derived_this, &args) {
|
||
Ok(val) => {
|
||
// super() 返回实例的 [[Prototype]] 须设为 new.target.prototype
|
||
let instance = if val.is_object() { val } else { derived_this };
|
||
if instance.is_object() {
|
||
self.set_constructed_proto(instance, new_target_obj)?;
|
||
}
|
||
self.regs[254] = instance;
|
||
self.regs[rd] = instance;
|
||
self.mark_super_called();
|
||
}
|
||
Err(_) => {
|
||
let exc = self
|
||
.last_uncaught_value
|
||
.take()
|
||
.unwrap_or_else(|| oxide_builtins::error::create_error(self, "super() call failed"));
|
||
self.exception_value = Some(exc);
|
||
self.pending_error_kind = Some(self.thrown_error_kind(exc));
|
||
self.unwind().map(|_| true)?;
|
||
}
|
||
}
|
||
Ok(false)
|
||
} else if super_obj.sub_module_index() > 0 {
|
||
self.push_bytecode_frame(
|
||
super_ctor,
|
||
derived_this,
|
||
FrameArgs::Slice(&args),
|
||
Some(254),
|
||
Some(derived_this),
|
||
new_target,
|
||
FrameContinuation::None,
|
||
0,
|
||
)?;
|
||
Ok(true)
|
||
} else {
|
||
self.raise_error_kind("TypeError", "super constructor is not callable")?;
|
||
Ok(true)
|
||
}
|
||
}
|
||
}
|