mirror of
https://github.com/pjh456/OxideJS.git
synced 2026-10-23 18:21:13 +08:00
101 lines
3.5 KiB
Rust
101 lines
3.5 KiB
Rust
//! 脚本顶层 var/function 声明落 globalThis 的运行时行为测试。
|
|
|
|
use oxide_compiler::compiler::Compiler;
|
|
use oxide_parser::Allocator;
|
|
use oxide_vm::vm::Vm;
|
|
|
|
fn eval_truthy(source: &str) {
|
|
let allocator = Allocator::default();
|
|
let program = oxide_parser::parse(&allocator, source).expect("parse");
|
|
let module = Compiler::new().compile(&program).expect("compile");
|
|
let mut vm = Vm::new();
|
|
let result = vm.run(&module).expect("run");
|
|
assert!(result.is_bool() && result.as_bool(), "expected true, got: {result:?}\nsource: {source}");
|
|
}
|
|
|
|
fn eval_string(source: &str) -> String {
|
|
let allocator = Allocator::default();
|
|
let program = oxide_parser::parse(&allocator, source).expect("parse");
|
|
let module = Compiler::new().compile(&program).expect("compile");
|
|
let mut vm = Vm::new();
|
|
let result = vm.run(&module).expect("run");
|
|
vm.lookup_str(result).unwrap_or_default()
|
|
}
|
|
|
|
#[test]
|
|
fn top_level_var_lands_on_global_this() {
|
|
eval_truthy("var x = 5; globalThis.x === 5");
|
|
eval_truthy("var y = 10; typeof globalThis.y === 'number'");
|
|
}
|
|
|
|
#[test]
|
|
fn top_level_function_lands_on_global_this() {
|
|
eval_truthy("function foo(){ return 1; } globalThis.foo() === 1");
|
|
eval_truthy("function foo(){ return 1; } typeof globalThis.foo === 'function'");
|
|
}
|
|
|
|
#[test]
|
|
fn let_const_class_do_not_land_on_global_this() {
|
|
eval_truthy("let z = 5; typeof globalThis.z === 'undefined'");
|
|
eval_truthy("const c = 1; typeof globalThis.c === 'undefined'");
|
|
eval_truthy("class C {} typeof globalThis.C === 'undefined'");
|
|
}
|
|
|
|
#[test]
|
|
fn function_local_var_does_not_land_on_global_this() {
|
|
eval_truthy("function f(){ var v = 1; } f(); typeof globalThis.v === 'undefined'");
|
|
}
|
|
|
|
#[test]
|
|
fn block_level_var_lands_on_global_this() {
|
|
eval_truthy("{ var b = 2; } globalThis.b === 2");
|
|
}
|
|
|
|
#[test]
|
|
fn redeclaration_updates_global_property() {
|
|
eval_truthy("var x = 1; var x = 2; globalThis.x === 2");
|
|
}
|
|
|
|
#[test]
|
|
fn var_global_property_is_non_configurable() {
|
|
eval_truthy("var x = 1; Object.getOwnPropertyDescriptor(globalThis, 'x').configurable === false");
|
|
eval_truthy("var x = 1; Object.getOwnPropertyDescriptor(globalThis, 'x').enumerable === true");
|
|
eval_truthy("var x = 1; delete globalThis.x === false");
|
|
eval_truthy("var x = 1; delete globalThis.x; typeof globalThis.x === 'number'");
|
|
}
|
|
|
|
#[test]
|
|
fn var_name_shows_in_get_own_property_names() {
|
|
eval_truthy("var x = 1; Object.getOwnPropertyNames(globalThis).indexOf('x') >= 0");
|
|
eval_truthy("function foo(){} Object.getOwnPropertyNames(globalThis).indexOf('foo') >= 0");
|
|
}
|
|
|
|
#[test]
|
|
fn function_declared_var_lands_after_user_assignment() {
|
|
eval_truthy("globalThis.x = 99; var x = 5; globalThis.x === 5");
|
|
}
|
|
|
|
#[test]
|
|
fn async_harness_done_pattern() {
|
|
// asyncHelpers.js 依赖顶层 function $DONE 落 globalThis。
|
|
eval_truthy("function $DONE(){} Object.prototype.hasOwnProperty.call(globalThis, '$DONE')");
|
|
eval_truthy("function $DONE(){} typeof globalThis.$DONE === 'function'");
|
|
}
|
|
|
|
#[test]
|
|
fn var_without_initializer_creates_undefined_property() {
|
|
eval_truthy("var x; typeof globalThis.x === 'undefined'");
|
|
eval_truthy("var x; Object.prototype.hasOwnProperty.call(globalThis, 'x')");
|
|
}
|
|
|
|
#[test]
|
|
fn function_internal_reference_still_works() {
|
|
eval_truthy("function foo(){ return 1; } var r = foo(); r === 1");
|
|
}
|
|
|
|
#[test]
|
|
fn descriptor_attributes_match_spec() {
|
|
let d = eval_string("var x = 1; JSON.stringify(Object.getOwnPropertyDescriptor(globalThis, 'x'))");
|
|
assert_eq!(d, r#"{"value":1,"writable":true,"enumerable":true,"configurable":false}"#);
|
|
}
|