fix: 语义重名诊断引擎侧复核,放行跨语句列的函数名合并

供应商语义检查器把"同语句列"近似为"声明域非 Top/Function
且前一项是函数声明",for-in/for-of 域用空 ScopeFlags 因而漏掉
Top|Function 守卫,误拒跨语句列的函数名与 var 头合法合并。
引擎侧在归一化前按 AST 复核:仅当函数非任一 block/case 列表
直接成员、或其外层链不含该列表时剔除该重名诊断,复核后无
剩余错误则落回解析成功。
This commit is contained in:
2026-09-15 02:18:07 +00:00
parent da5e6d13ba
commit 4b0b52ade3
7 changed files with 531 additions and 1 deletions
@@ -0,0 +1,74 @@
//! 函数名与 var 声明头跨语句列合法合并的求值行为钉:var 提升步复用函数
//! 声明既有绑定(脚本顶层全局属性 / 函数 var 环境),迭代写入同一绑定。
//!
//! 完成值一律收敛为布尔(JsValue 的 Display 只暴露 number/bool,不暴露
//! 字符串内容),字符串比较在引擎内完成。
use std::sync::Arc;
use oxide_compiler::compiler::Compiler;
use oxide_parser::Allocator;
use oxide_vm::vm::Vm;
fn eval(source: &str) -> String {
let allocator = Allocator::default();
let program = match oxide_parser::parse(&allocator, source) {
Ok(p) => p,
Err(e) => return format!("parse error: {}", e[0].message),
};
let module = match Compiler::new().compile(&program) {
Ok(m) => m,
Err(e) => return format!("compile error: {e}"),
};
let mut vm = Vm::new();
match vm.run(&Arc::new(module)) {
Ok(result) => format!("{result}"),
Err(e) => format!("vm error: {e}"),
}
}
#[test]
fn script_top_function_for_in_var_header_reuses_global_property() {
// 脚本顶层函数 + for-in var 头:迭代重写全局属性(末键),x 不再是函数。
assert_eq!(
eval(
"function x(){} var o={a:1,b:2}; for (var x in o) {} \
(x === \"b\") && (typeof x === \"string\")"
),
"true",
"var head hoists into the global var environment and reuses the function property"
);
}
#[test]
fn script_top_function_for_of_var_header_reuses_global_property() {
// for-of 孪生形:末元素 2 写入全局属性。
assert_eq!(
eval("function x(){} var o=[1,2]; for (var x of o) {} (x === 2) && (typeof x === \"number\")"),
"true",
"for-of var head merges with the top-level function name binding"
);
}
#[test]
fn function_body_function_for_in_var_header_reuses_fn_env_binding() {
// 函数作用域面:函数 var 环境内同形合并。
assert_eq!(
eval(
"function outer(){ function x(){} var o={a:1,b:2}; \
for (var x in o) {} return (x === \"b\") && (typeof x === \"string\") } outer()"
),
"true",
"var head in a for-in inside a function body reuses the function-scope binding"
);
}
#[test]
fn script_top_function_plain_var_keeps_function() {
// 纯 var 重名(无迭代写入):var 步零动作,x 保持函数本体。
assert_eq!(
eval("function x(){} var x; typeof x === \"function\""),
"true",
"plain var redeclaration of a function name keeps the function binding"
);
}