Files
OxideJS-New/crates/oxide_kernel/tests/builtin_world_tests.rs
T

142 lines
4.9 KiB
Rust

use oxide_kernel::builtin::BuiltinWorld;
use oxide_kernel::kernel::BuiltinDirtySet;
use oxide_kernel::shape_forge::{ShapeForge, EMPTY_SHAPE_ID};
use oxide_kernel::string_forge::PermInterner;
use oxide_types::object::JsObject;
fn make_world() -> BuiltinWorld {
let sf = PermInterner::new();
let sh = ShapeForge::new();
BuiltinWorld::new(&sf, &sh)
}
#[test]
fn test_all_protos_valid() {
let w = make_world();
let protos = [
&w.object_proto,
&w.array_proto,
&w.function_proto,
&w.string_proto,
&w.number_proto,
&w.boolean_proto,
&w.error_proto,
&w.symbol_proto,
];
for p in protos {
assert!(p.shape_id() > EMPTY_SHAPE_ID, "proto should have a non-empty shape");
}
}
#[test]
fn test_all_constructors_valid() {
let w = make_world();
assert!(w.object_constructor.is_function());
assert!(w.array_constructor.is_function());
assert!(w.function_constructor.is_function());
assert!(w.string_constructor.is_function());
assert!(w.number_constructor.is_function());
assert!(w.boolean_constructor.is_function());
assert!(w.error_constructor.is_function());
assert!(w.symbol_constructor.is_function());
}
#[test]
fn test_prototypes_are_not_functions() {
let w = make_world();
assert!(!w.object_proto.is_function());
assert!(!w.array_proto.is_function());
assert!(!w.function_proto.is_function());
assert!(!w.string_proto.is_function());
assert!(!w.number_proto.is_function());
assert!(!w.boolean_proto.is_function());
assert!(!w.error_proto.is_function());
assert!(!w.symbol_proto.is_function());
}
#[test]
fn test_protos_have_null_proto() {
let w = make_world();
// Object.prototype 是根——其 __proto__ 为 null。
assert!(w.object_proto.proto().is_null());
// 其余构造器原型均继承自 Object.prototype。
assert!(w.array_proto.proto().is_object());
assert!(w.function_proto.proto().is_object());
assert!(w.string_proto.proto().is_object());
assert!(w.number_proto.proto().is_object());
assert!(w.boolean_proto.proto().is_object());
assert!(w.error_proto.proto().is_object());
assert!(w.symbol_proto.proto().is_object());
}
#[test]
fn test_math_json_proto_links_to_object_proto() {
let w = make_world();
let obj_proto_ptr = w.object_proto.as_ptr() as *mut JsObject;
// Math/JSON 命名空间对象的 proto 槽应指向 Object.prototype 本体。
assert!(
std::ptr::eq(w.math_object.proto().as_js_object_ptr(), obj_proto_ptr),
"Math namespace object should inherit Object.prototype"
);
assert!(
std::ptr::eq(w.json_object.proto().as_js_object_ptr(), obj_proto_ptr),
"JSON namespace object should inherit Object.prototype"
);
}
#[test]
fn test_shapes_populated() {
let w = make_world();
assert!(
w.object_constructor.shape_id() > EMPTY_SHAPE_ID,
"constructor should have prototype + name shape"
);
assert!(w.object_proto.shape_id() > EMPTY_SHAPE_ID, "prototype should have constructor shape");
}
#[test]
fn builtin_rebuild_with_dirty_reuses_clean_fields() {
let sf = PermInterner::new();
let sh = ShapeForge::new();
let w = BuiltinWorld::new(&sf, &sh);
let rebuilt = BuiltinWorld::rebuild_with_dirty(&w, &sf, &sh, &BuiltinDirtySet::default());
assert!(std::ptr::eq(w.object_proto.as_ptr(), rebuilt.object_proto.as_ptr()));
assert!(std::ptr::eq(w.array_proto.as_ptr(), rebuilt.array_proto.as_ptr()));
assert!(std::ptr::eq(w.function_proto.as_ptr(), rebuilt.function_proto.as_ptr()));
}
#[test]
fn builtin_rebuild_with_dirty_replaces_only_dirty_group() {
let sf = PermInterner::new();
let sh = ShapeForge::new();
let w = BuiltinWorld::new(&sf, &sh);
let dirty = BuiltinDirtySet {
array: true,
..Default::default()
};
let rebuilt = BuiltinWorld::rebuild_with_dirty(&w, &sf, &sh, &dirty);
assert!(!std::ptr::eq(w.array_proto.as_ptr(), rebuilt.array_proto.as_ptr()));
assert!(!std::ptr::eq(w.array_constructor.as_ptr(), rebuilt.array_constructor.as_ptr()));
assert!(std::ptr::eq(w.object_proto.as_ptr(), rebuilt.object_proto.as_ptr()));
assert!(std::ptr::eq(w.function_proto.as_ptr(), rebuilt.function_proto.as_ptr()));
}
#[test]
fn builtin_rebuild_with_dirty_repairs_ctor_proto_links() {
let sf = PermInterner::new();
let sh = ShapeForge::new();
let w = BuiltinWorld::new(&sf, &sh);
let dirty = BuiltinDirtySet {
array: true,
..Default::default()
};
let rebuilt = BuiltinWorld::rebuild_with_dirty(&w, &sf, &sh, &dirty);
let ctor_proto = rebuilt.array_constructor.get_prop_at(0).as_js_object_ptr();
let proto_ctor = rebuilt.array_proto.get_prop_at(0).as_js_object_ptr();
assert!(std::ptr::eq(ctor_proto, rebuilt.array_proto.as_ptr() as *mut JsObject));
assert!(std::ptr::eq(proto_ctor, rebuilt.array_constructor.as_ptr() as *mut JsObject));
}