fix: 脚本顶层 var/function 声明落 globalThis(DEFINE_GLOBAL_PROP 非可配置数据属性)
This commit is contained in:
@@ -0,0 +1,100 @@
|
||||
//! 脚本顶层 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}"#);
|
||||
}
|
||||
Reference in New Issue
Block a user