mirror of
https://github.com/pjh456/OxideJS.git
synced 2026-10-24 02:31:13 +08:00
c564ec539b
- 谓词注册表化:targets_readonly_builtin 解析条件抽公共助手,新增 targets_writable_builtin / is_writable_builtin_global(BUILTIN_GLOBALS 减只读三常量派生,不复制名单)+ 只读/可写划分漂移守卫单测 - 12 个赋值族写点(简单/复合/更新/逻辑赋值、解构两臂、for-in/for-of 标识符目标)补双写臂:STORE_VAR 后 0x98 同步全局对象属性(既有可写 属性原地更值、保 e/c 位),裸读镜像与 globalThis 反射不失步 - for-in 头 tier 写点移除 builtin 名例外:可写 builtin 名迭代键照规范 覆写全局属性(三常量仍由拦截臂跳过) - 三常量(undefined/NaN/Infinity)全局描述符 configurable 翻正为 false:delete 拒绝、属性保留,描述符读同步 - 脚本顶层受限词法名集 3→4(补 eval,静态受限臂):let/const/class eval 顶层声明编译期 SyntaxError - 配套钉:7 处既有钉随 c 位翻正 + 2 枚 for-in/eval 形态钉反转,新增 global_builtin_writable_tests(16 钉:双写六形态 + 遮蔽/strict/eval/ 宿主名面) test262 子集:built-ins/global 29/29、三常量族 20/20、11.13.1-4 7/7、 assignmenttargettype plain 8/8 全绿;language/global-code 17 失败文件 双树单跑一致(pre-existing);annexB assignmenttargettype 7 个 parse error 为既有解析器缺口
126 lines
4.6 KiB
Rust
126 lines
4.6 KiB
Rust
//! 可写 builtin 全局双写(镜像槽 + 全局对象属性)回归测试。
|
||
//!
|
||
//! 规范可写全局(11 个 w:true 函数 + 48 个构造器/命名空间 + globalThis + 宿主名,
|
||
//! 描述符 {writable:true, enumerable:false, configurable:true})的标识符写须同步
|
||
//! 全局对象属性,裸读(镜像)与 globalThis 反射(属性)不失步。覆盖:简单/复合/
|
||
//! 更新/逻辑赋值、for-in/for-of 标识符目标、解构两臂、局部遮蔽不误伤、strict 可写
|
||
//! put 成功、eval 路径与 TypedArray 宿主名抽样。
|
||
|
||
use std::sync::Arc;
|
||
|
||
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(&Arc::new(module)).expect("run");
|
||
assert!(result.is_bool() && result.as_bool(), "expected true, got: {result:?}\nsource: {source}");
|
||
}
|
||
|
||
// ── 简单赋值:镜像与属性同步落值 ──
|
||
#[test]
|
||
fn simple_assign_math_dual_writes() {
|
||
eval_truthy("var m = Math; Math = 5; Math === 5 && globalThis.Math === 5 && m !== 5");
|
||
}
|
||
|
||
#[test]
|
||
fn simple_assign_writable_names_dual_write() {
|
||
for name in ["Object", "JSON", "Symbol", "Promise"] {
|
||
let src = format!("var m = {name}; {name} = 5; {name} === 5 && globalThis.{name} === 5");
|
||
eval_truthy(&src);
|
||
}
|
||
}
|
||
|
||
// ── w:true 函数族:strict 下可写 put 成功(无 TypeError) ──
|
||
#[test]
|
||
fn strict_writable_function_put_succeeds() {
|
||
eval_truthy("'use strict'; parseInt = 42; parseInt === 42 && globalThis.parseInt === 42");
|
||
}
|
||
|
||
#[test]
|
||
fn sloppy_writable_function_put_succeeds() {
|
||
eval_truthy("parseInt = 42; parseInt === 42 && globalThis.parseInt === 42");
|
||
}
|
||
|
||
#[test]
|
||
fn uri_family_dual_write() {
|
||
eval_truthy("var m = encodeURI; encodeURI = 1; encodeURI === 1 && globalThis.encodeURI === 1");
|
||
}
|
||
|
||
// ── 复合/更新/逻辑赋值:RMW 新值两侧同步 ──
|
||
#[test]
|
||
fn compound_assign_dual_writes() {
|
||
eval_truthy("var m = Math; Math = 5; Math += 1; Math === 6 && globalThis.Math === 6");
|
||
}
|
||
|
||
#[test]
|
||
fn update_assign_dual_writes() {
|
||
eval_truthy("var m = Math; Math = 5; var r = (Math++); r === 5 && Math === 6 && globalThis.Math === 6");
|
||
}
|
||
|
||
#[test]
|
||
fn logical_assign_dual_writes() {
|
||
// ||=:LHS falsy 触发 put;??=:LHS nullish 触发 put。
|
||
eval_truthy("var m = Math; Math = 0; Math ||= 9; Math === 9 && globalThis.Math === 9");
|
||
eval_truthy("var m = Math; Math = null; Math ??= 2; Math === 2 && globalThis.Math === 2");
|
||
}
|
||
|
||
#[test]
|
||
fn logical_assign_short_circuit_no_put() {
|
||
// 短路未通过不发生 put(&&= 遇 falsy、??= 遇非 nullish):值与属性均保持。
|
||
eval_truthy("var m = Math; Math = 0; Math &&= 1; Math === 0 && globalThis.Math === 0");
|
||
eval_truthy("var m = Math; Math = 5; Math ??= 2; Math === 5 && globalThis.Math === 5");
|
||
}
|
||
|
||
// ── for-in/for-of 标识符目标:迭代值两侧同步 ──
|
||
#[test]
|
||
fn for_in_target_dual_writes() {
|
||
eval_truthy("var m = Math; Math = 5; for (Math in {a:1,b:2}) {} Math === 'b' && globalThis.Math === 'b'");
|
||
}
|
||
|
||
#[test]
|
||
fn for_of_target_dual_writes() {
|
||
eval_truthy("var m = Math; for (Math of [1,2]) {} Math === 2 && globalThis.Math === 2");
|
||
}
|
||
|
||
// ── 解构赋值两臂:值两侧同步 ──
|
||
#[test]
|
||
fn destructure_assign_dual_writes() {
|
||
eval_truthy("var m = Math; ({Math} = {Math: 1}); Math === 1 && globalThis.Math === 1");
|
||
eval_truthy("var m = Math; ([Math = 1] = [2]); Math === 2 && globalThis.Math === 2");
|
||
}
|
||
|
||
// ── 局部遮蔽不误伤:函数内 var 同名写不触全局 ──
|
||
#[test]
|
||
fn local_shadow_not_dual_written() {
|
||
eval_truthy(
|
||
"var m = Math; function g(){ var Math = 7; return Math; } \
|
||
g() === 7 && Math === m && globalThis.Math === m",
|
||
);
|
||
}
|
||
|
||
// ── globalThis 自身可写:镜像与属性同步 ──
|
||
#[test]
|
||
fn global_this_self_dual_writes() {
|
||
eval_truthy(
|
||
"var m = globalThis; globalThis = 1; \
|
||
globalThis === 1 && Object.getOwnPropertyDescriptor(m, 'globalThis').value === 1",
|
||
);
|
||
}
|
||
|
||
// ── 宿主名(TypedArray 抽象运算对象)同双写面 ──
|
||
#[test]
|
||
fn typed_array_host_name_dual_writes() {
|
||
eval_truthy("var m = TypedArray; TypedArray = 1; TypedArray === 1 && globalThis.TypedArray === 1");
|
||
}
|
||
|
||
// ── eval 路径:同一 emit 管线双写同效(外层镜像预载不重载,只钉属性面) ──
|
||
#[test]
|
||
fn eval_code_dual_writes_property() {
|
||
eval_truthy("eval('Math = 5'); globalThis.Math === 5");
|
||
}
|