mirror of
https://github.com/pjh456/OxideJS.git
synced 2026-10-23 18:21:13 +08:00
refactor: builtin 实例化段拆出独立 construct 模块
This commit is contained in:
@@ -0,0 +1,589 @@
|
||||
//! 实例化职责:空槽构造原型/构造器对、Error 子类型、TypedArray 家族与全局
|
||||
//! 单例对象,并建立原型链链接(wire_ctor_proto / set_proto_if_changed /
|
||||
//! wire_builtin_world_links)。
|
||||
|
||||
use oxide_types::mem::P;
|
||||
use oxide_types::object::{JsObject, PropAttributes};
|
||||
use oxide_types::value::JsValue;
|
||||
|
||||
use super::BuiltinWorld;
|
||||
use crate::kernel_info;
|
||||
use crate::shape_forge::{ShapeForge, EMPTY_SHAPE_ID};
|
||||
use crate::string_forge::PermInterner;
|
||||
|
||||
fn intern_label(string_forge: &PermInterner, label: &str) -> u32 {
|
||||
string_forge.intern(label).0
|
||||
}
|
||||
|
||||
fn make_pair(
|
||||
string_forge: &PermInterner, shape_forge: &ShapeForge, name: &str, si_prototype: u32, si_constructor: u32,
|
||||
si_name: u32,
|
||||
) -> (P<JsObject>, P<JsObject>) {
|
||||
intern_label(string_forge, name);
|
||||
let name_si = string_forge.intern(name).0; // 同时 intern 构造器名作为属性值
|
||||
|
||||
let mut proto = JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::null());
|
||||
let mut ctor = JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::null());
|
||||
|
||||
let proto_shape = shape_forge.make_shape(EMPTY_SHAPE_ID, si_constructor);
|
||||
proto.set_shape_id(proto_shape);
|
||||
|
||||
let ctor_shape1 = shape_forge.make_shape(EMPTY_SHAPE_ID, si_prototype);
|
||||
let ctor_shape2 = shape_forge.make_shape(ctor_shape1, si_name);
|
||||
ctor.set_shape_id(ctor_shape2);
|
||||
ctor.set_function(true);
|
||||
|
||||
// 预分配槽位:proto[0]="constructor"、ctor[0]="prototype"、ctor[1]="name"。
|
||||
proto.ensure_hash_props().push(JsValue::undefined()); // 占位
|
||||
ctor.ensure_hash_props().push(JsValue::undefined()); // "prototype" 占位
|
||||
// 立即写入实际 name 值(ctor vec[1])。
|
||||
ctor.ensure_hash_props()
|
||||
.push(JsValue::perm_string(string_forge.string_ptr(name_si)));
|
||||
// 属性元数据:.prototype(ctor[0])= writable:false, enumerable:false, configurable:false。
|
||||
ctor.set_data_meta(0u32, oxide_types::object::PropAttributes::new(false, false, false));
|
||||
// .name(ctor[1])= writable:false, enumerable:false, configurable:true。
|
||||
ctor.set_data_meta(1u32, oxide_types::object::PropAttributes::new(false, false, true));
|
||||
// .constructor(proto[0])= writable:true, enumerable:false, configurable:true。
|
||||
// (JS 规范:prototype.constructor 非枚举,避免泄漏进 for-in。)
|
||||
proto.set_data_meta(0u32, oxide_types::object::PropAttributes::new(true, false, true));
|
||||
|
||||
(P::new(proto), P::new(ctor))
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
pub(crate) struct BuiltinLabels {
|
||||
prototype: u32,
|
||||
constructor: u32,
|
||||
name: u32,
|
||||
}
|
||||
|
||||
pub(crate) fn builtin_labels(string_forge: &PermInterner) -> BuiltinLabels {
|
||||
let labels = BuiltinLabels {
|
||||
prototype: intern_label(string_forge, "prototype"),
|
||||
constructor: intern_label(string_forge, "constructor"),
|
||||
name: intern_label(string_forge, "name"),
|
||||
};
|
||||
intern_label(string_forge, "length");
|
||||
intern_label(string_forge, "toString");
|
||||
intern_label(string_forge, "valueOf");
|
||||
labels
|
||||
}
|
||||
|
||||
pub(crate) fn make_named_pair(
|
||||
string_forge: &PermInterner, shape_forge: &ShapeForge, labels: BuiltinLabels, name: &str,
|
||||
) -> (P<JsObject>, P<JsObject>) {
|
||||
make_pair(string_forge, shape_forge, name, labels.prototype, labels.constructor, labels.name)
|
||||
}
|
||||
|
||||
pub(crate) fn make_error_subtypes(error_proto: &P<JsObject>) -> ErrorSubtypeProtos {
|
||||
let error_proto_val = JsValue::from_js_object(error_proto.as_ptr() as *mut JsObject);
|
||||
ErrorSubtypeProtos {
|
||||
type_error_proto: P::new(JsObject::new_empty(EMPTY_SHAPE_ID, error_proto_val)),
|
||||
reference_error_proto: P::new(JsObject::new_empty(EMPTY_SHAPE_ID, error_proto_val)),
|
||||
range_error_proto: P::new(JsObject::new_empty(EMPTY_SHAPE_ID, error_proto_val)),
|
||||
syntax_error_proto: P::new(JsObject::new_empty(EMPTY_SHAPE_ID, error_proto_val)),
|
||||
uri_error_proto: P::new(JsObject::new_empty(EMPTY_SHAPE_ID, error_proto_val)),
|
||||
eval_error_proto: P::new(JsObject::new_empty(EMPTY_SHAPE_ID, error_proto_val)),
|
||||
suppressed_error_proto: P::new(JsObject::new_empty(EMPTY_SHAPE_ID, error_proto_val)),
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) struct ErrorSubtypeProtos {
|
||||
pub(crate) type_error_proto: P<JsObject>,
|
||||
pub(crate) reference_error_proto: P<JsObject>,
|
||||
pub(crate) range_error_proto: P<JsObject>,
|
||||
pub(crate) syntax_error_proto: P<JsObject>,
|
||||
pub(crate) uri_error_proto: P<JsObject>,
|
||||
pub(crate) eval_error_proto: P<JsObject>,
|
||||
pub(crate) suppressed_error_proto: P<JsObject>,
|
||||
}
|
||||
|
||||
pub(crate) struct TypedArrayFamily {
|
||||
pub(crate) typed_array_constructor: P<JsObject>,
|
||||
pub(crate) typed_array_proto: P<JsObject>,
|
||||
pub(crate) int8array_constructor: P<JsObject>,
|
||||
pub(crate) int8array_proto: P<JsObject>,
|
||||
pub(crate) uint8array_constructor: P<JsObject>,
|
||||
pub(crate) uint8array_proto: P<JsObject>,
|
||||
pub(crate) uint8clampedarray_constructor: P<JsObject>,
|
||||
pub(crate) uint8clampedarray_proto: P<JsObject>,
|
||||
pub(crate) int16array_constructor: P<JsObject>,
|
||||
pub(crate) int16array_proto: P<JsObject>,
|
||||
pub(crate) uint16array_constructor: P<JsObject>,
|
||||
pub(crate) uint16array_proto: P<JsObject>,
|
||||
pub(crate) int32array_constructor: P<JsObject>,
|
||||
pub(crate) int32array_proto: P<JsObject>,
|
||||
pub(crate) uint32array_constructor: P<JsObject>,
|
||||
pub(crate) uint32array_proto: P<JsObject>,
|
||||
pub(crate) float32array_constructor: P<JsObject>,
|
||||
pub(crate) float32array_proto: P<JsObject>,
|
||||
pub(crate) float64array_constructor: P<JsObject>,
|
||||
pub(crate) float64array_proto: P<JsObject>,
|
||||
pub(crate) bigint64array_constructor: P<JsObject>,
|
||||
pub(crate) bigint64array_proto: P<JsObject>,
|
||||
pub(crate) biguint64array_constructor: P<JsObject>,
|
||||
pub(crate) biguint64array_proto: P<JsObject>,
|
||||
}
|
||||
|
||||
/// 建 `%TypedArray%` 抽象构造器对象:name=`TypedArray`、`prototype` 指向共享原型,
|
||||
/// 实际 native 实现由绑定层配置为恒抛 TypeError(不可 new 也不可调用)。
|
||||
fn make_typed_array_abstract_ctor(
|
||||
string_forge: &PermInterner, shape_forge: &ShapeForge, labels: BuiltinLabels, typed_array_proto: &P<JsObject>,
|
||||
) -> P<JsObject> {
|
||||
let name_si = string_forge.intern("TypedArray").0;
|
||||
let mut ctor = JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::null());
|
||||
let ctor_shape1 = shape_forge.make_shape(EMPTY_SHAPE_ID, labels.prototype);
|
||||
let ctor_shape2 = shape_forge.make_shape(ctor_shape1, labels.name);
|
||||
ctor.set_shape_id(ctor_shape2);
|
||||
ctor.set_function(true);
|
||||
ctor.ensure_hash_props()
|
||||
.push(JsValue::from_js_object(typed_array_proto.as_ptr() as *mut JsObject));
|
||||
ctor.ensure_hash_props()
|
||||
.push(JsValue::perm_string(string_forge.string_ptr(name_si)));
|
||||
// .prototype 不可写不可枚举不可配置;.name 不可写不可枚举可配置。
|
||||
ctor.set_data_meta(0, PropAttributes::new(false, false, false));
|
||||
ctor.set_data_meta(1, PropAttributes::new(false, false, true));
|
||||
P::new(ctor)
|
||||
}
|
||||
|
||||
pub(crate) fn make_typed_array_family(
|
||||
string_forge: &PermInterner, shape_forge: &ShapeForge, labels: BuiltinLabels, object_proto: &P<JsObject>,
|
||||
) -> TypedArrayFamily {
|
||||
let obj_proto_val = JsValue::from_js_object(object_proto.as_ptr() as *mut JsObject);
|
||||
// 给共享原型开 "constructor" 槽位(占位值在 wire 时填抽象构造器)。
|
||||
let mut typed_array_proto_obj = JsObject::new_empty(EMPTY_SHAPE_ID, obj_proto_val);
|
||||
let ctor_si = labels.constructor;
|
||||
let proto_shape = shape_forge.make_shape(typed_array_proto_obj.shape_id(), ctor_si);
|
||||
typed_array_proto_obj.set_shape_id(proto_shape);
|
||||
typed_array_proto_obj.ensure_hash_props().push(JsValue::undefined());
|
||||
typed_array_proto_obj.set_data_meta(0, PropAttributes::new(true, false, true));
|
||||
let typed_array_proto = P::new(typed_array_proto_obj);
|
||||
let typed_array_constructor = make_typed_array_abstract_ctor(string_forge, shape_forge, labels, &typed_array_proto);
|
||||
let (int8array_proto, int8array_constructor) = make_named_pair(string_forge, shape_forge, labels, "Int8Array");
|
||||
let (uint8array_proto, uint8array_constructor) = make_named_pair(string_forge, shape_forge, labels, "Uint8Array");
|
||||
let (uint8clampedarray_proto, uint8clampedarray_constructor) =
|
||||
make_named_pair(string_forge, shape_forge, labels, "Uint8ClampedArray");
|
||||
let (int16array_proto, int16array_constructor) = make_named_pair(string_forge, shape_forge, labels, "Int16Array");
|
||||
let (uint16array_proto, uint16array_constructor) =
|
||||
make_named_pair(string_forge, shape_forge, labels, "Uint16Array");
|
||||
let (int32array_proto, int32array_constructor) = make_named_pair(string_forge, shape_forge, labels, "Int32Array");
|
||||
let (uint32array_proto, uint32array_constructor) =
|
||||
make_named_pair(string_forge, shape_forge, labels, "Uint32Array");
|
||||
let (float32array_proto, float32array_constructor) =
|
||||
make_named_pair(string_forge, shape_forge, labels, "Float32Array");
|
||||
let (float64array_proto, float64array_constructor) =
|
||||
make_named_pair(string_forge, shape_forge, labels, "Float64Array");
|
||||
let (bigint64array_proto, bigint64array_constructor) =
|
||||
make_named_pair(string_forge, shape_forge, labels, "BigInt64Array");
|
||||
let (biguint64array_proto, biguint64array_constructor) =
|
||||
make_named_pair(string_forge, shape_forge, labels, "BigUint64Array");
|
||||
|
||||
TypedArrayFamily {
|
||||
typed_array_constructor,
|
||||
typed_array_proto,
|
||||
int8array_constructor,
|
||||
int8array_proto,
|
||||
uint8array_constructor,
|
||||
uint8array_proto,
|
||||
uint8clampedarray_constructor,
|
||||
uint8clampedarray_proto,
|
||||
int16array_constructor,
|
||||
int16array_proto,
|
||||
uint16array_constructor,
|
||||
uint16array_proto,
|
||||
int32array_constructor,
|
||||
int32array_proto,
|
||||
uint32array_constructor,
|
||||
uint32array_proto,
|
||||
float32array_constructor,
|
||||
float32array_proto,
|
||||
float64array_constructor,
|
||||
float64array_proto,
|
||||
bigint64array_constructor,
|
||||
bigint64array_proto,
|
||||
biguint64array_constructor,
|
||||
biguint64array_proto,
|
||||
}
|
||||
}
|
||||
|
||||
/// 用真实值覆盖(`make_pair` 设置的)占位槽。
|
||||
/// ctor.vec[0] = constructor.prototype → proto。
|
||||
/// proto.vec[0] = proto.constructor → ctor。
|
||||
fn wire_ctor_proto(ctor: &P<JsObject>, proto: &P<JsObject>) {
|
||||
let ctor_ptr = ctor.as_ptr() as *mut JsObject;
|
||||
let ctor = unsafe { &mut *ctor_ptr };
|
||||
let vec = ctor.ensure_hash_props();
|
||||
if !vec.is_empty() {
|
||||
vec[0] = JsValue::from_js_object(proto.as_ptr() as *mut JsObject);
|
||||
}
|
||||
let proto_ptr = proto.as_ptr() as *mut JsObject;
|
||||
let proto = unsafe { &mut *proto_ptr };
|
||||
let pvec = proto.ensure_hash_props();
|
||||
if !pvec.is_empty() {
|
||||
pvec[0] = JsValue::from_js_object(ctor_ptr);
|
||||
}
|
||||
}
|
||||
|
||||
fn set_proto_if_changed(obj: &P<JsObject>, proto: JsValue) {
|
||||
let ptr = obj.as_ptr() as *mut JsObject;
|
||||
let obj = unsafe { &mut *ptr };
|
||||
if obj.proto() != proto {
|
||||
obj.set_proto(proto).ok();
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn wire_builtin_world_links(world: &BuiltinWorld) {
|
||||
wire_ctor_proto(&world.object_constructor, &world.object_proto);
|
||||
wire_ctor_proto(&world.array_constructor, &world.array_proto);
|
||||
wire_ctor_proto(&world.function_constructor, &world.function_proto);
|
||||
wire_ctor_proto(&world.string_constructor, &world.string_proto);
|
||||
wire_ctor_proto(&world.number_constructor, &world.number_proto);
|
||||
wire_ctor_proto(&world.boolean_constructor, &world.boolean_proto);
|
||||
wire_ctor_proto(&world.error_constructor, &world.error_proto);
|
||||
wire_ctor_proto(&world.symbol_constructor, &world.symbol_proto);
|
||||
wire_ctor_proto(&world.date_constructor, &world.date_proto);
|
||||
wire_ctor_proto(&world.set_constructor, &world.set_proto);
|
||||
wire_ctor_proto(&world.map_constructor, &world.map_proto);
|
||||
wire_ctor_proto(&world.regexp_constructor, &world.regexp_proto);
|
||||
wire_ctor_proto(&world.array_buffer_constructor, &world.array_buffer_proto);
|
||||
wire_ctor_proto(&world.data_view_constructor, &world.data_view_proto);
|
||||
wire_ctor_proto(&world.int8array_constructor, &world.int8array_proto);
|
||||
wire_ctor_proto(&world.uint8array_constructor, &world.uint8array_proto);
|
||||
wire_ctor_proto(&world.uint8clampedarray_constructor, &world.uint8clampedarray_proto);
|
||||
wire_ctor_proto(&world.int16array_constructor, &world.int16array_proto);
|
||||
wire_ctor_proto(&world.uint16array_constructor, &world.uint16array_proto);
|
||||
wire_ctor_proto(&world.int32array_constructor, &world.int32array_proto);
|
||||
wire_ctor_proto(&world.uint32array_constructor, &world.uint32array_proto);
|
||||
wire_ctor_proto(&world.float32array_constructor, &world.float32array_proto);
|
||||
wire_ctor_proto(&world.float64array_constructor, &world.float64array_proto);
|
||||
wire_ctor_proto(&world.bigint64array_constructor, &world.bigint64array_proto);
|
||||
wire_ctor_proto(&world.biguint64array_constructor, &world.biguint64array_proto);
|
||||
wire_ctor_proto(&world.instant_constructor, &world.instant_proto);
|
||||
wire_ctor_proto(&world.plain_date_constructor, &world.plain_date_proto);
|
||||
wire_ctor_proto(&world.plain_time_constructor, &world.plain_time_proto);
|
||||
wire_ctor_proto(&world.duration_constructor, &world.duration_proto);
|
||||
wire_ctor_proto(&world.zoned_date_time_constructor, &world.zoned_date_time_proto);
|
||||
wire_ctor_proto(&world.plain_date_time_constructor, &world.plain_date_time_proto);
|
||||
wire_ctor_proto(&world.plain_month_day_constructor, &world.plain_month_day_proto);
|
||||
wire_ctor_proto(&world.plain_year_month_constructor, &world.plain_year_month_proto);
|
||||
wire_ctor_proto(&world.bigint_constructor, &world.bigint_proto);
|
||||
|
||||
// 所有内置构造器的 [[Prototype]] 指向 %FunctionPrototype%(ECMA-262 §17:
|
||||
// 标准内置函数对象均继承 Function.prototype;此前仅 TypedArray 构造器设置过)。
|
||||
let fn_proto_val = world.fn_proto_val();
|
||||
for ctor in [
|
||||
&world.object_constructor,
|
||||
&world.array_constructor,
|
||||
&world.function_constructor,
|
||||
&world.string_constructor,
|
||||
&world.number_constructor,
|
||||
&world.boolean_constructor,
|
||||
&world.error_constructor,
|
||||
&world.symbol_constructor,
|
||||
&world.date_constructor,
|
||||
&world.set_constructor,
|
||||
&world.map_constructor,
|
||||
&world.regexp_constructor,
|
||||
&world.array_buffer_constructor,
|
||||
&world.data_view_constructor,
|
||||
&world.bigint_constructor,
|
||||
&world.instant_constructor,
|
||||
&world.plain_date_constructor,
|
||||
&world.plain_time_constructor,
|
||||
&world.duration_constructor,
|
||||
&world.zoned_date_time_constructor,
|
||||
&world.plain_date_time_constructor,
|
||||
&world.plain_month_day_constructor,
|
||||
&world.plain_year_month_constructor,
|
||||
] {
|
||||
set_proto_if_changed(ctor, fn_proto_val);
|
||||
}
|
||||
|
||||
let obj_proto_val = JsValue::from_js_object(world.object_proto.as_ptr() as *mut JsObject);
|
||||
let non_object_protos: [&P<JsObject>; 25] = [
|
||||
&world.array_proto,
|
||||
&world.function_proto,
|
||||
&world.string_proto,
|
||||
&world.number_proto,
|
||||
&world.boolean_proto,
|
||||
&world.error_proto,
|
||||
&world.symbol_proto,
|
||||
&world.date_proto,
|
||||
&world.set_proto,
|
||||
&world.map_proto,
|
||||
&world.regexp_proto,
|
||||
&world.array_buffer_proto,
|
||||
&world.data_view_proto,
|
||||
&world.typed_array_proto,
|
||||
&world.instant_proto,
|
||||
&world.plain_date_proto,
|
||||
&world.plain_time_proto,
|
||||
&world.duration_proto,
|
||||
&world.zoned_date_time_proto,
|
||||
&world.plain_date_time_proto,
|
||||
&world.plain_month_day_proto,
|
||||
&world.plain_year_month_proto,
|
||||
&world.bigint_proto,
|
||||
&world.disposable_stack_proto,
|
||||
&world.async_disposable_stack_proto,
|
||||
];
|
||||
for proto in &non_object_protos {
|
||||
set_proto_if_changed(proto, obj_proto_val);
|
||||
}
|
||||
|
||||
// Temporal 命名空间对象(非构造器)继承 Object.prototype。
|
||||
set_proto_if_changed(&world.temporal_object, obj_proto_val);
|
||||
set_proto_if_changed(&world.temporal_now_object, obj_proto_val);
|
||||
|
||||
// Console 对象(单例命名空间)继承 Object.prototype。
|
||||
set_proto_if_changed(&world.console_object, obj_proto_val);
|
||||
|
||||
// 迭代器原型链:%IteratorPrototype% → Object.prototype;各集合迭代器原型
|
||||
// → %IteratorPrototype%(next/@@iterator 方法由绑定层安装到对应原型)。
|
||||
set_proto_if_changed(&world.iterator_proto, obj_proto_val);
|
||||
let iterator_proto_val = JsValue::from_js_object(world.iterator_proto.as_ptr() as *mut JsObject);
|
||||
let iterator_protos: [&P<JsObject>; 6] = [
|
||||
&world.array_iterator_proto,
|
||||
&world.map_iterator_proto,
|
||||
&world.set_iterator_proto,
|
||||
&world.string_iterator_proto,
|
||||
&world.regexp_string_iterator_proto,
|
||||
&world.iterator_helper_proto,
|
||||
];
|
||||
for proto in &iterator_protos {
|
||||
set_proto_if_changed(proto, iterator_proto_val);
|
||||
}
|
||||
|
||||
let typed_array_proto_val = JsValue::from_js_object(world.typed_array_proto.as_ptr() as *mut JsObject);
|
||||
let typed_array_protos: [&P<JsObject>; 11] = [
|
||||
&world.int8array_proto,
|
||||
&world.uint8array_proto,
|
||||
&world.uint8clampedarray_proto,
|
||||
&world.int16array_proto,
|
||||
&world.uint16array_proto,
|
||||
&world.int32array_proto,
|
||||
&world.uint32array_proto,
|
||||
&world.float32array_proto,
|
||||
&world.float64array_proto,
|
||||
&world.bigint64array_proto,
|
||||
&world.biguint64array_proto,
|
||||
];
|
||||
for proto in &typed_array_protos {
|
||||
set_proto_if_changed(proto, typed_array_proto_val);
|
||||
}
|
||||
|
||||
// 共享原型与抽象构造器互指(prototype/constructor);11 个具体构造器的
|
||||
// [[Prototype]] 指向 `%TypedArray%`,抽象构造器自身 [[Prototype]] 为 Function.prototype。
|
||||
wire_ctor_proto(&world.typed_array_constructor, &world.typed_array_proto);
|
||||
set_proto_if_changed(&world.typed_array_constructor, world.fn_proto_val());
|
||||
let typed_array_ctor_val = JsValue::from_js_object(world.typed_array_constructor.as_ptr() as *mut JsObject);
|
||||
let typed_array_ctors: [&P<JsObject>; 11] = [
|
||||
&world.int8array_constructor,
|
||||
&world.uint8array_constructor,
|
||||
&world.uint8clampedarray_constructor,
|
||||
&world.int16array_constructor,
|
||||
&world.uint16array_constructor,
|
||||
&world.int32array_constructor,
|
||||
&world.uint32array_constructor,
|
||||
&world.float32array_constructor,
|
||||
&world.float64array_constructor,
|
||||
&world.bigint64array_constructor,
|
||||
&world.biguint64array_constructor,
|
||||
];
|
||||
for ctor in &typed_array_ctors {
|
||||
set_proto_if_changed(ctor, typed_array_ctor_val);
|
||||
}
|
||||
}
|
||||
|
||||
impl BuiltinWorld {
|
||||
/// 全量构造一个全新的 builtin world:创建所有原型/构造器对、Error 子类型、
|
||||
/// TypedArray 家族与 well-known symbol 对象,并建立原型链链接。
|
||||
pub fn new(string_forge: &PermInterner, shape_forge: &ShapeForge) -> Self {
|
||||
let labels = builtin_labels(string_forge);
|
||||
|
||||
let (object_proto, object_constructor) = make_named_pair(string_forge, shape_forge, labels, "Object");
|
||||
let (array_proto, array_constructor) = make_named_pair(string_forge, shape_forge, labels, "Array");
|
||||
let (function_proto, function_constructor) = make_named_pair(string_forge, shape_forge, labels, "Function");
|
||||
let (string_proto, string_constructor) = make_named_pair(string_forge, shape_forge, labels, "String");
|
||||
let (number_proto, number_constructor) = make_named_pair(string_forge, shape_forge, labels, "Number");
|
||||
let (boolean_proto, boolean_constructor) = make_named_pair(string_forge, shape_forge, labels, "Boolean");
|
||||
let (error_proto, error_constructor) = make_named_pair(string_forge, shape_forge, labels, "Error");
|
||||
let (symbol_proto, symbol_constructor) = make_named_pair(string_forge, shape_forge, labels, "Symbol");
|
||||
|
||||
let error_subtypes = make_error_subtypes(&error_proto);
|
||||
|
||||
let math_object = P::new(JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::null()));
|
||||
|
||||
let json_object = P::new(JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::null()));
|
||||
|
||||
let console_object = P::new(JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::null()));
|
||||
|
||||
let (date_proto, date_constructor) = make_named_pair(string_forge, shape_forge, labels, "Date");
|
||||
let (set_proto, set_constructor) = make_named_pair(string_forge, shape_forge, labels, "Set");
|
||||
let (map_proto, map_constructor) = make_named_pair(string_forge, shape_forge, labels, "Map");
|
||||
let (regexp_proto, regexp_constructor) = make_named_pair(string_forge, shape_forge, labels, "RegExp");
|
||||
let (array_buffer_proto, array_buffer_constructor) =
|
||||
make_named_pair(string_forge, shape_forge, labels, "ArrayBuffer");
|
||||
let (data_view_proto, data_view_constructor) = make_named_pair(string_forge, shape_forge, labels, "DataView");
|
||||
let typed_arrays = make_typed_array_family(string_forge, shape_forge, labels, &object_proto);
|
||||
|
||||
let sym_match = P::new(JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::null()));
|
||||
let sym_replace = P::new(JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::null()));
|
||||
let sym_search = P::new(JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::null()));
|
||||
let sym_split = P::new(JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::null()));
|
||||
let sym_iterator = P::new(JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::null()));
|
||||
let sym_to_primitive = P::new(JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::null()));
|
||||
let sym_has_instance = P::new(JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::null()));
|
||||
let sym_match_all = P::new(JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::null()));
|
||||
let sym_async_iterator = P::new(JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::null()));
|
||||
let sym_to_string_tag = P::new(JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::null()));
|
||||
let sym_species = P::new(JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::null()));
|
||||
let sym_async_dispose = P::new(JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::null()));
|
||||
let sym_dispose = P::new(JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::null()));
|
||||
let temporal_object = P::new(JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::null()));
|
||||
let temporal_now_object = P::new(JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::null()));
|
||||
let (instant_proto, instant_constructor) = make_named_pair(string_forge, shape_forge, labels, "Instant");
|
||||
let (plain_date_proto, plain_date_constructor) =
|
||||
make_named_pair(string_forge, shape_forge, labels, "PlainDate");
|
||||
let (plain_time_proto, plain_time_constructor) =
|
||||
make_named_pair(string_forge, shape_forge, labels, "PlainTime");
|
||||
let (duration_proto, duration_constructor) = make_named_pair(string_forge, shape_forge, labels, "Duration");
|
||||
let (zoned_date_time_proto, zoned_date_time_constructor) =
|
||||
make_named_pair(string_forge, shape_forge, labels, "ZonedDateTime");
|
||||
let (plain_date_time_proto, plain_date_time_constructor) =
|
||||
make_named_pair(string_forge, shape_forge, labels, "PlainDateTime");
|
||||
let (plain_month_day_proto, plain_month_day_constructor) =
|
||||
make_named_pair(string_forge, shape_forge, labels, "PlainMonthDay");
|
||||
let (plain_year_month_proto, plain_year_month_constructor) =
|
||||
make_named_pair(string_forge, shape_forge, labels, "PlainYearMonth");
|
||||
let (bigint_proto, bigint_constructor) = make_named_pair(string_forge, shape_forge, labels, "BigInt");
|
||||
let stub_objects = Vec::new();
|
||||
|
||||
// 迭代器原型家族:链关系(→ %IteratorPrototype% → Object.prototype)在
|
||||
// wire_builtin_world_links 中建立,next/@@iterator 方法由绑定层安装。
|
||||
let iterator_proto = P::new(JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::null()));
|
||||
let array_iterator_proto = P::new(JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::null()));
|
||||
let map_iterator_proto = P::new(JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::null()));
|
||||
let set_iterator_proto = P::new(JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::null()));
|
||||
let string_iterator_proto = P::new(JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::null()));
|
||||
let regexp_string_iterator_proto = P::new(JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::null()));
|
||||
let iterator_helper_proto = P::new(JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::null()));
|
||||
let disposable_stack_proto = P::new(JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::null()));
|
||||
let async_disposable_stack_proto = P::new(JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::null()));
|
||||
// 默认迭代器指针初值空(绑定层随后经 bind_string 捕获写入)。
|
||||
let string_default_iterator = std::cell::Cell::new(std::ptr::null());
|
||||
|
||||
let world = Self {
|
||||
object_proto,
|
||||
string_default_iterator,
|
||||
array_proto,
|
||||
function_proto,
|
||||
string_proto,
|
||||
number_proto,
|
||||
boolean_proto,
|
||||
error_proto,
|
||||
symbol_proto,
|
||||
object_constructor,
|
||||
array_constructor,
|
||||
function_constructor,
|
||||
string_constructor,
|
||||
number_constructor,
|
||||
boolean_constructor,
|
||||
error_constructor,
|
||||
symbol_constructor,
|
||||
type_error_proto: error_subtypes.type_error_proto,
|
||||
reference_error_proto: error_subtypes.reference_error_proto,
|
||||
range_error_proto: error_subtypes.range_error_proto,
|
||||
syntax_error_proto: error_subtypes.syntax_error_proto,
|
||||
uri_error_proto: error_subtypes.uri_error_proto,
|
||||
eval_error_proto: error_subtypes.eval_error_proto,
|
||||
suppressed_error_proto: error_subtypes.suppressed_error_proto,
|
||||
math_object,
|
||||
json_object,
|
||||
date_constructor,
|
||||
date_proto,
|
||||
set_constructor,
|
||||
set_proto,
|
||||
map_constructor,
|
||||
map_proto,
|
||||
regexp_constructor,
|
||||
regexp_proto,
|
||||
array_buffer_constructor,
|
||||
array_buffer_proto,
|
||||
data_view_constructor,
|
||||
data_view_proto,
|
||||
typed_array_proto: typed_arrays.typed_array_proto,
|
||||
typed_array_constructor: typed_arrays.typed_array_constructor,
|
||||
int8array_constructor: typed_arrays.int8array_constructor,
|
||||
int8array_proto: typed_arrays.int8array_proto,
|
||||
uint8array_constructor: typed_arrays.uint8array_constructor,
|
||||
uint8array_proto: typed_arrays.uint8array_proto,
|
||||
uint8clampedarray_constructor: typed_arrays.uint8clampedarray_constructor,
|
||||
uint8clampedarray_proto: typed_arrays.uint8clampedarray_proto,
|
||||
int16array_constructor: typed_arrays.int16array_constructor,
|
||||
int16array_proto: typed_arrays.int16array_proto,
|
||||
uint16array_constructor: typed_arrays.uint16array_constructor,
|
||||
uint16array_proto: typed_arrays.uint16array_proto,
|
||||
int32array_constructor: typed_arrays.int32array_constructor,
|
||||
int32array_proto: typed_arrays.int32array_proto,
|
||||
uint32array_constructor: typed_arrays.uint32array_constructor,
|
||||
uint32array_proto: typed_arrays.uint32array_proto,
|
||||
float32array_constructor: typed_arrays.float32array_constructor,
|
||||
float32array_proto: typed_arrays.float32array_proto,
|
||||
float64array_constructor: typed_arrays.float64array_constructor,
|
||||
float64array_proto: typed_arrays.float64array_proto,
|
||||
bigint64array_constructor: typed_arrays.bigint64array_constructor,
|
||||
bigint64array_proto: typed_arrays.bigint64array_proto,
|
||||
biguint64array_constructor: typed_arrays.biguint64array_constructor,
|
||||
biguint64array_proto: typed_arrays.biguint64array_proto,
|
||||
sym_match,
|
||||
sym_replace,
|
||||
sym_search,
|
||||
sym_split,
|
||||
sym_iterator,
|
||||
sym_to_primitive,
|
||||
sym_has_instance,
|
||||
sym_match_all,
|
||||
sym_async_iterator,
|
||||
sym_to_string_tag,
|
||||
sym_species,
|
||||
sym_async_dispose,
|
||||
sym_dispose,
|
||||
temporal_object,
|
||||
temporal_now_object,
|
||||
instant_constructor,
|
||||
instant_proto,
|
||||
plain_date_constructor,
|
||||
plain_date_proto,
|
||||
plain_time_constructor,
|
||||
plain_time_proto,
|
||||
duration_constructor,
|
||||
duration_proto,
|
||||
zoned_date_time_constructor,
|
||||
zoned_date_time_proto,
|
||||
plain_date_time_constructor,
|
||||
plain_date_time_proto,
|
||||
plain_month_day_constructor,
|
||||
plain_month_day_proto,
|
||||
plain_year_month_constructor,
|
||||
plain_year_month_proto,
|
||||
bigint_constructor,
|
||||
bigint_proto,
|
||||
iterator_proto,
|
||||
array_iterator_proto,
|
||||
map_iterator_proto,
|
||||
set_iterator_proto,
|
||||
string_iterator_proto,
|
||||
regexp_string_iterator_proto,
|
||||
iterator_helper_proto,
|
||||
disposable_stack_proto,
|
||||
async_disposable_stack_proto,
|
||||
stub_objects,
|
||||
console_object,
|
||||
leaked_objects: std::cell::RefCell::new(Vec::new()),
|
||||
};
|
||||
wire_builtin_world_links(&world);
|
||||
kernel_info!("BuiltinWorld initialized");
|
||||
world
|
||||
}
|
||||
}
|
||||
@@ -2,15 +2,13 @@
|
||||
//! 支持按脏标记重建,并提供绑定层的 native 方法指针表。
|
||||
|
||||
use oxide_types::mem::P;
|
||||
use oxide_types::object::{JsObject, NativeFnPtr, PropAttributes};
|
||||
use oxide_types::object::{JsObject, NativeFnPtr};
|
||||
use oxide_types::value::JsValue;
|
||||
|
||||
use crate::kernel::BuiltinId;
|
||||
use crate::kernel_info;
|
||||
use crate::shape_forge::{ShapeForge, EMPTY_SHAPE_ID};
|
||||
use crate::string_forge::PermInterner;
|
||||
|
||||
mod bind;
|
||||
mod construct;
|
||||
mod methods;
|
||||
mod rebuild;
|
||||
pub use methods::{ArrayMethods, ErrorMethods, FunctionMethods, ObjectMethods, RegExpMethods, StringMethods};
|
||||
@@ -223,390 +221,6 @@ struct LeakedSlot {
|
||||
key: Option<FnWrapperKey>,
|
||||
}
|
||||
|
||||
fn intern_label(string_forge: &PermInterner, label: &str) -> u32 {
|
||||
string_forge.intern(label).0
|
||||
}
|
||||
|
||||
fn make_pair(
|
||||
string_forge: &PermInterner, shape_forge: &ShapeForge, name: &str, si_prototype: u32, si_constructor: u32,
|
||||
si_name: u32,
|
||||
) -> (P<JsObject>, P<JsObject>) {
|
||||
intern_label(string_forge, name);
|
||||
let name_si = string_forge.intern(name).0; // 同时 intern 构造器名作为属性值
|
||||
|
||||
let mut proto = JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::null());
|
||||
let mut ctor = JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::null());
|
||||
|
||||
let proto_shape = shape_forge.make_shape(EMPTY_SHAPE_ID, si_constructor);
|
||||
proto.set_shape_id(proto_shape);
|
||||
|
||||
let ctor_shape1 = shape_forge.make_shape(EMPTY_SHAPE_ID, si_prototype);
|
||||
let ctor_shape2 = shape_forge.make_shape(ctor_shape1, si_name);
|
||||
ctor.set_shape_id(ctor_shape2);
|
||||
ctor.set_function(true);
|
||||
|
||||
// 预分配槽位:proto[0]="constructor"、ctor[0]="prototype"、ctor[1]="name"。
|
||||
proto.ensure_hash_props().push(JsValue::undefined()); // 占位
|
||||
ctor.ensure_hash_props().push(JsValue::undefined()); // "prototype" 占位
|
||||
// 立即写入实际 name 值(ctor vec[1])。
|
||||
ctor.ensure_hash_props()
|
||||
.push(JsValue::perm_string(string_forge.string_ptr(name_si)));
|
||||
// 属性元数据:.prototype(ctor[0])= writable:false, enumerable:false, configurable:false。
|
||||
ctor.set_data_meta(0u32, oxide_types::object::PropAttributes::new(false, false, false));
|
||||
// .name(ctor[1])= writable:false, enumerable:false, configurable:true。
|
||||
ctor.set_data_meta(1u32, oxide_types::object::PropAttributes::new(false, false, true));
|
||||
// .constructor(proto[0])= writable:true, enumerable:false, configurable:true。
|
||||
// (JS 规范:prototype.constructor 非枚举,避免泄漏进 for-in。)
|
||||
proto.set_data_meta(0u32, oxide_types::object::PropAttributes::new(true, false, true));
|
||||
|
||||
(P::new(proto), P::new(ctor))
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy)]
|
||||
struct BuiltinLabels {
|
||||
prototype: u32,
|
||||
constructor: u32,
|
||||
name: u32,
|
||||
}
|
||||
|
||||
fn builtin_labels(string_forge: &PermInterner) -> BuiltinLabels {
|
||||
let labels = BuiltinLabels {
|
||||
prototype: intern_label(string_forge, "prototype"),
|
||||
constructor: intern_label(string_forge, "constructor"),
|
||||
name: intern_label(string_forge, "name"),
|
||||
};
|
||||
intern_label(string_forge, "length");
|
||||
intern_label(string_forge, "toString");
|
||||
intern_label(string_forge, "valueOf");
|
||||
labels
|
||||
}
|
||||
|
||||
fn make_named_pair(
|
||||
string_forge: &PermInterner, shape_forge: &ShapeForge, labels: BuiltinLabels, name: &str,
|
||||
) -> (P<JsObject>, P<JsObject>) {
|
||||
make_pair(string_forge, shape_forge, name, labels.prototype, labels.constructor, labels.name)
|
||||
}
|
||||
|
||||
fn make_error_subtypes(error_proto: &P<JsObject>) -> ErrorSubtypeProtos {
|
||||
let error_proto_val = JsValue::from_js_object(error_proto.as_ptr() as *mut JsObject);
|
||||
ErrorSubtypeProtos {
|
||||
type_error_proto: P::new(JsObject::new_empty(EMPTY_SHAPE_ID, error_proto_val)),
|
||||
reference_error_proto: P::new(JsObject::new_empty(EMPTY_SHAPE_ID, error_proto_val)),
|
||||
range_error_proto: P::new(JsObject::new_empty(EMPTY_SHAPE_ID, error_proto_val)),
|
||||
syntax_error_proto: P::new(JsObject::new_empty(EMPTY_SHAPE_ID, error_proto_val)),
|
||||
uri_error_proto: P::new(JsObject::new_empty(EMPTY_SHAPE_ID, error_proto_val)),
|
||||
eval_error_proto: P::new(JsObject::new_empty(EMPTY_SHAPE_ID, error_proto_val)),
|
||||
suppressed_error_proto: P::new(JsObject::new_empty(EMPTY_SHAPE_ID, error_proto_val)),
|
||||
}
|
||||
}
|
||||
|
||||
struct ErrorSubtypeProtos {
|
||||
type_error_proto: P<JsObject>,
|
||||
reference_error_proto: P<JsObject>,
|
||||
range_error_proto: P<JsObject>,
|
||||
syntax_error_proto: P<JsObject>,
|
||||
uri_error_proto: P<JsObject>,
|
||||
eval_error_proto: P<JsObject>,
|
||||
suppressed_error_proto: P<JsObject>,
|
||||
}
|
||||
|
||||
struct TypedArrayFamily {
|
||||
typed_array_constructor: P<JsObject>,
|
||||
typed_array_proto: P<JsObject>,
|
||||
int8array_constructor: P<JsObject>,
|
||||
int8array_proto: P<JsObject>,
|
||||
uint8array_constructor: P<JsObject>,
|
||||
uint8array_proto: P<JsObject>,
|
||||
uint8clampedarray_constructor: P<JsObject>,
|
||||
uint8clampedarray_proto: P<JsObject>,
|
||||
int16array_constructor: P<JsObject>,
|
||||
int16array_proto: P<JsObject>,
|
||||
uint16array_constructor: P<JsObject>,
|
||||
uint16array_proto: P<JsObject>,
|
||||
int32array_constructor: P<JsObject>,
|
||||
int32array_proto: P<JsObject>,
|
||||
uint32array_constructor: P<JsObject>,
|
||||
uint32array_proto: P<JsObject>,
|
||||
float32array_constructor: P<JsObject>,
|
||||
float32array_proto: P<JsObject>,
|
||||
float64array_constructor: P<JsObject>,
|
||||
float64array_proto: P<JsObject>,
|
||||
bigint64array_constructor: P<JsObject>,
|
||||
bigint64array_proto: P<JsObject>,
|
||||
biguint64array_constructor: P<JsObject>,
|
||||
biguint64array_proto: P<JsObject>,
|
||||
}
|
||||
|
||||
/// 建 `%TypedArray%` 抽象构造器对象:name=`TypedArray`、`prototype` 指向共享原型,
|
||||
/// 实际 native 实现由绑定层配置为恒抛 TypeError(不可 new 也不可调用)。
|
||||
fn make_typed_array_abstract_ctor(
|
||||
string_forge: &PermInterner, shape_forge: &ShapeForge, labels: BuiltinLabels, typed_array_proto: &P<JsObject>,
|
||||
) -> P<JsObject> {
|
||||
let name_si = string_forge.intern("TypedArray").0;
|
||||
let mut ctor = JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::null());
|
||||
let ctor_shape1 = shape_forge.make_shape(EMPTY_SHAPE_ID, labels.prototype);
|
||||
let ctor_shape2 = shape_forge.make_shape(ctor_shape1, labels.name);
|
||||
ctor.set_shape_id(ctor_shape2);
|
||||
ctor.set_function(true);
|
||||
ctor.ensure_hash_props()
|
||||
.push(JsValue::from_js_object(typed_array_proto.as_ptr() as *mut JsObject));
|
||||
ctor.ensure_hash_props()
|
||||
.push(JsValue::perm_string(string_forge.string_ptr(name_si)));
|
||||
// .prototype 不可写不可枚举不可配置;.name 不可写不可枚举可配置。
|
||||
ctor.set_data_meta(0, PropAttributes::new(false, false, false));
|
||||
ctor.set_data_meta(1, PropAttributes::new(false, false, true));
|
||||
P::new(ctor)
|
||||
}
|
||||
|
||||
fn make_typed_array_family(
|
||||
string_forge: &PermInterner, shape_forge: &ShapeForge, labels: BuiltinLabels, object_proto: &P<JsObject>,
|
||||
) -> TypedArrayFamily {
|
||||
let obj_proto_val = JsValue::from_js_object(object_proto.as_ptr() as *mut JsObject);
|
||||
// 给共享原型开 "constructor" 槽位(占位值在 wire 时填抽象构造器)。
|
||||
let mut typed_array_proto_obj = JsObject::new_empty(EMPTY_SHAPE_ID, obj_proto_val);
|
||||
let ctor_si = labels.constructor;
|
||||
let proto_shape = shape_forge.make_shape(typed_array_proto_obj.shape_id(), ctor_si);
|
||||
typed_array_proto_obj.set_shape_id(proto_shape);
|
||||
typed_array_proto_obj.ensure_hash_props().push(JsValue::undefined());
|
||||
typed_array_proto_obj.set_data_meta(0, PropAttributes::new(true, false, true));
|
||||
let typed_array_proto = P::new(typed_array_proto_obj);
|
||||
let typed_array_constructor = make_typed_array_abstract_ctor(string_forge, shape_forge, labels, &typed_array_proto);
|
||||
let (int8array_proto, int8array_constructor) = make_named_pair(string_forge, shape_forge, labels, "Int8Array");
|
||||
let (uint8array_proto, uint8array_constructor) = make_named_pair(string_forge, shape_forge, labels, "Uint8Array");
|
||||
let (uint8clampedarray_proto, uint8clampedarray_constructor) =
|
||||
make_named_pair(string_forge, shape_forge, labels, "Uint8ClampedArray");
|
||||
let (int16array_proto, int16array_constructor) = make_named_pair(string_forge, shape_forge, labels, "Int16Array");
|
||||
let (uint16array_proto, uint16array_constructor) =
|
||||
make_named_pair(string_forge, shape_forge, labels, "Uint16Array");
|
||||
let (int32array_proto, int32array_constructor) = make_named_pair(string_forge, shape_forge, labels, "Int32Array");
|
||||
let (uint32array_proto, uint32array_constructor) =
|
||||
make_named_pair(string_forge, shape_forge, labels, "Uint32Array");
|
||||
let (float32array_proto, float32array_constructor) =
|
||||
make_named_pair(string_forge, shape_forge, labels, "Float32Array");
|
||||
let (float64array_proto, float64array_constructor) =
|
||||
make_named_pair(string_forge, shape_forge, labels, "Float64Array");
|
||||
let (bigint64array_proto, bigint64array_constructor) =
|
||||
make_named_pair(string_forge, shape_forge, labels, "BigInt64Array");
|
||||
let (biguint64array_proto, biguint64array_constructor) =
|
||||
make_named_pair(string_forge, shape_forge, labels, "BigUint64Array");
|
||||
|
||||
TypedArrayFamily {
|
||||
typed_array_constructor,
|
||||
typed_array_proto,
|
||||
int8array_constructor,
|
||||
int8array_proto,
|
||||
uint8array_constructor,
|
||||
uint8array_proto,
|
||||
uint8clampedarray_constructor,
|
||||
uint8clampedarray_proto,
|
||||
int16array_constructor,
|
||||
int16array_proto,
|
||||
uint16array_constructor,
|
||||
uint16array_proto,
|
||||
int32array_constructor,
|
||||
int32array_proto,
|
||||
uint32array_constructor,
|
||||
uint32array_proto,
|
||||
float32array_constructor,
|
||||
float32array_proto,
|
||||
float64array_constructor,
|
||||
float64array_proto,
|
||||
bigint64array_constructor,
|
||||
bigint64array_proto,
|
||||
biguint64array_constructor,
|
||||
biguint64array_proto,
|
||||
}
|
||||
}
|
||||
|
||||
/// 用真实值覆盖(`make_pair` 设置的)占位槽。
|
||||
/// ctor.vec[0] = constructor.prototype → proto。
|
||||
/// proto.vec[0] = proto.constructor → ctor。
|
||||
fn wire_ctor_proto(ctor: &P<JsObject>, proto: &P<JsObject>) {
|
||||
let ctor_ptr = ctor.as_ptr() as *mut JsObject;
|
||||
let ctor = unsafe { &mut *ctor_ptr };
|
||||
let vec = ctor.ensure_hash_props();
|
||||
if !vec.is_empty() {
|
||||
vec[0] = JsValue::from_js_object(proto.as_ptr() as *mut JsObject);
|
||||
}
|
||||
let proto_ptr = proto.as_ptr() as *mut JsObject;
|
||||
let proto = unsafe { &mut *proto_ptr };
|
||||
let pvec = proto.ensure_hash_props();
|
||||
if !pvec.is_empty() {
|
||||
pvec[0] = JsValue::from_js_object(ctor_ptr);
|
||||
}
|
||||
}
|
||||
|
||||
fn set_proto_if_changed(obj: &P<JsObject>, proto: JsValue) {
|
||||
let ptr = obj.as_ptr() as *mut JsObject;
|
||||
let obj = unsafe { &mut *ptr };
|
||||
if obj.proto() != proto {
|
||||
obj.set_proto(proto).ok();
|
||||
}
|
||||
}
|
||||
|
||||
fn wire_builtin_world_links(world: &BuiltinWorld) {
|
||||
wire_ctor_proto(&world.object_constructor, &world.object_proto);
|
||||
wire_ctor_proto(&world.array_constructor, &world.array_proto);
|
||||
wire_ctor_proto(&world.function_constructor, &world.function_proto);
|
||||
wire_ctor_proto(&world.string_constructor, &world.string_proto);
|
||||
wire_ctor_proto(&world.number_constructor, &world.number_proto);
|
||||
wire_ctor_proto(&world.boolean_constructor, &world.boolean_proto);
|
||||
wire_ctor_proto(&world.error_constructor, &world.error_proto);
|
||||
wire_ctor_proto(&world.symbol_constructor, &world.symbol_proto);
|
||||
wire_ctor_proto(&world.date_constructor, &world.date_proto);
|
||||
wire_ctor_proto(&world.set_constructor, &world.set_proto);
|
||||
wire_ctor_proto(&world.map_constructor, &world.map_proto);
|
||||
wire_ctor_proto(&world.regexp_constructor, &world.regexp_proto);
|
||||
wire_ctor_proto(&world.array_buffer_constructor, &world.array_buffer_proto);
|
||||
wire_ctor_proto(&world.data_view_constructor, &world.data_view_proto);
|
||||
wire_ctor_proto(&world.int8array_constructor, &world.int8array_proto);
|
||||
wire_ctor_proto(&world.uint8array_constructor, &world.uint8array_proto);
|
||||
wire_ctor_proto(&world.uint8clampedarray_constructor, &world.uint8clampedarray_proto);
|
||||
wire_ctor_proto(&world.int16array_constructor, &world.int16array_proto);
|
||||
wire_ctor_proto(&world.uint16array_constructor, &world.uint16array_proto);
|
||||
wire_ctor_proto(&world.int32array_constructor, &world.int32array_proto);
|
||||
wire_ctor_proto(&world.uint32array_constructor, &world.uint32array_proto);
|
||||
wire_ctor_proto(&world.float32array_constructor, &world.float32array_proto);
|
||||
wire_ctor_proto(&world.float64array_constructor, &world.float64array_proto);
|
||||
wire_ctor_proto(&world.bigint64array_constructor, &world.bigint64array_proto);
|
||||
wire_ctor_proto(&world.biguint64array_constructor, &world.biguint64array_proto);
|
||||
wire_ctor_proto(&world.instant_constructor, &world.instant_proto);
|
||||
wire_ctor_proto(&world.plain_date_constructor, &world.plain_date_proto);
|
||||
wire_ctor_proto(&world.plain_time_constructor, &world.plain_time_proto);
|
||||
wire_ctor_proto(&world.duration_constructor, &world.duration_proto);
|
||||
wire_ctor_proto(&world.zoned_date_time_constructor, &world.zoned_date_time_proto);
|
||||
wire_ctor_proto(&world.plain_date_time_constructor, &world.plain_date_time_proto);
|
||||
wire_ctor_proto(&world.plain_month_day_constructor, &world.plain_month_day_proto);
|
||||
wire_ctor_proto(&world.plain_year_month_constructor, &world.plain_year_month_proto);
|
||||
wire_ctor_proto(&world.bigint_constructor, &world.bigint_proto);
|
||||
|
||||
// 所有内置构造器的 [[Prototype]] 指向 %FunctionPrototype%(ECMA-262 §17:
|
||||
// 标准内置函数对象均继承 Function.prototype;此前仅 TypedArray 构造器设置过)。
|
||||
let fn_proto_val = world.fn_proto_val();
|
||||
for ctor in [
|
||||
&world.object_constructor,
|
||||
&world.array_constructor,
|
||||
&world.function_constructor,
|
||||
&world.string_constructor,
|
||||
&world.number_constructor,
|
||||
&world.boolean_constructor,
|
||||
&world.error_constructor,
|
||||
&world.symbol_constructor,
|
||||
&world.date_constructor,
|
||||
&world.set_constructor,
|
||||
&world.map_constructor,
|
||||
&world.regexp_constructor,
|
||||
&world.array_buffer_constructor,
|
||||
&world.data_view_constructor,
|
||||
&world.bigint_constructor,
|
||||
&world.instant_constructor,
|
||||
&world.plain_date_constructor,
|
||||
&world.plain_time_constructor,
|
||||
&world.duration_constructor,
|
||||
&world.zoned_date_time_constructor,
|
||||
&world.plain_date_time_constructor,
|
||||
&world.plain_month_day_constructor,
|
||||
&world.plain_year_month_constructor,
|
||||
] {
|
||||
set_proto_if_changed(ctor, fn_proto_val);
|
||||
}
|
||||
|
||||
let obj_proto_val = JsValue::from_js_object(world.object_proto.as_ptr() as *mut JsObject);
|
||||
let non_object_protos: [&P<JsObject>; 25] = [
|
||||
&world.array_proto,
|
||||
&world.function_proto,
|
||||
&world.string_proto,
|
||||
&world.number_proto,
|
||||
&world.boolean_proto,
|
||||
&world.error_proto,
|
||||
&world.symbol_proto,
|
||||
&world.date_proto,
|
||||
&world.set_proto,
|
||||
&world.map_proto,
|
||||
&world.regexp_proto,
|
||||
&world.array_buffer_proto,
|
||||
&world.data_view_proto,
|
||||
&world.typed_array_proto,
|
||||
&world.instant_proto,
|
||||
&world.plain_date_proto,
|
||||
&world.plain_time_proto,
|
||||
&world.duration_proto,
|
||||
&world.zoned_date_time_proto,
|
||||
&world.plain_date_time_proto,
|
||||
&world.plain_month_day_proto,
|
||||
&world.plain_year_month_proto,
|
||||
&world.bigint_proto,
|
||||
&world.disposable_stack_proto,
|
||||
&world.async_disposable_stack_proto,
|
||||
];
|
||||
for proto in &non_object_protos {
|
||||
set_proto_if_changed(proto, obj_proto_val);
|
||||
}
|
||||
|
||||
// Temporal 命名空间对象(非构造器)继承 Object.prototype。
|
||||
set_proto_if_changed(&world.temporal_object, obj_proto_val);
|
||||
set_proto_if_changed(&world.temporal_now_object, obj_proto_val);
|
||||
|
||||
// Console 对象(单例命名空间)继承 Object.prototype。
|
||||
set_proto_if_changed(&world.console_object, obj_proto_val);
|
||||
|
||||
// 迭代器原型链:%IteratorPrototype% → Object.prototype;各集合迭代器原型
|
||||
// → %IteratorPrototype%(next/@@iterator 方法由绑定层安装到对应原型)。
|
||||
set_proto_if_changed(&world.iterator_proto, obj_proto_val);
|
||||
let iterator_proto_val = JsValue::from_js_object(world.iterator_proto.as_ptr() as *mut JsObject);
|
||||
let iterator_protos: [&P<JsObject>; 6] = [
|
||||
&world.array_iterator_proto,
|
||||
&world.map_iterator_proto,
|
||||
&world.set_iterator_proto,
|
||||
&world.string_iterator_proto,
|
||||
&world.regexp_string_iterator_proto,
|
||||
&world.iterator_helper_proto,
|
||||
];
|
||||
for proto in &iterator_protos {
|
||||
set_proto_if_changed(proto, iterator_proto_val);
|
||||
}
|
||||
|
||||
let typed_array_proto_val = JsValue::from_js_object(world.typed_array_proto.as_ptr() as *mut JsObject);
|
||||
let typed_array_protos: [&P<JsObject>; 11] = [
|
||||
&world.int8array_proto,
|
||||
&world.uint8array_proto,
|
||||
&world.uint8clampedarray_proto,
|
||||
&world.int16array_proto,
|
||||
&world.uint16array_proto,
|
||||
&world.int32array_proto,
|
||||
&world.uint32array_proto,
|
||||
&world.float32array_proto,
|
||||
&world.float64array_proto,
|
||||
&world.bigint64array_proto,
|
||||
&world.biguint64array_proto,
|
||||
];
|
||||
for proto in &typed_array_protos {
|
||||
set_proto_if_changed(proto, typed_array_proto_val);
|
||||
}
|
||||
|
||||
// 共享原型与抽象构造器互指(prototype/constructor);11 个具体构造器的
|
||||
// [[Prototype]] 指向 `%TypedArray%`,抽象构造器自身 [[Prototype]] 为 Function.prototype。
|
||||
wire_ctor_proto(&world.typed_array_constructor, &world.typed_array_proto);
|
||||
set_proto_if_changed(&world.typed_array_constructor, world.fn_proto_val());
|
||||
let typed_array_ctor_val = JsValue::from_js_object(world.typed_array_constructor.as_ptr() as *mut JsObject);
|
||||
let typed_array_ctors: [&P<JsObject>; 11] = [
|
||||
&world.int8array_constructor,
|
||||
&world.uint8array_constructor,
|
||||
&world.uint8clampedarray_constructor,
|
||||
&world.int16array_constructor,
|
||||
&world.uint16array_constructor,
|
||||
&world.int32array_constructor,
|
||||
&world.uint32array_constructor,
|
||||
&world.float32array_constructor,
|
||||
&world.float64array_constructor,
|
||||
&world.bigint64array_constructor,
|
||||
&world.biguint64array_constructor,
|
||||
];
|
||||
for ctor in &typed_array_ctors {
|
||||
set_proto_if_changed(ctor, typed_array_ctor_val);
|
||||
}
|
||||
}
|
||||
|
||||
impl BuiltinWorld {
|
||||
pub fn fn_proto_val(&self) -> JsValue {
|
||||
JsValue::from_js_object(self.function_proto.as_ptr() as *mut JsObject)
|
||||
@@ -936,202 +550,12 @@ impl BuiltinWorld {
|
||||
BuiltinId::Console => &self.console_object,
|
||||
}
|
||||
}
|
||||
|
||||
/// 全量构造一个全新的 builtin world:创建所有原型/构造器对、Error 子类型、
|
||||
/// TypedArray 家族与 well-known symbol 对象,并建立原型链链接。
|
||||
pub fn new(string_forge: &PermInterner, shape_forge: &ShapeForge) -> Self {
|
||||
let labels = builtin_labels(string_forge);
|
||||
|
||||
let (object_proto, object_constructor) = make_named_pair(string_forge, shape_forge, labels, "Object");
|
||||
let (array_proto, array_constructor) = make_named_pair(string_forge, shape_forge, labels, "Array");
|
||||
let (function_proto, function_constructor) = make_named_pair(string_forge, shape_forge, labels, "Function");
|
||||
let (string_proto, string_constructor) = make_named_pair(string_forge, shape_forge, labels, "String");
|
||||
let (number_proto, number_constructor) = make_named_pair(string_forge, shape_forge, labels, "Number");
|
||||
let (boolean_proto, boolean_constructor) = make_named_pair(string_forge, shape_forge, labels, "Boolean");
|
||||
let (error_proto, error_constructor) = make_named_pair(string_forge, shape_forge, labels, "Error");
|
||||
let (symbol_proto, symbol_constructor) = make_named_pair(string_forge, shape_forge, labels, "Symbol");
|
||||
|
||||
let error_subtypes = make_error_subtypes(&error_proto);
|
||||
|
||||
let math_object = P::new(JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::null()));
|
||||
|
||||
let json_object = P::new(JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::null()));
|
||||
|
||||
let console_object = P::new(JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::null()));
|
||||
|
||||
let (date_proto, date_constructor) = make_named_pair(string_forge, shape_forge, labels, "Date");
|
||||
let (set_proto, set_constructor) = make_named_pair(string_forge, shape_forge, labels, "Set");
|
||||
let (map_proto, map_constructor) = make_named_pair(string_forge, shape_forge, labels, "Map");
|
||||
let (regexp_proto, regexp_constructor) = make_named_pair(string_forge, shape_forge, labels, "RegExp");
|
||||
let (array_buffer_proto, array_buffer_constructor) =
|
||||
make_named_pair(string_forge, shape_forge, labels, "ArrayBuffer");
|
||||
let (data_view_proto, data_view_constructor) = make_named_pair(string_forge, shape_forge, labels, "DataView");
|
||||
let typed_arrays = make_typed_array_family(string_forge, shape_forge, labels, &object_proto);
|
||||
|
||||
let sym_match = P::new(JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::null()));
|
||||
let sym_replace = P::new(JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::null()));
|
||||
let sym_search = P::new(JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::null()));
|
||||
let sym_split = P::new(JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::null()));
|
||||
let sym_iterator = P::new(JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::null()));
|
||||
let sym_to_primitive = P::new(JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::null()));
|
||||
let sym_has_instance = P::new(JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::null()));
|
||||
let sym_match_all = P::new(JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::null()));
|
||||
let sym_async_iterator = P::new(JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::null()));
|
||||
let sym_to_string_tag = P::new(JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::null()));
|
||||
let sym_species = P::new(JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::null()));
|
||||
let sym_async_dispose = P::new(JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::null()));
|
||||
let sym_dispose = P::new(JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::null()));
|
||||
let temporal_object = P::new(JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::null()));
|
||||
let temporal_now_object = P::new(JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::null()));
|
||||
let (instant_proto, instant_constructor) = make_named_pair(string_forge, shape_forge, labels, "Instant");
|
||||
let (plain_date_proto, plain_date_constructor) =
|
||||
make_named_pair(string_forge, shape_forge, labels, "PlainDate");
|
||||
let (plain_time_proto, plain_time_constructor) =
|
||||
make_named_pair(string_forge, shape_forge, labels, "PlainTime");
|
||||
let (duration_proto, duration_constructor) = make_named_pair(string_forge, shape_forge, labels, "Duration");
|
||||
let (zoned_date_time_proto, zoned_date_time_constructor) =
|
||||
make_named_pair(string_forge, shape_forge, labels, "ZonedDateTime");
|
||||
let (plain_date_time_proto, plain_date_time_constructor) =
|
||||
make_named_pair(string_forge, shape_forge, labels, "PlainDateTime");
|
||||
let (plain_month_day_proto, plain_month_day_constructor) =
|
||||
make_named_pair(string_forge, shape_forge, labels, "PlainMonthDay");
|
||||
let (plain_year_month_proto, plain_year_month_constructor) =
|
||||
make_named_pair(string_forge, shape_forge, labels, "PlainYearMonth");
|
||||
let (bigint_proto, bigint_constructor) = make_named_pair(string_forge, shape_forge, labels, "BigInt");
|
||||
let stub_objects = Vec::new();
|
||||
|
||||
// 迭代器原型家族:链关系(→ %IteratorPrototype% → Object.prototype)在
|
||||
// wire_builtin_world_links 中建立,next/@@iterator 方法由绑定层安装。
|
||||
let iterator_proto = P::new(JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::null()));
|
||||
let array_iterator_proto = P::new(JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::null()));
|
||||
let map_iterator_proto = P::new(JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::null()));
|
||||
let set_iterator_proto = P::new(JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::null()));
|
||||
let string_iterator_proto = P::new(JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::null()));
|
||||
let regexp_string_iterator_proto = P::new(JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::null()));
|
||||
let iterator_helper_proto = P::new(JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::null()));
|
||||
let disposable_stack_proto = P::new(JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::null()));
|
||||
let async_disposable_stack_proto = P::new(JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::null()));
|
||||
// 默认迭代器指针初值空(绑定层随后经 bind_string 捕获写入)。
|
||||
let string_default_iterator = std::cell::Cell::new(std::ptr::null());
|
||||
|
||||
let world = Self {
|
||||
object_proto,
|
||||
string_default_iterator,
|
||||
array_proto,
|
||||
function_proto,
|
||||
string_proto,
|
||||
number_proto,
|
||||
boolean_proto,
|
||||
error_proto,
|
||||
symbol_proto,
|
||||
object_constructor,
|
||||
array_constructor,
|
||||
function_constructor,
|
||||
string_constructor,
|
||||
number_constructor,
|
||||
boolean_constructor,
|
||||
error_constructor,
|
||||
symbol_constructor,
|
||||
type_error_proto: error_subtypes.type_error_proto,
|
||||
reference_error_proto: error_subtypes.reference_error_proto,
|
||||
range_error_proto: error_subtypes.range_error_proto,
|
||||
syntax_error_proto: error_subtypes.syntax_error_proto,
|
||||
uri_error_proto: error_subtypes.uri_error_proto,
|
||||
eval_error_proto: error_subtypes.eval_error_proto,
|
||||
suppressed_error_proto: error_subtypes.suppressed_error_proto,
|
||||
math_object,
|
||||
json_object,
|
||||
date_constructor,
|
||||
date_proto,
|
||||
set_constructor,
|
||||
set_proto,
|
||||
map_constructor,
|
||||
map_proto,
|
||||
regexp_constructor,
|
||||
regexp_proto,
|
||||
array_buffer_constructor,
|
||||
array_buffer_proto,
|
||||
data_view_constructor,
|
||||
data_view_proto,
|
||||
typed_array_proto: typed_arrays.typed_array_proto,
|
||||
typed_array_constructor: typed_arrays.typed_array_constructor,
|
||||
int8array_constructor: typed_arrays.int8array_constructor,
|
||||
int8array_proto: typed_arrays.int8array_proto,
|
||||
uint8array_constructor: typed_arrays.uint8array_constructor,
|
||||
uint8array_proto: typed_arrays.uint8array_proto,
|
||||
uint8clampedarray_constructor: typed_arrays.uint8clampedarray_constructor,
|
||||
uint8clampedarray_proto: typed_arrays.uint8clampedarray_proto,
|
||||
int16array_constructor: typed_arrays.int16array_constructor,
|
||||
int16array_proto: typed_arrays.int16array_proto,
|
||||
uint16array_constructor: typed_arrays.uint16array_constructor,
|
||||
uint16array_proto: typed_arrays.uint16array_proto,
|
||||
int32array_constructor: typed_arrays.int32array_constructor,
|
||||
int32array_proto: typed_arrays.int32array_proto,
|
||||
uint32array_constructor: typed_arrays.uint32array_constructor,
|
||||
uint32array_proto: typed_arrays.uint32array_proto,
|
||||
float32array_constructor: typed_arrays.float32array_constructor,
|
||||
float32array_proto: typed_arrays.float32array_proto,
|
||||
float64array_constructor: typed_arrays.float64array_constructor,
|
||||
float64array_proto: typed_arrays.float64array_proto,
|
||||
bigint64array_constructor: typed_arrays.bigint64array_constructor,
|
||||
bigint64array_proto: typed_arrays.bigint64array_proto,
|
||||
biguint64array_constructor: typed_arrays.biguint64array_constructor,
|
||||
biguint64array_proto: typed_arrays.biguint64array_proto,
|
||||
sym_match,
|
||||
sym_replace,
|
||||
sym_search,
|
||||
sym_split,
|
||||
sym_iterator,
|
||||
sym_to_primitive,
|
||||
sym_has_instance,
|
||||
sym_match_all,
|
||||
sym_async_iterator,
|
||||
sym_to_string_tag,
|
||||
sym_species,
|
||||
sym_async_dispose,
|
||||
sym_dispose,
|
||||
temporal_object,
|
||||
temporal_now_object,
|
||||
instant_constructor,
|
||||
instant_proto,
|
||||
plain_date_constructor,
|
||||
plain_date_proto,
|
||||
plain_time_constructor,
|
||||
plain_time_proto,
|
||||
duration_constructor,
|
||||
duration_proto,
|
||||
zoned_date_time_constructor,
|
||||
zoned_date_time_proto,
|
||||
plain_date_time_constructor,
|
||||
plain_date_time_proto,
|
||||
plain_month_day_constructor,
|
||||
plain_month_day_proto,
|
||||
plain_year_month_constructor,
|
||||
plain_year_month_proto,
|
||||
bigint_constructor,
|
||||
bigint_proto,
|
||||
iterator_proto,
|
||||
array_iterator_proto,
|
||||
map_iterator_proto,
|
||||
set_iterator_proto,
|
||||
string_iterator_proto,
|
||||
regexp_string_iterator_proto,
|
||||
iterator_helper_proto,
|
||||
disposable_stack_proto,
|
||||
async_disposable_stack_proto,
|
||||
stub_objects,
|
||||
console_object,
|
||||
leaked_objects: std::cell::RefCell::new(Vec::new()),
|
||||
};
|
||||
wire_builtin_world_links(&world);
|
||||
kernel_info!("BuiltinWorld initialized");
|
||||
world
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::shape_forge::EMPTY_SHAPE_ID;
|
||||
|
||||
/// 选择性重建的释放 + 重指面动态自测:被替换旧 P 对象属性区恰好释放一次
|
||||
/// (置空可断言,含保活钉住对的属性区、本体钉保留),保留字段指针不变且
|
||||
|
||||
@@ -6,10 +6,11 @@ use oxide_types::mem::P;
|
||||
use oxide_types::object::JsObject;
|
||||
use oxide_types::value::JsValue;
|
||||
|
||||
use super::{
|
||||
use super::construct::{
|
||||
builtin_labels, make_error_subtypes, make_named_pair, make_typed_array_family, wire_builtin_world_links,
|
||||
BuiltinWorld, ErrorSubtypeProtos, TypedArrayFamily,
|
||||
ErrorSubtypeProtos, TypedArrayFamily,
|
||||
};
|
||||
use super::BuiltinWorld;
|
||||
use crate::kernel::BuiltinDirtySet;
|
||||
use crate::shape_forge::{ShapeForge, EMPTY_SHAPE_ID};
|
||||
use crate::string_forge::PermInterner;
|
||||
|
||||
Reference in New Issue
Block a user