feat: compiler/test262 runner 接线 + 模块顶层 this 绑定

- Compiler::compile_module:Emitter::emit_program_module → 统一 IR 管线(DCE/regalloc/lower/flatten)
- CompiledModule.is_es_module:VM run 时模块顶层 this=undefined(脚本仍为全局对象)
- 全局注册 __moduleLinkGet
- test262 runner:Test262ModuleLoader(相对路径解析 + import attributes 判定 json/text/bytes),is_module 走 compile_module
This commit is contained in:
爱特每羊队
2026-08-12 17:37:24 +08:00
parent 6da248872b
commit 4303462d19
8 changed files with 92 additions and 7 deletions
+1
View File
@@ -13,6 +13,7 @@ path = "src/main.rs"
[dependencies]
oxide_bytecode = { path = "../oxide_bytecode" }
oxide_compiler = { path = "../oxide_compiler" }
oxide_emit = { path = "../oxide_emit" }
oxide_vm = { path = "../oxide_vm" }
oxide_parser = { path = "../oxide_parser" }
oxide_kernel = { path = "../oxide_kernel" }
+44 -1
View File
@@ -436,6 +436,44 @@ fn run_test(
}
}
/// test262 模块用例的依赖加载器:以测试文件父目录为基准解析相对导入,
/// 读取磁盘上的 fixture 源码;json/text/bytes 经 import attributes 判定。
struct Test262ModuleLoader;
impl oxide_emit::module::ModuleSourceLoader for Test262ModuleLoader {
fn resolve(
&mut self, base_dir: &str, specifier: &str, attributes: &[(&str, &str)],
) -> Result<oxide_emit::module::ResolvedModule, String> {
use oxide_emit::module::{ModuleKind, ResolvedModule};
let kind = attributes
.iter()
.find(|(k, _)| *k == "type")
.map(|(_, v)| match *v {
"json" => ModuleKind::Json,
"text" => ModuleKind::Text,
"bytes" => ModuleKind::Bytes,
_ => ModuleKind::Js,
})
.unwrap_or(ModuleKind::Js);
let base = Path::new(base_dir);
let full = if specifier.starts_with('/') {
PathBuf::from(specifier.trim_start_matches('/'))
} else {
base.join(specifier)
};
let canonical = full
.canonicalize()
.map_err(|e| format!("cannot resolve module {specifier}: {e}"))?;
let content = std::fs::read_to_string(&canonical)
.map_err(|e| format!("cannot read module {specifier}: {e}"))?;
Ok(ResolvedModule {
source: content,
path: canonical.to_string_lossy().to_string(),
kind,
})
}
}
/// 单测执行主流程:拼 harness 前缀 → parse → compile → run;
/// 依据 `negative` 元数据校验期望错误,未实现特性按 no_skip 选择跳过或失败。
#[expect(clippy::too_many_arguments)]
@@ -495,7 +533,12 @@ fn run_test_inner(
};
let compiler = if no_regalloc { Compiler::new().with_regalloc(false) } else { Compiler::new() };
let module = match compiler.compile(&program) {
let module = match if is_module {
let mut loader = Test262ModuleLoader;
compiler.compile_module(&program, &path.to_string_lossy().to_string(), &mut loader)
} else {
compiler.compile(&program)
} {
Ok(m) => m,
Err(e) => {
let dur = start.elapsed().as_millis() as u64;