fix: 模块 var 与函数导出实例化期预初始化

This commit is contained in:
2026-09-18 00:32:29 +00:00
parent 39183f449c
commit 1855775956
4 changed files with 164 additions and 11 deletions
+108 -2
View File
@@ -153,6 +153,101 @@ fn module_own_export_names(body: &[Statement]) -> HashSet<String> {
names
}
/// 收集模块实例化期即初始化为 undefined 的导出名(VarScopedDeclarations):
/// `export var`、`export function`、`export default function`(具名与匿名)以及
/// 经 `export { x }` 本地再导出、底层绑定为 var/function 的导出名。
///
/// # 边界与前提
/// - lexical(let/const/class)与跨模块再导出(`export { x } from`)不在集合内,
/// 其命名空间条目保持未初始化(TDZ)。
/// - `export { x as y }` 只认本模块顶层直接声明的 var/function;自导入别名等
/// 间接名不判真(按 TDZ 处理)。
/// - 匿名 `export default function` 的导出名是 `default`,按 HoistableDeclaration
/// 预初始化。
fn module_var_scoped_export_names(body: &[Statement]) -> HashSet<String> {
let mut var_locals: HashSet<String> = HashSet::new();
for stmt in body {
match stmt {
Statement::VariableDeclaration(vd) => {
if matches!(vd.kind, VariableDeclarationKind::Var) {
for d in &vd.declarations {
if let BindingPattern::BindingIdentifier(bi) = &d.id {
var_locals.insert(bi.name.to_string());
}
}
}
}
Statement::FunctionDeclaration(fd) => {
if let Some(id) = &fd.id {
var_locals.insert(id.name.to_string());
}
}
Statement::ExportNamedDeclaration(exp) => {
if let Some(decl) = &exp.declaration {
match decl {
Declaration::VariableDeclaration(vd) => {
if matches!(vd.kind, VariableDeclarationKind::Var) {
for d in &vd.declarations {
if let BindingPattern::BindingIdentifier(bi) = &d.id {
var_locals.insert(bi.name.to_string());
}
}
}
}
Declaration::FunctionDeclaration(fd) => {
if let Some(id) = &fd.id {
var_locals.insert(id.name.to_string());
}
}
_ => {}
}
}
}
_ => {}
}
}
let mut names = HashSet::new();
for stmt in body {
match stmt {
Statement::ExportNamedDeclaration(exp) => {
if let Some(decl) = &exp.declaration {
match decl {
Declaration::VariableDeclaration(vd) => {
if matches!(vd.kind, VariableDeclarationKind::Var) {
for d in &vd.declarations {
if let BindingPattern::BindingIdentifier(bi) = &d.id {
names.insert(bi.name.to_string());
}
}
}
}
Declaration::FunctionDeclaration(fd) => {
if let Some(id) = &fd.id {
names.insert(id.name.to_string());
}
}
_ => {}
}
} else if exp.source.is_none() {
for spec in &exp.specifiers {
if var_locals.contains(module_export_name_str(&spec.local).as_str()) {
names.insert(module_export_name_str(&spec.exported));
}
}
}
}
Statement::ExportDefaultDeclaration(exp) => {
if matches!(&exp.declaration, ExportDefaultDeclarationKind::FunctionDeclaration(_)) {
names.insert(DEFAULT_EXPORT_NAME.to_string());
}
}
_ => {}
}
}
names
}
/// 判断语句是否为提升的函数声明(含 export 包装的函数声明)。
fn is_hoisted_function_decl(stmt: &Statement) -> bool {
match stmt {
@@ -513,13 +608,17 @@ impl Emitter {
}
// —— live 命名空间预注册:早于 hoisted 函数声明的 __moduleSet 与 body 求值,
// 按名序预注册全部本地导出名,使自导入 ns 在读点先观察到未初始化状态。 ——
// 按名序预注册全部本地导出名,使自导入 ns 在读点先观察到未初始化状态。
// var/函数类导出(VarScopedDeclarations)在实例化期即初始化为 undefined,
// lexical/class 保持未初始化(TDZ)。 ——
if has_self_ns_import {
let var_scoped = module_var_scoped_export_names(body);
let mut export_names: Vec<String> = own_export_names.into_iter().collect();
export_names.sort();
for name in export_names {
let name_reg = self.load_string_const(&name, ctx);
self.emit_module_call(ctx, "__modulePreRegister", &[ns_reg, name_reg])?;
let var_like_reg = self.load_bool_const(var_scoped.contains(&name), ctx);
self.emit_module_call(ctx, "__modulePreRegister", &[ns_reg, name_reg, var_like_reg])?;
}
}
@@ -667,6 +766,13 @@ impl Emitter {
reg
}
fn load_bool_const(&self, b: bool, ctx: &mut CompileCtx) -> u32 {
let idx = ctx.add_constant(Constant::Boolean(b));
let reg = ctx.alloc_reg();
ctx.inst(Inst::load_const(Operand::Reg(reg), idx));
reg
}
/// 自导入别名回写:导出名若被本模块 self-import 绑定别名引用,
/// export 语句执行时同步把值写回本地绑定槽。
fn emit_self_alias_write(&self, ctx: &mut CompileCtx, export_name: &str, value_reg: u32) {