mirror of
https://github.com/pjh456/OxideJS.git
synced 2026-10-23 18:21:13 +08:00
fix: for-in 与 for-of 头 var 名补编译期预声明臂
This commit is contained in:
@@ -442,6 +442,33 @@ impl Emitter {
|
||||
}
|
||||
self.predeclare_var_declarations(std::slice::from_ref(&fs.body), ctx);
|
||||
}
|
||||
Statement::ForInStatement(fi) => {
|
||||
// var 头名提升到函数/全局作用域(与 For 臂同规则),先于提升
|
||||
// 函数声明发射预声明,使函数体按既有 var 绑定解析头名;
|
||||
// let/const 头是迭代级绑定,不入提升面。
|
||||
if let oxide_parser::ForStatementLeft::VariableDeclaration(decl) = &fi.left {
|
||||
if matches!(decl.kind, VariableDeclarationKind::Var) {
|
||||
for d in &decl.declarations {
|
||||
if let oxide_parser::BindingPattern::BindingIdentifier(bi) = &d.id {
|
||||
self.predeclare_var_name(bi.name.as_str(), ctx);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
self.predeclare_var_declarations(std::slice::from_ref(&fi.body), ctx);
|
||||
}
|
||||
Statement::ForOfStatement(fo) => {
|
||||
if let oxide_parser::ForStatementLeft::VariableDeclaration(decl) = &fo.left {
|
||||
if matches!(decl.kind, VariableDeclarationKind::Var) {
|
||||
for d in &decl.declarations {
|
||||
if let oxide_parser::BindingPattern::BindingIdentifier(bi) = &d.id {
|
||||
self.predeclare_var_name(bi.name.as_str(), ctx);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
self.predeclare_var_declarations(std::slice::from_ref(&fo.body), ctx);
|
||||
}
|
||||
Statement::SwitchStatement(sw) => {
|
||||
for case in &sw.cases {
|
||||
self.predeclare_var_declarations(&case.consequent, ctx);
|
||||
|
||||
@@ -102,3 +102,37 @@ fn for_in_var_head_fresh_name() {
|
||||
"for-in var head binds iteration keys into the hoisted var slot"
|
||||
);
|
||||
}
|
||||
|
||||
// ── 提升函数引用 for-in/for-of 头 var 名:头名须编译期预声明(hoisting 面)──
|
||||
|
||||
#[test]
|
||||
fn for_in_var_head_hoisted_fn_read() {
|
||||
// 顶层提升函数读 for-in 头 var:头名预声明入全局 var 名集,函数体按
|
||||
// 全局 var 绑定解析,完成值为迭代键。
|
||||
assert_eq!(
|
||||
eval("function f(){ return x; } for (var x in {a:1}) {} f() === \"a\""),
|
||||
"true",
|
||||
"hoisted function reads for-in head var through the global var binding"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn for_in_var_head_hoisted_fn_strict_write() {
|
||||
// strict 嵌套写:头名预声明为全局 var 绑定后,写落全局属性(A 侧);
|
||||
// 头名缺预声明时该写按未声明名抛 ReferenceError(本钉判别面)。
|
||||
assert_eq!(
|
||||
eval("'use strict'; function f(){ x = 5; } for (var x in {a:1}) { f(); } x === 5"),
|
||||
"true",
|
||||
"strict hoisted-function write to for-in head var hits the global binding"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn for_of_var_head_hoisted_fn_strict_write() {
|
||||
// for-of 头同形:预声明臂覆盖 for-in 与 for-of 两臂。
|
||||
assert_eq!(
|
||||
eval("'use strict'; function f(){ x = 5; } for (var x of [1,2]) { f(); } x === 5"),
|
||||
"true",
|
||||
"strict hoisted-function write to for-of head var hits the global binding"
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user