Files
OxideJS-New/crates/oxide_kernel/src/builtin/rebuild.rs
T

627 lines
30 KiB
Rust
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
//! 脏重建职责:按脏标记选择性重建 builtin world(干净家族 Arc::clone 复用、
//! Function/Object 4 个对象经 `mem::forget` 抬升 Arc 计数永久保留),收尾把保留
//! 对象 proto 槽改写到新指针,并恰好释放一次被替换旧 P 对象的属性区。
use oxide_types::mem::P;
use oxide_types::object::JsObject;
use oxide_types::value::JsValue;
use super::construct::{
builtin_labels, make_error_subtypes, make_named_pair, make_typed_array_family, tag_boolean_proto, tag_number_proto,
tag_string_proto, wire_builtin_world_links, ErrorSubtypeProtos, TypedArrayFamily,
};
use super::{BindEnv, BuiltinWorld};
use crate::kernel::BuiltinDirtySet;
use crate::shape_forge::EMPTY_SHAPE_ID;
impl BuiltinWorld {
/// 选择性重建收尾:把保留对象的原型槽改写到新对象,并释放被替换旧对象的
/// 属性区。
///
/// 选择性重建([`Self::rebuild_with_dirty`])只为脏家族新建对象,未脏家族
/// 的新旧 world 持有同一个 `Arc` 对象。本函数在旧 world 被丢弃前做两件事:
///
/// 1. 原型槽改写:保留对象(登记表 wrapper 与新旧 world 共享的 P 字段)
/// 的 `[[Prototype]]` 槽若仍指向已被替换的旧对象,改写为对应的新对象;
/// 2. 释放:被替换旧 P 对象的四处堆外属性区(命名属性值 / 命名属性元数据 /
/// 数组元素 / 数组元素元数据)逐一释放并置空。
///
/// # 边界与前提
/// - 须在 `inherit_leaked_objects` 之后、旧 world 被替换前调用,且此刻
/// 无存活 VM(宿主的重置边界);
/// - 原型槽改写必须先于释放完成,否则保留对象的原型链会读到已释放的
/// 属性区;
/// - 替换集按逐字段新旧指针比较判定(stub 按指针集合),与保留集不相交:
/// 未替换字段的属性区归 session 收尾(`teardown_heap_data`)释放,此处
/// 不碰,不双放;
/// - Function/Object 4 个对象本体由 `rebuild_with_dirty` 经 `mem::forget`
/// 抬升 Arc 计数后永久保留(兜底用途见该函数注意事项);此处只释放其
/// 属性区——原型槽改写遗漏时读者看到的是属性静默缺失(本体存活),
/// 不是 use-after-free;
/// - 只改写原型槽;属性值之间的链接由同家族同批替换与绑定层重新同步
/// 覆盖,不在此处改写。
///
/// # 副作用
/// - 保留对象原型槽改写,每次改写递增该对象 generation;
/// - 被替换旧 P 对象四处属性区释放并置空(幂等,重入为 no-op)。
pub fn retire_replaced(&self, old: &BuiltinWorld) {
// 替换映射:逐字段新旧指针比较(stubs 按指针集合),记录被替换的
// 旧指针 → 新指针;stub 无继任者记空指针,只进释放集。
let old_fields = old.all_p_fields();
let new_fields = self.all_p_fields();
let mut remap: std::collections::HashMap<*mut JsObject, *mut JsObject> = std::collections::HashMap::new();
for (o, n) in old_fields.iter().zip(new_fields.iter()) {
let (op, np) = (o.as_ptr() as *mut JsObject, n.as_ptr() as *mut JsObject);
if !std::ptr::eq(op, np) {
remap.insert(op, np);
}
}
for p in &old.stub_objects {
let op = p.as_ptr() as *mut JsObject;
if !self.stub_objects.iter().any(|q| std::ptr::eq(q.as_ptr() as *mut JsObject, op)) {
remap.insert(op, std::ptr::null_mut());
}
}
if remap.is_empty() {
return;
}
// 原型槽改写:保留对象(新旧 world 同一指针)proto 槽仍指被替换旧
// 指针的,改写到新指针——与 `wire_builtin_world_links` 的
// set_proto_if_changed 同模式。
let repoint = |obj: &mut JsObject| {
let cur = obj.proto();
if !cur.is_object() {
return;
}
let cur_ptr = cur.as_js_object_ptr();
let Some(np) = remap.get(&cur_ptr).copied() else {
return;
};
if np.is_null() {
return;
}
// SAFETY: np 是本 world 的 P 对象;full_reset 是无存活 VM 的
// 时刻,无并发读者,成环检查由 set_proto 内部完成。
obj.set_proto(JsValue::from_js_object(np)).ok();
};
for (o, n) in old_fields.iter().zip(new_fields.iter()) {
let op = o.as_ptr() as *mut JsObject;
let np = n.as_ptr() as *mut JsObject;
if std::ptr::eq(op, np) {
// SAFETY: op/np 指向同一保留 P 对象;full_reset 是无存活 VM
// 的时刻,无并发读者。
unsafe {
repoint(&mut *np);
}
}
}
for slot in self.leaked_objects.borrow().iter() {
let ptr = slot.ptr;
// SAFETY: 登记表指针 session 存活期内有效;full_reset 是无存活 VM
// 的时刻,无并发读者。
unsafe {
repoint(&mut *ptr);
}
}
// 后置条件检查:原型槽改写后保留对象 proto 槽不得残留任何被替换旧指针。
for (o, n) in old_fields.iter().zip(new_fields.iter()) {
let op = o.as_ptr() as *mut JsObject;
let np = n.as_ptr() as *mut JsObject;
if std::ptr::eq(op, np) {
let cur = unsafe { (*np).proto() };
debug_assert!(
!cur.is_object() || !remap.contains_key(&cur.as_js_object_ptr()),
"保留字段 proto 槽不得残留被替换旧指针"
);
}
}
for slot in self.leaked_objects.borrow().iter() {
let cur = unsafe { (*slot.ptr).proto() };
debug_assert!(
!cur.is_object() || !remap.contains_key(&cur.as_js_object_ptr()),
"登记表 wrapper proto 槽不得残留被替换旧指针"
);
}
// 释放:被替换旧 P 对象属性区逐一恰好释放一次(本体不释放;经
// `mem::forget` 抬升 Arc 计数的 4 个对象保留本体、属性区同样释放)。
for &op in remap.keys() {
// SAFETY: op 是旧 world 被替换的 P 对象,属性区仅此一处释放并置空
// (幂等);full_reset 是无存活 VM 的时刻,无并发读者。
unsafe {
(&mut *op).release_raw_heap();
}
}
}
/// 按脏标记选择性重建 builtin world:仅重建被污染的对象家族,未污染的保留原指针。
///
/// # 注意事项
/// - Function/Object 家族脏时,先对旧的 `function_proto` /
/// `function_constructor` / `object_proto` / `object_constructor` 各用
/// `mem::forget` 抬升一次 Arc 计数(本体永久保留)再重建。原因:方法
/// wrapper 经 `Box::into_raw` 分配后登记在释放登记表、跨重建存活,其
/// `[[Prototype]]` 裸指针指向绑定时的旧 function_proto;执行期原型链查找
/// (如 `push.call` 沿 wrapper 原型链取 `call`)仍走这些对象,session
/// 重置只清执行态、不切断该路径,旧对 Arc 若在此归零则指针悬空。保留的
/// 本体同时充当 `retire_replaced` 原型槽改写遗漏的兜底:遗漏时读者仅见
/// 属性缺失,不产生 use-after-free。属性区于原型槽改写完成后由
/// `retire_replaced` 释放。
pub fn rebuild_with_dirty(env: BindEnv<'_>, dirty: &BuiltinDirtySet) -> BuiltinWorld {
let current = env.world;
let string_forge = env.string_forge;
let shape_forge = env.shape_forge;
let labels = builtin_labels(string_forge);
// 用 `mem::forget` 抬升 4 个对象(旧 Function/Object 对)的 Arc 计数
// 使其永不归零——保留对象的原型槽改写在 `retire_replaced`(本函数
// 返回后、旧 world 被替换前)完成,抬升计数的本体是原型槽改写遗漏
// 的兜底,不经任何路径释放。
if dirty.function || dirty.object {
std::mem::forget(current.function_proto.clone());
std::mem::forget(current.function_constructor.clone());
std::mem::forget(current.object_proto.clone());
std::mem::forget(current.object_constructor.clone());
}
let (object_proto, object_constructor) = if dirty.object {
make_named_pair(string_forge, shape_forge, labels, "Object")
} else {
(current.object_proto.clone(), current.object_constructor.clone())
};
let (array_proto, array_constructor) = if dirty.array {
make_named_pair(string_forge, shape_forge, labels, "Array")
} else {
(current.array_proto.clone(), current.array_constructor.clone())
};
let (function_proto, function_constructor) = if dirty.function {
make_named_pair(string_forge, shape_forge, labels, "Function")
} else {
(current.function_proto.clone(), current.function_constructor.clone())
};
let (string_proto, string_constructor) = if dirty.string {
// 脏重建与全量构造同形:原型本体须带 String 对象 tag 与空串包值
// (+length 物化),漏此分支 full_reset 后 tag 翻回 "Object"。
let (proto, ctor) = make_named_pair(string_forge, shape_forge, labels, "String");
tag_string_proto(&proto, string_forge, shape_forge);
(proto, ctor)
} else {
(current.string_proto.clone(), current.string_constructor.clone())
};
let (number_proto, number_constructor) = if dirty.number {
// 脏重建与全量构造同形:原型本体须带 Number 对象 tag 与 +0 包值,
// 漏此分支 full_reset 后 tag 翻回 "Object"。
let (proto, ctor) = make_named_pair(string_forge, shape_forge, labels, "Number");
tag_number_proto(&proto);
(proto, ctor)
} else {
(current.number_proto.clone(), current.number_constructor.clone())
};
let (boolean_proto, boolean_constructor) = if dirty.boolean {
// 脏重建与全量构造同形:原型本体须带 Boolean 对象 tag 与 false 包值,
// 漏此分支 full_reset 后 tag 翻回 "Object"。
let (proto, ctor) = make_named_pair(string_forge, shape_forge, labels, "Boolean");
tag_boolean_proto(&proto);
(proto, ctor)
} else {
(current.boolean_proto.clone(), current.boolean_constructor.clone())
};
let (error_proto, error_constructor, error_subtypes) = if dirty.error_family {
let (error_proto, error_constructor) = make_named_pair(string_forge, shape_forge, labels, "Error");
let error_subtypes = make_error_subtypes(&error_proto);
(error_proto, error_constructor, error_subtypes)
} else {
(
current.error_proto.clone(),
current.error_constructor.clone(),
ErrorSubtypeProtos {
type_error_proto: current.type_error_proto.clone(),
reference_error_proto: current.reference_error_proto.clone(),
range_error_proto: current.range_error_proto.clone(),
syntax_error_proto: current.syntax_error_proto.clone(),
uri_error_proto: current.uri_error_proto.clone(),
eval_error_proto: current.eval_error_proto.clone(),
suppressed_error_proto: current.suppressed_error_proto.clone(),
},
)
};
let (symbol_proto, symbol_constructor) = if dirty.symbol_family {
make_named_pair(string_forge, shape_forge, labels, "Symbol")
} else {
(current.symbol_proto.clone(), current.symbol_constructor.clone())
};
let math_object = if dirty.math {
P::new(JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::null()))
} else {
current.math_object.clone()
};
let json_object = if dirty.json {
P::new(JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::null()))
} else {
current.json_object.clone()
};
let (date_proto, date_constructor) = if dirty.date {
make_named_pair(string_forge, shape_forge, labels, "Date")
} else {
(current.date_proto.clone(), current.date_constructor.clone())
};
let (set_proto, set_constructor) = if dirty.set {
make_named_pair(string_forge, shape_forge, labels, "Set")
} else {
(current.set_proto.clone(), current.set_constructor.clone())
};
let (map_proto, map_constructor) = if dirty.map {
make_named_pair(string_forge, shape_forge, labels, "Map")
} else {
(current.map_proto.clone(), current.map_constructor.clone())
};
let (regexp_proto, regexp_constructor) = if dirty.regexp {
make_named_pair(string_forge, shape_forge, labels, "RegExp")
} else {
(current.regexp_proto.clone(), current.regexp_constructor.clone())
};
let (array_buffer_proto, array_buffer_constructor) = if dirty.array_buffer {
make_named_pair(string_forge, shape_forge, labels, "ArrayBuffer")
} else {
(current.array_buffer_proto.clone(), current.array_buffer_constructor.clone())
};
let (shared_array_buffer_proto, shared_array_buffer_constructor) = if dirty.shared_array_buffer {
make_named_pair(string_forge, shape_forge, labels, "SharedArrayBuffer")
} else {
(current.shared_array_buffer_proto.clone(), current.shared_array_buffer_constructor.clone())
};
let atomics_object = if dirty.atomics {
P::new(JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::null()))
} else {
current.atomics_object.clone()
};
let (data_view_proto, data_view_constructor) = if dirty.data_view {
make_named_pair(string_forge, shape_forge, labels, "DataView")
} else {
(current.data_view_proto.clone(), current.data_view_constructor.clone())
};
let typed_arrays = if dirty.typed_array_family {
make_typed_array_family(string_forge, shape_forge, labels, &object_proto)
} else {
TypedArrayFamily {
typed_array_proto: current.typed_array_proto.clone(),
typed_array_constructor: current.typed_array_constructor.clone(),
int8array_constructor: current.int8array_constructor.clone(),
int8array_proto: current.int8array_proto.clone(),
uint8array_constructor: current.uint8array_constructor.clone(),
uint8array_proto: current.uint8array_proto.clone(),
uint8clampedarray_constructor: current.uint8clampedarray_constructor.clone(),
uint8clampedarray_proto: current.uint8clampedarray_proto.clone(),
int16array_constructor: current.int16array_constructor.clone(),
int16array_proto: current.int16array_proto.clone(),
uint16array_constructor: current.uint16array_constructor.clone(),
uint16array_proto: current.uint16array_proto.clone(),
int32array_constructor: current.int32array_constructor.clone(),
int32array_proto: current.int32array_proto.clone(),
uint32array_constructor: current.uint32array_constructor.clone(),
uint32array_proto: current.uint32array_proto.clone(),
float32array_constructor: current.float32array_constructor.clone(),
float32array_proto: current.float32array_proto.clone(),
float64array_constructor: current.float64array_constructor.clone(),
float64array_proto: current.float64array_proto.clone(),
bigint64array_constructor: current.bigint64array_constructor.clone(),
bigint64array_proto: current.bigint64array_proto.clone(),
biguint64array_constructor: current.biguint64array_constructor.clone(),
biguint64array_proto: current.biguint64array_proto.clone(),
}
};
let (
temporal_object,
temporal_now_object,
instant_proto,
instant_constructor,
plain_date_proto,
plain_date_constructor,
plain_time_proto,
plain_time_constructor,
duration_proto,
duration_constructor,
zoned_date_time_proto,
zoned_date_time_constructor,
plain_date_time_proto,
plain_date_time_constructor,
plain_month_day_proto,
plain_month_day_constructor,
plain_year_month_proto,
plain_year_month_constructor,
) = if dirty.temporal {
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");
(
P::new(JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::null())),
P::new(JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::null())),
instant_proto,
instant_constructor,
plain_date_proto,
plain_date_constructor,
plain_time_proto,
plain_time_constructor,
duration_proto,
duration_constructor,
zoned_date_time_proto,
zoned_date_time_constructor,
plain_date_time_proto,
plain_date_time_constructor,
plain_month_day_proto,
plain_month_day_constructor,
plain_year_month_proto,
plain_year_month_constructor,
)
} else {
(
current.temporal_object.clone(),
current.temporal_now_object.clone(),
current.instant_proto.clone(),
current.instant_constructor.clone(),
current.plain_date_proto.clone(),
current.plain_date_constructor.clone(),
current.plain_time_proto.clone(),
current.plain_time_constructor.clone(),
current.duration_proto.clone(),
current.duration_constructor.clone(),
current.zoned_date_time_proto.clone(),
current.zoned_date_time_constructor.clone(),
current.plain_date_time_proto.clone(),
current.plain_date_time_constructor.clone(),
current.plain_month_day_proto.clone(),
current.plain_month_day_constructor.clone(),
current.plain_year_month_proto.clone(),
current.plain_year_month_constructor.clone(),
)
};
let (bigint_proto, bigint_constructor) = if dirty.stubs {
make_named_pair(string_forge, shape_forge, labels, "BigInt")
} else {
(current.bigint_proto.clone(), current.bigint_constructor.clone())
};
let stub_objects = if dirty.stubs { Vec::new() } else { current.stub_objects.clone() };
let console_object = if dirty.console {
P::new(JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::null()))
} else {
current.console_object.clone()
};
// MessagePort 原型与 MessageChannel 构造器:脏则换新空对象占位(与
// 全量构造同形),未脏沿用旧指针。
let (message_port_proto, message_channel_constructor) = if dirty.message_channel {
(
P::new(JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::null())),
P::new(JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::null())),
)
} else {
(current.message_port_proto.clone(), current.message_channel_constructor.clone())
};
// BroadcastChannel 原型与构造器:脏则换新空对象占位(与全量构造同形),
// 未脏沿用旧指针。
let (broadcast_channel_proto, broadcast_channel_constructor) = if dirty.broadcast_channel {
(
P::new(JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::null())),
P::new(JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::null())),
)
} else {
(current.broadcast_channel_proto.clone(), current.broadcast_channel_constructor.clone())
};
// Event 体系九个占位:脏则换新空对象(与全量构造同形),未脏沿用旧指针。
let (
event_proto,
event_constructor,
message_event_proto,
message_event_constructor,
error_event_proto,
error_event_constructor,
custom_event_proto,
custom_event_constructor,
event_target_proto,
) = if dirty.event {
(
P::new(JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::null())),
P::new(JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::null())),
P::new(JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::null())),
P::new(JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::null())),
P::new(JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::null())),
P::new(JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::null())),
P::new(JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::null())),
P::new(JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::null())),
P::new(JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::null())),
)
} else {
(
current.event_proto.clone(),
current.event_constructor.clone(),
current.message_event_proto.clone(),
current.message_event_constructor.clone(),
current.error_event_proto.clone(),
current.error_event_constructor.clone(),
current.custom_event_proto.clone(),
current.custom_event_constructor.clone(),
current.event_target_proto.clone(),
)
};
// 迭代器原型与资源栈原型依赖 Object.prototype(链到其上):object 家族重建时
// 一并重建,否则旧原型链指向已释放的 object_proto。
let (
iterator_proto,
array_iterator_proto,
map_iterator_proto,
set_iterator_proto,
string_iterator_proto,
regexp_string_iterator_proto,
async_iterator_proto,
iterator_helper_proto,
disposable_stack_proto,
async_disposable_stack_proto,
) = if dirty.object {
(
P::new(JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::null())),
P::new(JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::null())),
P::new(JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::null())),
P::new(JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::null())),
P::new(JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::null())),
P::new(JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::null())),
P::new(JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::null())),
P::new(JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::null())),
P::new(JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::null())),
P::new(JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::null())),
)
} else {
(
current.iterator_proto.clone(),
current.array_iterator_proto.clone(),
current.map_iterator_proto.clone(),
current.set_iterator_proto.clone(),
current.string_iterator_proto.clone(),
current.regexp_string_iterator_proto.clone(),
current.async_iterator_proto.clone(),
current.iterator_helper_proto.clone(),
current.disposable_stack_proto.clone(),
current.async_disposable_stack_proto.clone(),
)
};
let world = BuiltinWorld {
object_proto,
string_default_iterator: std::cell::Cell::new(if dirty.string {
std::ptr::null()
} else {
current.string_default_iterator.get()
}),
// %ThrowTypeError% 原型链挂 Function.prototype:function 家族脏时
// 置空由绑定层重建,未脏沿用旧对象(跨重建恒等)。
throw_type_error: std::cell::Cell::new(if dirty.function {
std::ptr::null()
} else {
current.throw_type_error.get()
}),
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,
shared_array_buffer_proto,
shared_array_buffer_constructor,
atomics_object,
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,
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,
async_iterator_proto,
iterator_helper_proto,
disposable_stack_proto,
async_disposable_stack_proto,
stub_objects,
console_object,
message_port_proto,
message_channel_constructor,
broadcast_channel_proto,
broadcast_channel_constructor,
event_proto,
event_constructor,
message_event_proto,
message_event_constructor,
error_event_proto,
error_event_constructor,
custom_event_proto,
custom_event_constructor,
event_target_proto,
leaked_objects: std::cell::RefCell::new(Vec::new()),
};
wire_builtin_world_links(&world);
world
}
}