fix: for-in var 头撞既有绑定复用槽位消除顶层编译报错,迭代键写不可写全局内置接只读拦截

This commit is contained in:
2026-09-10 05:56:10 +08:00
parent 1f37c4c9e6
commit a5aab0077f
3 changed files with 59 additions and 3 deletions
@@ -79,3 +79,24 @@ fn for_in_still_enumerates_own_keys() {
"for-in still enumerates the object's own enumerable keys"
);
}
#[test]
fn for_in_var_head_reuses_existing_var_binding() {
// var 头命中同 scope 已预声明的 var 绑定:复用既有槽位不重复声明,
// 迭代键逐迭代落入该绑定(终值 = 末键)。
assert_eq!(
eval("var x = 0; for (var x in {a:1,b:2}) {} x === \"b\""),
"true",
"for-in var head reuses the predeclared same-scope var binding"
);
}
#[test]
fn for_in_var_head_fresh_name() {
// var 头无其他引用:提升的 var 槽接收迭代键。
assert_eq!(
eval("for (var x in {a:1}) {} x === \"a\""),
"true",
"for-in var head binds iteration keys into the hoisted var slot"
);
}
@@ -186,3 +186,21 @@ fn function_declaration_builtin_name() {
&& d.enumerable === false && d.configurable === true",
);
}
#[test]
fn for_in_var_head_builtin_name_compiles_and_keeps_property() {
// 顶层 for-in var 头撞 builtin 名:序言预登记槽复用后可编译,
// 迭代键不触及全局属性(Math 对象保)。
run_truthy("var m = Math; for (var Math in {a:1,b:2}) {} globalThis.Math === m");
}
#[test]
fn for_in_var_head_readonly_builtin_not_clobbered() {
// 顶层 for-in var 头撞三常量:迭代键写命中只读内置拦截——
// sloppy 静默跳过(镜像槽与声明值均不污染),strict 迭代抛 TypeError。
run_truthy("var n = NaN; for (var NaN in {a:1,b:2}) {} Number.isNaN(NaN) && Number.isNaN(n)");
run_truthy(
"var i = Infinity; for (var Infinity in {a:1,b:2}) {} Infinity === i && Infinity === globalThis.Infinity",
);
run_truthy("\"use strict\"; try { for (var NaN in {a:1}) {} } catch (e) { e instanceof TypeError }");
}