mirror of
https://github.com/pjh456/OxideJS.git
synced 2026-10-25 11:11:11 +08:00
feat: source-phase 导入绑定 ModuleSource 宿主内建
This commit is contained in:
@@ -7,7 +7,9 @@
|
||||
//! defer 导入(`import defer * as ns`)的依赖不求值:编译入子模块树并发
|
||||
//! `__moduleDeferObject` 构造 deferred namespace 对象(逐名预注册静态导出名),
|
||||
//! 绑定该对象;自导入/祖先 defer 回边发哨兵形态(不递归、不编译)。
|
||||
//! 未支持:嵌套闭包内读 import 名(仍为链接期快照)、source-phase;
|
||||
//! source-phase 导入(`import source x from`)的局部名绑定目标模块的 ModuleSource
|
||||
//! 对象(宿主内建),再导出链按 `~source~` 来源身份转发。
|
||||
//! 未支持:嵌套闭包内读 import 名(仍为链接期快照);
|
||||
//! star 转发与经再导出链的活值仍为快照;eager 环导入在编译期跳过。
|
||||
|
||||
use std::collections::{HashMap, HashSet};
|
||||
@@ -28,7 +30,7 @@ use oxide_parser::{
|
||||
ImportAttributeKey, ImportDeclarationSpecifier, ImportPhase, ModuleExportName, ObjectPropertyKind,
|
||||
SimpleAssignmentTarget, Statement, VariableDeclarationKind, WithClause,
|
||||
};
|
||||
use oxide_types::MODULE_NAMESPACE_BINDING;
|
||||
use oxide_types::{MODULE_NAMESPACE_BINDING, MODULE_SOURCE_BINDING};
|
||||
|
||||
/// 数据模块种类(非 JS 源码模块)。
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
@@ -1241,6 +1243,25 @@ impl Emitter {
|
||||
}
|
||||
}
|
||||
ImportDeclarationSpecifier::ImportDefaultSpecifier(s) => {
|
||||
if imp.phase == Some(ImportPhase::Source) {
|
||||
// source-phase 导入:局部名绑定目标模块的 ModuleSource
|
||||
// 对象(宿主提供的 %AbstractModuleSource% 实例),
|
||||
// 非默认导出。再导出链的来源身份按 `~source~` 哨兵
|
||||
// 登记,使同名异源经 star 转发时身份可比。
|
||||
ctx.module_import_origins.insert(
|
||||
s.local.name.to_string(),
|
||||
(dep_path.clone(), MODULE_SOURCE_BINDING.to_string()),
|
||||
);
|
||||
let val_reg = self.emit_module_call(ctx, "__moduleSourceObject", &[])?;
|
||||
self.emit_bind_target(
|
||||
s.local.name.as_str(),
|
||||
val_reg,
|
||||
VariableDeclarationKind::Const,
|
||||
false,
|
||||
ctx,
|
||||
)?;
|
||||
continue;
|
||||
}
|
||||
if !is_self {
|
||||
ctx.module_import_origins.insert(
|
||||
s.local.name.to_string(),
|
||||
|
||||
@@ -663,3 +663,53 @@ fn defer_only_dep_without_tla_no_hoisting() {
|
||||
assert_eq!(native_calls_to(&ir, "__moduleWaitAll"), 0, "无 TLA 模块不得发聚合 gate");
|
||||
assert!(!ir.is_async, "无 TLA 模块的导入方不得标记异步");
|
||||
}
|
||||
|
||||
/// 面 33:source-phase 导入(`import source x from`)局部名绑定 ModuleSource 对象——
|
||||
/// 发 `__moduleSourceObject` 调用,不走默认导入的 `__moduleLinkGet` 取 default 路径。
|
||||
#[test]
|
||||
fn import_source_phase_binds_module_source_object() {
|
||||
let (ir, _) = emit_module(
|
||||
"import source x from \"./src.js\"; var y = x;",
|
||||
"./entry.js",
|
||||
&[("./src.js", ModuleKind::Js, "")],
|
||||
)
|
||||
.expect("source-phase 导入应编译成功");
|
||||
assert!(
|
||||
builtin_names(&ir).contains("__moduleSourceObject"),
|
||||
"source-phase 导入应发 __moduleSourceObject 调用"
|
||||
);
|
||||
assert_eq!(native_calls_to(&ir, "__moduleSourceObject"), 1, "局部名应绑定一次 ModuleSource");
|
||||
assert_eq!(native_calls_to(&ir, "__moduleLinkGet"), 0, "source-phase 不得走 default 导出链接");
|
||||
}
|
||||
|
||||
/// 面 34:source-phase 导入再导出(`export { x }`)按 `~source~` 来源身份转发——
|
||||
/// 经 `__moduleSetReexport` 注册,来源路径与绑定名入池。
|
||||
#[test]
|
||||
fn import_source_phase_reexport_registrs_source_origin() {
|
||||
let (ir, _) = emit_module(
|
||||
"import source x from \"./src.js\"; export { x };",
|
||||
"./entry.js",
|
||||
&[("./src.js", ModuleKind::Js, "")],
|
||||
)
|
||||
.expect("source-phase 导入再导出应编译成功");
|
||||
assert!(
|
||||
builtin_names(&ir).contains("__moduleSetReexport"),
|
||||
"source-phase 再导出应走 __moduleSetReexport"
|
||||
);
|
||||
assert_eq!(native_calls_to(&ir, "__moduleSetReexport"), 1, "再导出应注册一次来源身份");
|
||||
assert_eq!(native_calls_to(&ir, "__moduleSet"), 0, "source-phase 再导出不得走本地注册");
|
||||
}
|
||||
|
||||
/// 面 35:普通导入(phase 缺省)产物零 diff 守卫——source-phase 分支不得改变
|
||||
/// 默认导入的发射形态(仍走 `__moduleLinkGet` 取 default)。
|
||||
#[test]
|
||||
fn default_import_unchanged_by_source_phase_branch() {
|
||||
let (ir, _) = emit_module(
|
||||
"import d from \"./dep.js\"; var y = d;",
|
||||
"./entry.js",
|
||||
&[("./dep.js", ModuleKind::Js, "export default 42;")],
|
||||
)
|
||||
.expect("默认导入应编译成功");
|
||||
assert!(builtin_names(&ir).contains("__moduleLinkGet"), "默认导入应经 __moduleLinkGet 链接");
|
||||
assert_eq!(native_calls_to(&ir, "__moduleSourceObject"), 0, "普通默认导入不得发 source 对象调用");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user