diff --git a/Cargo.lock b/Cargo.lock index 35836bf5..623f36fe 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1160,7 +1160,7 @@ dependencies = [ [[package]] name = "oxide_builtins" -version = "0.15.2" +version = "0.15.3" dependencies = [ "chrono", "fast-float", @@ -1185,7 +1185,7 @@ dependencies = [ [[package]] name = "oxide_bytecode" -version = "0.15.2" +version = "0.15.3" dependencies = [ "num-bigint", "oxide_log", @@ -1193,7 +1193,7 @@ dependencies = [ [[package]] name = "oxide_cfg" -version = "0.15.2" +version = "0.15.3" dependencies = [ "oxide_bytecode", "oxide_emit", @@ -1204,7 +1204,7 @@ dependencies = [ [[package]] name = "oxide_cli" -version = "0.15.2" +version = "0.15.3" dependencies = [ "ansi_term", "bumpalo", @@ -1227,7 +1227,7 @@ dependencies = [ [[package]] name = "oxide_code_cache" -version = "0.15.2" +version = "0.15.3" dependencies = [ "lru", "oxide_bytecode", @@ -1236,7 +1236,7 @@ dependencies = [ [[package]] name = "oxide_compiler" -version = "0.15.2" +version = "0.15.3" dependencies = [ "oxide_bytecode", "oxide_cfg", @@ -1256,7 +1256,7 @@ dependencies = [ [[package]] name = "oxide_dce" -version = "0.15.2" +version = "0.15.3" dependencies = [ "oxide_bytecode", "oxide_cfg", @@ -1270,7 +1270,7 @@ dependencies = [ [[package]] name = "oxide_emit" -version = "0.15.2" +version = "0.15.3" dependencies = [ "num-bigint", "oxc_allocator", @@ -1285,7 +1285,7 @@ dependencies = [ [[package]] name = "oxide_engine" -version = "0.15.2" +version = "0.15.3" dependencies = [ "oxide_bytecode", "oxide_compiler", @@ -1297,7 +1297,7 @@ dependencies = [ [[package]] name = "oxide_ir" -version = "0.15.2" +version = "0.15.3" dependencies = [ "oxide_bytecode", "oxide_log", @@ -1306,7 +1306,7 @@ dependencies = [ [[package]] name = "oxide_kernel" -version = "0.15.2" +version = "0.15.3" dependencies = [ "bumpalo", "dashmap", @@ -1320,7 +1320,7 @@ dependencies = [ [[package]] name = "oxide_liveness" -version = "0.15.2" +version = "0.15.3" dependencies = [ "oxide_bytecode", "oxide_cfg", @@ -1332,7 +1332,7 @@ dependencies = [ [[package]] name = "oxide_log" -version = "0.15.2" +version = "0.15.3" dependencies = [ "tracing", "tracing-appender", @@ -1341,7 +1341,7 @@ dependencies = [ [[package]] name = "oxide_parser" -version = "0.15.2" +version = "0.15.3" dependencies = [ "oxc_allocator", "oxc_ast", @@ -1356,7 +1356,7 @@ dependencies = [ [[package]] name = "oxide_regalloc" -version = "0.15.2" +version = "0.15.3" dependencies = [ "oxide_bytecode", "oxide_cfg", @@ -1372,7 +1372,7 @@ dependencies = [ [[package]] name = "oxide_runtime_api" -version = "0.15.2" +version = "0.15.3" dependencies = [ "num-bigint", "num-traits", @@ -1385,7 +1385,7 @@ dependencies = [ [[package]] name = "oxide_test262" -version = "0.15.2" +version = "0.15.3" dependencies = [ "oxide_bytecode", "oxide_compiler", @@ -1403,7 +1403,7 @@ dependencies = [ [[package]] name = "oxide_types" -version = "0.15.2" +version = "0.15.3" dependencies = [ "bumpalo", "dashmap", @@ -1416,7 +1416,7 @@ dependencies = [ [[package]] name = "oxide_vm" -version = "0.15.2" +version = "0.15.3" dependencies = [ "bumpalo", "chrono", diff --git a/Cargo.toml b/Cargo.toml index c47e34da..ae688672 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -23,7 +23,7 @@ members = [ ] [workspace.package] -version = "0.15.2" +version = "0.15.3" edition = "2021" license = "MIT" rust-version = "1.80" diff --git a/crates/oxide_test262/src/main.rs b/crates/oxide_test262/src/main.rs index 56db80ee..66a5c96d 100644 --- a/crates/oxide_test262/src/main.rs +++ b/crates/oxide_test262/src/main.rs @@ -141,7 +141,25 @@ fn run_tests() -> bool { test262_info!("no-skip mode enabled"); eprintln!("no-skip mode: capability filters disabled; unsupported results count as failures"); } - let paths = discover_tests(&test262_root); + // 监督模式:监督者把全量路径清单(每行一路径,与父扫描同序)经 + // OXIDE_TEST262_PATHS_FILE 传下来,子进程读文件代替全量重扫目录。 + // 文件缺失或不可读时显式报错退出,不静默回退重扫——回退会让 + // 父扫描与子重扫之间的树变化造成下标错位静默复活。 + let paths = match std::env::var_os("OXIDE_TEST262_PATHS_FILE") { + Some(list_path) => { + let list_path = PathBuf::from(list_path); + let content = match std::fs::read_to_string(&list_path) { + Ok(content) => content, + Err(err) => { + test262_error!("paths file unreadable: {}: {err}", list_path.display()); + eprintln!("paths file unreadable: {}: {err}", list_path.display()); + std::process::exit(1); + } + }; + content.lines().map(PathBuf::from).collect() + } + None => discover_tests(&test262_root), + }; test262_info!("found {} test files", paths.len()); eprintln!("found {} test files", paths.len()); diff --git a/crates/oxide_test262/src/supervise.rs b/crates/oxide_test262/src/supervise.rs index 5e408b7f..54752b84 100644 --- a/crates/oxide_test262/src/supervise.rs +++ b/crates/oxide_test262/src/supervise.rs @@ -91,10 +91,15 @@ fn record_timeout_or_crash(stats: &mut RunStats, no_skip: bool, index: usize, el /// 子进程被杀死、按路径报告肇事者,并由全新子进程从肇事者之后续跑;子进程 /// 在测试中途崩溃也经同路径恢复,恢复基于最后完成下标,无漏项。子进程死亡后 /// 读取旁路失败行并入 fail_records。超时/崩溃默认计为 skip,`--no-skip` 下计为失败。 +/// +/// # 注意事项 +/// - `paths_file` 是父进程写出的全量路径清单文件(每行一路径,与父扫描同序), +/// 经 `OXIDE_TEST262_PATHS_FILE` 环境变量传给子进程,子进程读文件代替全量重扫 +/// 目录;文件在窗口内子进程多次重启间只读共享,不得按 spawn 删除。 #[expect(clippy::too_many_arguments)] fn supervise_window( exe: &Path, args: &[String], no_skip: bool, wstart: usize, wend: usize, timeout: Duration, startup_grace: Duration, - paths: &[PathBuf], window_id: usize, + paths: &[PathBuf], paths_file: &Path, window_id: usize, ) -> RunStats { let mut stats = RunStats::default(); let mut cur = wstart; @@ -144,6 +149,7 @@ fn supervise_window( .env("OXIDE_TEST262_WORKERS", "1") .env("OXIDE_TEST262_HEARTBEAT", &hb_path) .env("OXIDE_TEST262_PC_WATCH", &pc_path) + .env("OXIDE_TEST262_PATHS_FILE", paths_file) .env("OXIDE_TEST262_CHILD_CHUNK", "1") .env("OXIDE_TEST262_ALLOW_FAIL_EXIT", "1") .env_remove("OXIDE_TEST262_CHUNK_SIZE") @@ -281,6 +287,15 @@ pub(crate) fn run_supervised( } }; + // 路径清单文件:派生窗口前写一次(每行一路径,与父扫描同序),跨窗口只读 + // 共享;子进程读文件代替全量重扫目录。运行结束删除,防临时目录残留。 + let paths_file = std::env::temp_dir().join(format!("oxide_t262_paths_{}.txt", std::process::id())); + let list = paths.iter().map(|p| p.to_string_lossy()).collect::>().join("\n"); + if let Err(err) = std::fs::write(&paths_file, list) { + eprintln!("failed to write paths file {}: {err}", paths_file.display()); + return false; + } + let window = std::env::var("OXIDE_TEST262_WINDOW") .ok() .and_then(|s| s.parse::().ok()) @@ -329,6 +344,7 @@ pub(crate) fn run_supervised( let next = &next; let windows = &windows; let exe = &exe; + let paths_file = &paths_file; let partials: Vec = std::thread::scope(|scope| { let handles: Vec<_> = (0..supervisors) @@ -350,6 +366,7 @@ pub(crate) fn run_supervised( timeout, startup_grace, paths, + paths_file, window_id, ); stats.merge(window_stats); @@ -369,6 +386,9 @@ pub(crate) fn run_supervised( stats.merge(partial_stats); } + // 全部窗口结束、子进程已读完清单,删除路径清单文件防临时目录残留。 + let _ = std::fs::remove_file(paths_file); + let total = stats.pass + stats.fail + stats.skip; println!(); println!("═══════════════════════════════════════");