mirror of
https://github.com/pjh456/OxideJS.git
synced 2026-10-26 03:31:12 +08:00
fix: 顶层声明撞不可定义全局按规范抛 TypeError
This commit is contained in:
@@ -64,6 +64,18 @@ fn phase2_err_text(phase1: &str, phase2: &str) -> String {
|
||||
}
|
||||
}
|
||||
|
||||
/// phase2 必须抛未捕获异常的变体;返回同 VM 续跑探针脚本的字符串化完成值
|
||||
/// (抛后 A 侧保留面的判别探针)。非字符串完成值走 Display(布尔形探针返回
|
||||
/// "true"/"false")。
|
||||
fn phase2_err_then_probe(phase1: &str, phase2: &str, probe: &str) -> String {
|
||||
let mut vm = Vm::new();
|
||||
vm.run(&Arc::new(compile(phase1))).expect("run1");
|
||||
vm.reset();
|
||||
assert!(vm.run(&Arc::new(compile(phase2))).is_err(), "phase2 应抛未捕获异常: {phase2}");
|
||||
let result = vm.run(&Arc::new(compile(probe))).expect("probe run");
|
||||
vm.lookup_str(result).unwrap_or_else(|| format!("{result}"))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn top_level_var_lands_on_global_this() {
|
||||
eval_truthy("var x = 5; globalThis.x === 5");
|
||||
@@ -425,13 +437,23 @@ fn top_level_function_shadow_and_var_no_init() {
|
||||
eval_truthy("function f(){return 1;} var f = 5; f === 5 && globalThis.f === 5");
|
||||
}
|
||||
|
||||
/// 声明处描述符感知写:既有不可写不可配置属性声明不更值(定义不变量静默
|
||||
/// no-op),裸读与反射一致见既有值。
|
||||
/// 函数臂撞既有不可配置不可写数据属性:GDI 检查阶段抛 TypeError(两模式同形),
|
||||
/// 无部分创建——抛后值与描述符均保留(corpus 无部分绑定形)。
|
||||
#[test]
|
||||
fn top_level_function_decl_respects_nonwritable_property() {
|
||||
assert_two_phases_truthy(
|
||||
let err = phase2_err_text(
|
||||
"Object.defineProperty(globalThis, 'f', {value: 1, writable: false, configurable: false})",
|
||||
"function f(){} f === 1 && globalThis.f === 1 && typeof f === 'number'",
|
||||
"function f(){}",
|
||||
);
|
||||
assert!(err.contains("TypeError"), "声明应抛 TypeError,实际: {err}");
|
||||
assert_eq!(
|
||||
phase2_err_then_probe(
|
||||
"Object.defineProperty(globalThis, 'f', {value: 1, writable: false, configurable: false})",
|
||||
"function f(){}",
|
||||
"f === 1 && globalThis.f === 1 && typeof f === 'number'",
|
||||
),
|
||||
"true",
|
||||
"抛后 A 侧应保留原值与描述符",
|
||||
);
|
||||
}
|
||||
|
||||
@@ -445,18 +467,18 @@ fn top_level_function_survives_reset() {
|
||||
));
|
||||
}
|
||||
|
||||
/// builtin 名形零污染:可写 builtin 名(Math)声明更值保描述符;不可写
|
||||
/// builtin 名(undefined)声明不更新,裸读与反射一致见既有值。
|
||||
/// builtin 名形:c:true builtin 名(Math)声明经 CreateGlobalFunctionBinding
|
||||
/// 重配臂落标准函数描述符(可写/可枚举/不可配置,值可调用);不可配置
|
||||
/// builtin 名(undefined,c:false)声明在 GDI 检查阶段抛 TypeError。
|
||||
#[test]
|
||||
fn top_level_function_decl_builtin_name_zero_pollution() {
|
||||
eval_truthy("function Math(){ return 7; } Math() === 7 && globalThis.Math() === 7 && Math === globalThis.Math");
|
||||
eval_truthy(
|
||||
"function Math(){} var d = Object.getOwnPropertyDescriptor(globalThis, 'Math'); \
|
||||
d.writable === true && d.enumerable === false && d.configurable === true",
|
||||
);
|
||||
eval_truthy(
|
||||
"function undefined(){ return 1; } typeof undefined === 'undefined' && globalThis.undefined === undefined",
|
||||
d.writable === true && d.enumerable === true && d.configurable === false",
|
||||
);
|
||||
let err = phase2_err_text("0", "function undefined(){ return 1; }");
|
||||
assert!(err.contains("TypeError"), "undefined 声明应抛 TypeError,实际: {err}");
|
||||
}
|
||||
|
||||
// ── 声明带初始化的 A 侧写是 PutValue:strict 撞既有不可写用户属性抛 TypeError ──
|
||||
|
||||
Reference in New Issue
Block a user