feat: TypedArray 第一批解锁(%TypedArray% 构造器、原型访问器、of/from、bind 绑参、harness)

This commit is contained in:
2026-08-09 12:26:31 +08:00
parent 6c79dbb21c
commit 2bebd822d0
13 changed files with 475 additions and 82 deletions
@@ -1,11 +1,60 @@
use std::sync::Arc;
use crate::bind_constructor;
use crate::bindings::{apply_binding_table, configure_native_constructor};
use crate::bindings::{apply_binding_table, bind_accessor_getter, configure_native_constructor};
use oxide_kernel::kernel::{KernelCore, KernelSession};
use oxide_types::object::{JsObject, PropAttributes};
use oxide_types::value::JsValue;
/// 把 `%TypedArray%` 抽象构造器的 native 实现配置为恒抛 TypeError(不可 new/不可调用),
/// 设置 `length` 属性为 0,并挂载静态 `of`/`from`(具体构造器经原型链继承)。
fn bind_typed_array_abstract_ctor(core: &Arc<KernelCore>, session: &KernelSession) {
let ctor_ptr = session.builtin_world().typed_array_constructor.as_ptr() as *mut JsObject;
let ctor = unsafe { &mut *ctor_ptr };
configure_native_constructor(
ctor,
oxide_builtins::typed_array::typed_array_abstract_constructor::<crate::vm::Vm> as *const (),
0,
);
let length_si = core.perm_interner().intern("length").0;
let length_shape = core.shape_forge().make_shape(ctor.shape_id(), length_si);
ctor.set_shape_id(length_shape);
ctor.ensure_hash_props().push(JsValue::int(0));
let pos = ctor.hash_props_vec().map_or(0, |v| v.len() as u32).saturating_sub(1);
ctor.set_data_meta(pos, PropAttributes::new(false, false, true));
let sf = core.perm_interner().as_ref();
let sh = core.shape_forge().as_ref();
let world = session.builtin_world();
let ctor_ptr = world.typed_array_constructor.as_ptr() as *mut JsObject;
let ctor = unsafe { &mut *ctor_ptr };
// SAFETY: of/from 是转成 *const () 的 NativeFn 函数项指针。
let _ = world.bind_method(
ctor,
sh,
sf,
"of",
unsafe {
oxide_types::object::NativeFnPtr::from_raw(
oxide_builtins::typed_array::typed_array_of::<crate::vm::Vm> as *const (),
)
},
0,
);
let _ = world.bind_method(
ctor,
sh,
sf,
"from",
unsafe {
oxide_types::object::NativeFnPtr::from_raw(
oxide_builtins::typed_array::typed_array_from::<crate::vm::Vm> as *const (),
)
},
1,
);
}
/// 给构造器与对应原型设置 `BYTES_PER_ELEMENT`(只读、不可枚举、不可配置)。
///
/// # 步骤
@@ -34,8 +83,11 @@ fn set_bypes_per_element(core: &Arc<KernelCore>, ctor_ptr: *mut JsObject, proto_
macro_rules! bind_typed_array_constructor {
($core:expr, $global:expr, $name:literal, $ctor_ptr:expr, $proto_ptr:expr, $bpe:expr, $ctor_fn:path) => {{
let ctor = unsafe { &mut *$ctor_ptr };
configure_native_constructor(ctor, ($ctor_fn as fn(&mut $crate::vm::Vm, &[u8]) -> oxide_runtime_api::NativeResult) as *const (), 1);
bind_constructor!($core, $global, $name, $ctor_ptr, $ctor_fn, 1, hash: true);
configure_native_constructor(ctor, ($ctor_fn as fn(&mut $crate::vm::Vm, &[u8]) -> oxide_runtime_api::NativeResult) as *const (), 3);
bind_constructor!($core, $global, $name, $ctor_ptr, $ctor_fn, 3, hash: true);
// Function.length 描述符:不可写、不可枚举、可配置。
let len_pos = ctor.hash_props_vec().map_or(0, |v| v.len() as u32).saturating_sub(1);
ctor.set_data_meta(len_pos, PropAttributes::new(false, false, true));
set_bypes_per_element($core, $ctor_ptr, $proto_ptr, $bpe);
}};
}
@@ -58,14 +110,49 @@ pub fn bind_typed_array(core: &Arc<KernelCore>, session: &KernelSession, global:
oxide_builtins::typed_array::typed_array_subarray::<crate::vm::Vm> as *const (),
2,
),
(
"toString",
oxide_builtins::typed_array::typed_array_to_string::<crate::vm::Vm> as *const (),
0,
),
],
);
// 原型访问器:视图属性(buffer/byteOffset/byteLength/length)读内部数据槽,
// @@toStringTag 返回具体类型名,供 Object.prototype.toString 区分类型。
bind_accessor_getter(
core,
session,
shared_proto,
"buffer",
oxide_builtins::typed_array::typed_array_buffer_getter::<crate::vm::Vm> as *const (),
);
bind_accessor_getter(
core,
session,
shared_proto,
"byteOffset",
oxide_builtins::typed_array::typed_array_byte_offset_getter::<crate::vm::Vm> as *const (),
);
bind_accessor_getter(
core,
session,
shared_proto,
"byteLength",
oxide_builtins::typed_array::typed_array_byte_length_getter::<crate::vm::Vm> as *const (),
);
bind_accessor_getter(
core,
session,
shared_proto,
"length",
oxide_builtins::typed_array::typed_array_length_getter::<crate::vm::Vm> as *const (),
);
bind_accessor_getter(
core,
session,
shared_proto,
"@@toStringTag",
oxide_builtins::typed_array::typed_array_to_string_tag_getter::<crate::vm::Vm> as *const (),
);
bind_typed_array_abstract_ctor(core, session);
bind_typed_array_constructor!(
core,
global,
+1 -1
View File
@@ -502,7 +502,7 @@ pub fn bind_global_builtin_slots(core: &Arc<KernelCore>, session: &KernelSession
oxide_builtins::typed_array::biguint64array_constructor::<crate::vm::Vm> as *const (),
),
] {
configure_existing_ctor(ctor, native_fn, 1);
configure_existing_ctor(ctor, native_fn, 3);
bind_existing_global(core, global, name, JsValue::from_js_object(ctor.as_ptr() as *mut JsObject));
}