mirror of
https://github.com/pjh456/OxideJS.git
synced 2026-10-24 02:31:13 +08:00
feat: arguments 对象绑定(CREATE_ARGUMENTS + 帧实参 spill 区)
This commit is contained in:
@@ -238,7 +238,7 @@ impl Vm {
|
||||
|
||||
/// 当前执行函数的闭包对象:普通路径取 frames 栈顶帧,inline(sync 回调)路径
|
||||
/// frames 被隔离为空,取 `inline_callee`。
|
||||
fn current_callee(&self) -> Option<JsValue> {
|
||||
pub(crate) fn current_callee(&self) -> Option<JsValue> {
|
||||
self.frames.last().map(|f| f.callee).or(self.inline_callee)
|
||||
}
|
||||
|
||||
@@ -465,6 +465,14 @@ impl Vm {
|
||||
let saved_this = self.regs[254];
|
||||
let saved_new_target = self.regs[255];
|
||||
|
||||
// 完整实参写入 spill 栈实参区(在帧的 spill 区之前),供 CREATE_ARGUMENTS 使用。
|
||||
let args_base = self.spill_stack.len() as u32;
|
||||
for i in 0..arg_count {
|
||||
let src_reg = first_arg_reg.wrapping_add(i as u8) as usize;
|
||||
self.spill_stack.push(self.regs[src_reg]);
|
||||
}
|
||||
let args_count = arg_count.min(u16::MAX as usize) as u16;
|
||||
|
||||
for i in 0..sub_n_args {
|
||||
let src_reg = first_arg_reg.wrapping_add(i as u8) as usize;
|
||||
self.regs[sub_param_base + i] = self.regs[src_reg];
|
||||
@@ -487,6 +495,8 @@ impl Vm {
|
||||
caller_reg_limit,
|
||||
saved_reg_offset,
|
||||
spill_offset: self.spill_stack.len() as u32,
|
||||
arguments_base: args_base,
|
||||
arguments_count: args_count,
|
||||
saved_this,
|
||||
saved_new_target,
|
||||
callee: super_ctor,
|
||||
|
||||
@@ -2,7 +2,7 @@ use crate::vm::Vm;
|
||||
use crate::{vm_error, vm_trace};
|
||||
use oxide_bytecode::opcode;
|
||||
use oxide_kernel::shape_forge::EMPTY_SHAPE_ID;
|
||||
use oxide_types::object::JsObject;
|
||||
use oxide_types::object::{JsObject, PropAttributes};
|
||||
use oxide_types::value::JsValue;
|
||||
|
||||
impl Vm {
|
||||
@@ -132,6 +132,42 @@ impl Vm {
|
||||
self.regs[rd] = JsValue::object(obj as *mut u8);
|
||||
}
|
||||
|
||||
/// 创建 arguments 对象:索引属性取当前帧(或 inline 同步调用)的完整实参,
|
||||
/// 附 length / callee 属性。第一版为 unmapped(非严格)语义,索引与形参不同步。
|
||||
///
|
||||
/// # 边界与前提
|
||||
/// - 实参区由 `push_bytecode_frame` / `dispatch_super_call` / `dispatch_new_expression`
|
||||
/// 在推帧时写入 spill 栈;frames 为空(inline 同步调用)时读 `inline_args_*`。
|
||||
/// - 索引属性用 shape 槽存储(普通对象),length/callee 为不可枚举数据属性。
|
||||
pub(crate) fn dispatch_create_arguments(&mut self, rd: usize) -> Result<(), String> {
|
||||
let (base, count) = match self.frames.last() {
|
||||
Some(frame) => (frame.arguments_base, frame.arguments_count),
|
||||
None => (self.inline_args_base, self.inline_args_count),
|
||||
};
|
||||
let proto_ptr = &*self.object_prototype as *const JsObject as *mut JsObject;
|
||||
let obj_ptr = self.alloc_object(JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::from_js_object(proto_ptr)));
|
||||
let obj = unsafe { &mut *obj_ptr };
|
||||
|
||||
// 索引属性:按实参下标写入 shape 槽,属性描述符为默认(可写/可枚举/可配置)。
|
||||
for i in 0..count as usize {
|
||||
let si = self.kernel_core.perm_interner().intern(&i.to_string()).0;
|
||||
let val = self.spill_stack.get(base as usize + i).copied().unwrap_or(JsValue::undefined());
|
||||
self.set_or_create_prop_value(obj, si, val);
|
||||
}
|
||||
|
||||
// length:实参个数,可写、不可枚举、可配置。
|
||||
let length_si = self.kernel_core.perm_interner().intern("length").0;
|
||||
self.define_data_property(obj, length_si, JsValue::int(count as i32), PropAttributes::new(true, false, true))?;
|
||||
|
||||
// callee:当前执行函数,可写、不可枚举、可配置(严格模式应抛 TypeError,未支持)。
|
||||
let callee_si = self.kernel_core.perm_interner().intern("callee").0;
|
||||
let callee = self.current_callee().unwrap_or(JsValue::undefined());
|
||||
self.define_data_property(obj, callee_si, callee, PropAttributes::new(true, false, true))?;
|
||||
|
||||
self.regs[rd] = JsValue::from_js_object(obj_ptr);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub(crate) fn dispatch_new_array(&mut self, rd: usize, instr: u32) {
|
||||
let n = opcode::imm16(instr) as usize;
|
||||
|
||||
Reference in New Issue
Block a user