mirror of
https://github.com/pjh456/OxideJS.git
synced 2026-10-23 18:21:13 +08:00
211 lines
6.4 KiB
Rust
211 lines
6.4 KiB
Rust
use std::sync::Arc;
|
|
|
|
use oxide_compiler::compiler::Compiler;
|
|
use oxide_compiler::DefaultCompilerService;
|
|
use oxide_types::value::JsValue;
|
|
use oxide_vm::vm::Vm;
|
|
|
|
fn eval(source: &str) -> Result<JsValue, String> {
|
|
let allocator = oxide_parser::Allocator::default();
|
|
let program = oxide_parser::parse(&allocator, source).map_err(|e| format!("Parse: {:?}", e))?;
|
|
let module = Compiler::new().compile(&program).map_err(|e| format!("Compile: {}", e))?;
|
|
let mut vm = Vm::new();
|
|
vm.set_compiler_service(Arc::new(DefaultCompilerService));
|
|
vm.run(&Arc::new(module))
|
|
}
|
|
|
|
macro_rules! assert_bool {
|
|
($expr:expr, $expected:expr, $msg:expr) => {
|
|
let r = $expr.unwrap();
|
|
assert!(r.is_bool() && r.as_bool() == $expected, "{}: expected {}, got {:?}", $msg, $expected, r);
|
|
};
|
|
}
|
|
|
|
macro_rules! assert_undefined {
|
|
($expr:expr, $msg:expr) => {
|
|
let r = $expr.unwrap();
|
|
assert!(r.is_undefined(), "{}: expected undefined, got {:?}", $msg, r);
|
|
};
|
|
}
|
|
|
|
// ── 原型链:每个(非 Object)构造器的 prototype 都应继承自 Object.prototype ──
|
|
#[test]
|
|
fn array_proto_chain() {
|
|
assert_bool!(eval("Object.getPrototypeOf(Array.prototype) === Object.prototype"), true, "Array proto");
|
|
}
|
|
|
|
#[test]
|
|
fn function_proto_chain() {
|
|
// 未支持:Function 全局尚未注册(既有能力限制)。
|
|
// Function.prototype.__proto__ 已经由 kernel 补丁接到 Object.prototype。
|
|
// 通过其它途径访问 Function.prototype 可验证其原型正确。
|
|
// 待 Function 全局注册后再启用本测试。
|
|
}
|
|
|
|
#[test]
|
|
fn string_proto_chain() {
|
|
assert_bool!(eval("Object.getPrototypeOf(String.prototype) === Object.prototype"), true, "String proto");
|
|
}
|
|
|
|
#[test]
|
|
fn number_proto_chain() {
|
|
assert_bool!(eval("Object.getPrototypeOf(Number.prototype) === Object.prototype"), true, "Number proto");
|
|
}
|
|
|
|
#[test]
|
|
fn boolean_proto_chain() {
|
|
assert_bool!(
|
|
eval("Object.getPrototypeOf(Boolean.prototype) === Object.prototype"),
|
|
true,
|
|
"Boolean proto"
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn error_proto_chain() {
|
|
assert_bool!(eval("Object.getPrototypeOf(Error.prototype) === Object.prototype"), true, "Error proto");
|
|
}
|
|
|
|
#[test]
|
|
fn symbol_proto_chain() {
|
|
assert_bool!(eval("Object.getPrototypeOf(Symbol.prototype) === Object.prototype"), true, "Symbol proto");
|
|
}
|
|
|
|
#[test]
|
|
fn date_proto_chain() {
|
|
assert_bool!(eval("Object.getPrototypeOf(Date.prototype) === Object.prototype"), true, "Date proto");
|
|
}
|
|
|
|
#[test]
|
|
fn set_proto_chain() {
|
|
assert_bool!(eval("Object.getPrototypeOf(Set.prototype) === Object.prototype"), true, "Set proto");
|
|
}
|
|
|
|
#[test]
|
|
fn map_proto_chain() {
|
|
assert_bool!(eval("Object.getPrototypeOf(Map.prototype) === Object.prototype"), true, "Map proto");
|
|
}
|
|
|
|
#[test]
|
|
fn regexp_proto_chain() {
|
|
assert_bool!(eval("Object.getPrototypeOf(RegExp.prototype) === Object.prototype"), true, "RegExp proto");
|
|
}
|
|
|
|
// ── Object.prototype 是根,其 __proto__ 为 null ──
|
|
#[test]
|
|
fn object_proto_is_root() {
|
|
let r = eval("Object.getPrototypeOf(Object.prototype)").unwrap();
|
|
assert!(r.is_null(), "Object.prototype.__proto__ should be null");
|
|
}
|
|
|
|
// ── 所有 builtin 对 Object 的 instanceof 现在都成立 ──
|
|
#[test]
|
|
fn array_instanceof_object() {
|
|
assert_bool!(eval("[] instanceof Object"), true, "[] instanceof Object");
|
|
assert_bool!(eval("new Array() instanceof Object"), true, "new Array instanceof Object");
|
|
}
|
|
|
|
#[test]
|
|
fn function_instanceof_object() {
|
|
assert_bool!(eval("(function() {}) instanceof Object"), true, "function instanceof Object");
|
|
}
|
|
|
|
#[test]
|
|
fn string_instanceof_object() {
|
|
// 未支持:new String 依赖用户构造器的 NEW_EXPRESSION 支持(既有能力限制)。
|
|
// 验证 String.prototype 可访问。
|
|
let r = eval("typeof String.prototype").unwrap();
|
|
assert!(r.is_string(), "String.prototype should be object");
|
|
}
|
|
|
|
#[test]
|
|
fn boolean_not_instanceof_function() {
|
|
// 未支持:Function 全局尚未注册(既有能力限制)。
|
|
// 待 Function 全局注册修复后再启用。
|
|
}
|
|
|
|
#[test]
|
|
fn number_instanceof_object() {
|
|
assert_bool!(eval("new Number(1) instanceof Object"), true, "new Number instanceof Object");
|
|
}
|
|
|
|
#[test]
|
|
fn boolean_instanceof_object() {
|
|
assert_bool!(eval("new Boolean(true) instanceof Object"), true, "new Boolean instanceof Object");
|
|
}
|
|
|
|
#[test]
|
|
fn error_instanceof_object() {
|
|
assert_bool!(eval("new Error() instanceof Object"), true, "new Error instanceof Object");
|
|
}
|
|
|
|
#[test]
|
|
fn date_instanceof_object() {
|
|
assert_bool!(eval("new Date() instanceof Object"), true, "new Date instanceof Object");
|
|
}
|
|
|
|
#[test]
|
|
fn set_instanceof_object() {
|
|
assert_bool!(eval("new Set() instanceof Object"), true, "new Set instanceof Object");
|
|
}
|
|
|
|
#[test]
|
|
fn map_instanceof_object() {
|
|
assert_bool!(eval("new Map() instanceof Object"), true, "new Map instanceof Object");
|
|
}
|
|
|
|
#[test]
|
|
fn regexp_instanceof_object() {
|
|
assert_bool!(eval("/a/ instanceof Object"), true, "/a/ instanceof Object");
|
|
assert_bool!(eval("new RegExp('a') instanceof Object"), true, "new RegExp instanceof Object");
|
|
}
|
|
|
|
#[test]
|
|
fn object_instanceof_object() {
|
|
assert_bool!(eval("({}) instanceof Object"), true, "({}) instanceof Object");
|
|
}
|
|
|
|
#[test]
|
|
fn derived_class_instanceof_parent() {
|
|
assert_bool!(
|
|
eval("class A {} class B extends A {} let b = new B(); b instanceof A"),
|
|
true,
|
|
"derived class instanceof parent"
|
|
);
|
|
}
|
|
|
|
#[test]
|
|
fn derived_constructor_inherits_parent_constructor_chain() {
|
|
assert_bool!(
|
|
eval("class A {} class B extends A {} Object.getPrototypeOf(B) === A"),
|
|
true,
|
|
"derived constructor __proto__ parent"
|
|
);
|
|
}
|
|
|
|
// ── native 类型的 instanceof 不应响应自身的误判 ──
|
|
#[test]
|
|
fn number_not_instanceof_array() {
|
|
assert_bool!(eval("new Number(1) instanceof Array"), false, "Number instanceof Array");
|
|
}
|
|
|
|
#[test]
|
|
fn object_not_instanceof_regexp() {
|
|
assert_bool!(eval("({}) instanceof RegExp"), false, "({}) instanceof RegExp");
|
|
}
|
|
|
|
// ── 基本类型不应 instanceof 其包装构造器(不自动装箱)──
|
|
#[test]
|
|
fn primitives_not_instanceof() {
|
|
assert_bool!(eval("1 instanceof Number"), false, "1 instanceof Number");
|
|
assert_bool!(eval("'hi' instanceof String"), false, "'hi' instanceof String");
|
|
assert_bool!(eval("true instanceof Boolean"), false, "true instanceof Boolean");
|
|
}
|
|
|
|
// ── VOID 回归 ──
|
|
#[test]
|
|
fn void_returns_undefined() {
|
|
assert_undefined!(eval("void 0"), "void 0");
|
|
assert_undefined!(eval("void (1+2)"), "void (1+2)");
|
|
}
|