diff --git a/crates/oxide_builtins/tests/array_boundary_tests.rs b/crates/oxide_builtins/tests/array_boundary_tests.rs index 94f6b37f..fde55179 100644 --- a/crates/oxide_builtins/tests/array_boundary_tests.rs +++ b/crates/oxide_builtins/tests/array_boundary_tests.rs @@ -1,3 +1,5 @@ +use std::sync::Arc; + use oxide_compiler::compiler::Compiler; use oxide_types::value::JsValue; use oxide_vm::vm::Vm; @@ -7,7 +9,7 @@ fn eval(source: &str) -> Result<(Vm, JsValue), String> { let program = oxide_parser::parse(&allocator, source).map_err(|e| format!("Parse error: {:?}", e))?; let module = Compiler::new().compile(&program).map_err(|e| format!("Compile error: {}", e))?; let mut vm = Vm::new(); - let result = vm.run(&module)?; + let result = vm.run(&Arc::new(module))?; Ok((vm, result)) } diff --git a/crates/oxide_builtins/tests/builtins_json_tests.rs b/crates/oxide_builtins/tests/builtins_json_tests.rs index e0ad3812..9de1b6d7 100644 --- a/crates/oxide_builtins/tests/builtins_json_tests.rs +++ b/crates/oxide_builtins/tests/builtins_json_tests.rs @@ -1,3 +1,5 @@ +use std::sync::Arc; + use oxide_compiler::compiler::Compiler; use oxide_types::value::JsValue; use oxide_vm::vm::Vm; @@ -7,7 +9,7 @@ fn eval(source: &str) -> Result<(Vm, JsValue), String> { let program = oxide_parser::parse(&allocator, source).map_err(|e| format!("Parse error: {:?}", e))?; let module = Compiler::new().compile(&program).map_err(|e| format!("Compile error: {}", e))?; let mut vm = Vm::new(); - let result = vm.run(&module)?; + let result = vm.run(&Arc::new(module))?; Ok((vm, result)) } diff --git a/crates/oxide_builtins/tests/object_boundary_tests.rs b/crates/oxide_builtins/tests/object_boundary_tests.rs index aaa0f382..92b6acf1 100644 --- a/crates/oxide_builtins/tests/object_boundary_tests.rs +++ b/crates/oxide_builtins/tests/object_boundary_tests.rs @@ -1,3 +1,5 @@ +use std::sync::Arc; + use oxide_compiler::compiler::Compiler; use oxide_types::value::JsValue; use oxide_vm::vm::Vm; @@ -7,7 +9,7 @@ fn eval(source: &str) -> Result<(Vm, JsValue), String> { let program = oxide_parser::parse(&allocator, source).map_err(|e| format!("Parse error: {:?}", e))?; let module = Compiler::new().compile(&program).map_err(|e| format!("Compile error: {}", e))?; let mut vm = Vm::new(); - let result = vm.run(&module)?; + let result = vm.run(&Arc::new(module))?; Ok((vm, result)) } diff --git a/crates/oxide_cli/src/bench/leak_detect.rs b/crates/oxide_cli/src/bench/leak_detect.rs index 7a53a97d..d82b28ef 100644 --- a/crates/oxide_cli/src/bench/leak_detect.rs +++ b/crates/oxide_cli/src/bench/leak_detect.rs @@ -287,7 +287,7 @@ pub fn run_mem_dirty_rebuild_leak(kernel: &Arc) -> ExitCode { return ExitCode::FAILURE; } }; - if let Err(e) = vm.run(&module) { + if let Err(e) = vm.run(&Arc::new(module)) { eprintln!("[dirty_rebuild] round {round} run failed: {e}"); return ExitCode::FAILURE; } @@ -581,7 +581,7 @@ pub fn run_mem_kernel_lifetime() -> ExitCode { Err(_) => return ExitCode::FAILURE, }; let js_module = match Compiler::new().compile(&program) { - Ok(m) => m, + Ok(m) => Arc::new(m), Err(e) => { eprintln!("[kernel_lifetime] js phase compile failed: {e}"); return ExitCode::FAILURE; diff --git a/crates/oxide_dce/tests/precise_eq.rs b/crates/oxide_dce/tests/precise_eq.rs index 209b3cfa..a9aa0a69 100644 --- a/crates/oxide_dce/tests/precise_eq.rs +++ b/crates/oxide_dce/tests/precise_eq.rs @@ -4,6 +4,8 @@ //! 对比顶层执行结果。**不经 `Compiler::compile`**(测试层直调底层函数)。顶层赋值 / //! escaped 槽样例做字节码/IR 级断言,is_top_level 标志直接断言。 +use std::sync::Arc; + use oxide_bytecode::opcode::OpCode; use oxide_vm::vm::Vm; use oxide_vm::JsValue; @@ -23,7 +25,7 @@ fn run_source(src: &str, precise: bool) -> Result { } let module = oxide_ir::lower::lower(&ir).expect("lower failed"); let mut vm = Vm::new(); - vm.run(&module) + vm.run(&Arc::new(module)) } /// 结果规约成可断言形态:`(是否 Ok, 字符串化结果或错误消息)`。 diff --git a/crates/oxide_dce/tests/runtime_eq.rs b/crates/oxide_dce/tests/runtime_eq.rs index 349bf89e..f221776d 100644 --- a/crates/oxide_dce/tests/runtime_eq.rs +++ b/crates/oxide_dce/tests/runtime_eq.rs @@ -4,6 +4,8 @@ //! 对比顶层执行结果。副作用纯表读错 VM handler 也能被此兜底。 //! **不经 `Compiler::compile`**:测试层直调底层函数,不依赖编译器开关。 +use std::sync::Arc; + use oxide_vm::vm::Vm; use oxide_vm::JsValue; @@ -19,7 +21,7 @@ fn run_source(src: &str, dce: bool) -> Result { } let module = oxide_ir::lower::lower(&ir).expect("lower failed"); let mut vm = Vm::new(); - vm.run(&module) + vm.run(&Arc::new(module)) } /// 结果规约成可断言形态:`(是否 Ok, 字符串化结果或错误消息)`。 diff --git a/crates/oxide_regalloc/tests/nested_parent_slot_regress.rs b/crates/oxide_regalloc/tests/nested_parent_slot_regress.rs index 19ef4e64..a3bc87ce 100644 --- a/crates/oxide_regalloc/tests/nested_parent_slot_regress.rs +++ b/crates/oxide_regalloc/tests/nested_parent_slot_regress.rs @@ -5,6 +5,8 @@ //! on={object} vs off=42)。修复:graph.rs/rewrite.rs 对称 collect_own_escaped。 //! 槽号 ≥ inherited_reg_start(param_layout.base)时触发,故用高压力变量推高槽号。 +use std::sync::Arc; + use oxide_vm::vm::Vm; fn run_source(src: &str, regalloc: bool) -> (bool, String) { @@ -33,7 +35,7 @@ fn run_source(src: &str, regalloc: bool) -> (bool, String) { Err(e) => return (false, format!("lower error: {e}")), }; let mut vm = Vm::new(); - match vm.run(&module) { + match vm.run(&Arc::new(module)) { Ok(v) => (true, v.to_string()), Err(e) => (false, e), } diff --git a/crates/oxide_regalloc/tests/runtime_eq.rs b/crates/oxide_regalloc/tests/runtime_eq.rs index 11bdae3f..d97315dc 100644 --- a/crates/oxide_regalloc/tests/runtime_eq.rs +++ b/crates/oxide_regalloc/tests/runtime_eq.rs @@ -3,6 +3,8 @@ //! 同一 JS 源码走两条管线:parse → emit → dce(保守恒定)→(regalloc on/off)→ lower → run, //! 对比顶层执行结果。**不经 Compiler::compile**(测试层直调底层函数)。 +use std::sync::Arc; + use oxide_bytecode::opcode::OpCode; use oxide_vm::vm::Vm; use oxide_vm::JsValue; @@ -29,7 +31,7 @@ fn run_source(src: &str, regalloc: bool) -> Result { let mut module = module; oxide_compiler::flatten::flatten_submodules(&mut module); let mut vm = Vm::new(); - vm.run(&module) + vm.run(&Arc::new(module)) } /// 结果规约成可断言形态:`(是否 Ok, 字符串化结果或错误消息)`。 diff --git a/crates/oxide_test262/src/main.rs b/crates/oxide_test262/src/main.rs index f8db1c9f..90e9a59c 100644 --- a/crates/oxide_test262/src/main.rs +++ b/crates/oxide_test262/src/main.rs @@ -695,7 +695,7 @@ fn run_test_inner( }; let mut vm = Vm::with_kernel_core(Arc::clone(kernel)); - let run_result = vm.run(&module); + let run_result = vm.run(&Arc::new(module)); let dur = start.elapsed().as_millis() as u64; if is_async { diff --git a/crates/oxide_vm/benches/call.rs b/crates/oxide_vm/benches/call.rs index 84f5b088..c6d5d262 100644 --- a/crates/oxide_vm/benches/call.rs +++ b/crates/oxide_vm/benches/call.rs @@ -9,7 +9,7 @@ fn bench_call(c: &mut Criterion) { let js = "function fib(n) { if (n < 2) return n; return fib(n-1) + fib(n-2); } fib(15);"; let alloc = oxide_parser::Allocator::default(); let program = oxide_parser::parse(&alloc, js).expect("parse"); - let module = Compiler::new().compile(&program).expect("compile"); + let module = Arc::new(Compiler::new().compile(&program).expect("compile")); c.bench_function("call", |b| { b.iter_batched( diff --git a/crates/oxide_vm/benches/coercion.rs b/crates/oxide_vm/benches/coercion.rs index 6b2fa254..db438773 100644 --- a/crates/oxide_vm/benches/coercion.rs +++ b/crates/oxide_vm/benches/coercion.rs @@ -9,7 +9,7 @@ fn bench_coercion(c: &mut Criterion) { let js = "var x = \"42\"; var y = \"3.14\"; var r = 0; for (var i = 0; i < 5000; i++) { r += (+x) + (+y); } r"; let alloc = oxide_parser::Allocator::default(); let program = oxide_parser::parse(&alloc, js).expect("parse"); - let module = Compiler::new().compile(&program).expect("compile"); + let module = Arc::new(Compiler::new().compile(&program).expect("compile")); c.bench_function("coercion", |b| { b.iter_batched( diff --git a/crates/oxide_vm/benches/dispatch.rs b/crates/oxide_vm/benches/dispatch.rs index dd01b432..73ff187e 100644 --- a/crates/oxide_vm/benches/dispatch.rs +++ b/crates/oxide_vm/benches/dispatch.rs @@ -9,7 +9,7 @@ fn bench_dispatch(c: &mut Criterion) { let js = "var x = 0; for (var i = 0; i < 10000; i++) { x = x + i - i * 2 + (i % 3); } x"; let alloc = oxide_parser::Allocator::default(); let program = oxide_parser::parse(&alloc, js).expect("parse"); - let module = Compiler::new().compile(&program).expect("compile"); + let module = Arc::new(Compiler::new().compile(&program).expect("compile")); c.bench_function("dispatch", |b| { b.iter_batched( diff --git a/crates/oxide_vm/benches/gc_mark_sweep.rs b/crates/oxide_vm/benches/gc_mark_sweep.rs index 7e33ceab..7a4f1886 100644 --- a/crates/oxide_vm/benches/gc_mark_sweep.rs +++ b/crates/oxide_vm/benches/gc_mark_sweep.rs @@ -11,7 +11,7 @@ fn bench_gc(c: &mut Criterion) { let js = "var g = {}; for (var i = 0; i < 500; i++) { var obj = { x: i, y: i * 2 }; g[i] = obj; } g[\"x\"]"; let alloc = oxide_parser::Allocator::default(); let program = oxide_parser::parse(&alloc, js).expect("parse"); - let module = Compiler::new().compile(&program).expect("compile"); + let module = Arc::new(Compiler::new().compile(&program).expect("compile")); c.bench_function("gc_mark_sweep", |b| { b.iter_batched( diff --git a/crates/oxide_vm/benches/property.rs b/crates/oxide_vm/benches/property.rs index 8f811c41..b6b9d286 100644 --- a/crates/oxide_vm/benches/property.rs +++ b/crates/oxide_vm/benches/property.rs @@ -9,7 +9,7 @@ fn bench_property(c: &mut Criterion) { let js = "var obj = { a: 1, b: 2, c: 3, d: 4, e: 5 }; var sum = 0; for (var i = 0; i < 10000; i++) { sum += obj.a + obj.b + obj.c + obj.d + obj.e; } sum"; let alloc = oxide_parser::Allocator::default(); let program = oxide_parser::parse(&alloc, js).expect("parse"); - let module = Compiler::new().compile(&program).expect("compile"); + let module = Arc::new(Compiler::new().compile(&program).expect("compile")); c.bench_function("property", |b| { b.iter_batched( diff --git a/crates/oxide_vm/src/session_gc.rs b/crates/oxide_vm/src/session_gc.rs index d2f5d31d..0aa67d6b 100644 --- a/crates/oxide_vm/src/session_gc.rs +++ b/crates/oxide_vm/src/session_gc.rs @@ -959,6 +959,8 @@ mod tests { use oxide_types::object::JsObject; use oxide_types::value::JsValue; + use std::sync::Arc; + use super::*; use crate::vm::{CallFrame, FrameContinuation}; use oxide_builtins::{array_buffer, data_view, map, set, typed_array}; @@ -1612,8 +1614,10 @@ mod tests { #[test] fn closure_cell_survives_object_sweep() { let mut vm = vm_with_threshold(1); - vm.run(&compile("var counter = 0; function inc() { return ++counter; } globalThis.inc = inc; 0")) - .expect("run1"); + vm.run(&Arc::new(compile( + "var counter = 0; function inc() { return ++counter; } globalThis.inc = inc; 0", + ))) + .expect("run1"); assert!(!vm.gc_state.session_cell_ptrs.borrow().is_empty(), "run1 应分配 upvalue cell"); // reset 触发对象 sweep:存活对象搬到新 arena,旧 arena 释放。 @@ -1636,10 +1640,10 @@ mod tests { #[test] fn private_brand_cell_survives_object_sweep() { let mut vm = vm_with_threshold(1); - vm.run(&compile( + vm.run(&Arc::new(compile( "class C { #x = 0; set(v){ this.#x = v; } get(){ return this.#x; } } \ globalThis.c = new C(); globalThis.c.set(4); 0", - )) + ))) .expect("run1"); vm.reset(); @@ -1664,14 +1668,16 @@ mod tests { #[test] fn cells_freed_by_full_reset_and_reallocatable() { let mut vm = Vm::new(); - vm.run(&compile("var x = 1; function f() { return x; } globalThis.f = f; f()")) + vm.run(&Arc::new(compile("var x = 1; function f() { return x; } globalThis.f = f; f()"))) .expect("run1"); assert!(!vm.gc_state.session_cell_ptrs.borrow().is_empty()); vm.full_reset(); assert!(vm.gc_state.session_cell_ptrs.borrow().is_empty(), "full_reset 应释放全部 cell"); - let result = vm.run(&compile("var y = 2; function g() { return y; } g()")).expect("run2"); + let result = vm + .run(&Arc::new(compile("var y = 2; function g() { return y; } g()"))) + .expect("run2"); assert_eq!(format!("{result}"), "2", "重置后新 cell 应正常分配与读取"); } diff --git a/crates/oxide_vm/src/vm.rs b/crates/oxide_vm/src/vm.rs index 21f0489f..3914460b 100644 --- a/crates/oxide_vm/src/vm.rs +++ b/crates/oxide_vm/src/vm.rs @@ -446,8 +446,8 @@ pub struct Vm { pub math_rng_state: u64, /// 全局扁平模块表:下标 = 模块 `flat_id`(顶层 0,子模块 flatten 后全局唯一)。 /// 闭包 `sub_module_index` 即 flat_id,逃逸闭包也能自足解析。 - /// 条目为 `Arc`,与调用方模块树共享(`run()` 只做 Arc::clone, - /// 不再每次深拷贝整棵子树)。 + /// 条目为 `Arc`,与调用方模块树共享:顶层条目即调用方模块 + /// Arc 同一实例,`run()` 全程只做 Arc::clone,无深拷贝。 pub(crate) sub_modules: Arc>>, /// 帧切换时暂存调用方字节码的 Arc 栈(与 `bytecode` 同共享语义)。 pub(crate) saved_bytecode_stack: Vec>, @@ -2801,7 +2801,8 @@ mod tests { is_async: false, }); - vm.run(&module).expect("FOR_OF_CLOSE should tolerate non-object sentinel"); + vm.run(&Arc::new(module)) + .expect("FOR_OF_CLOSE should tolerate non-object sentinel"); assert!(vm.iters.for_of_iters.is_empty()); } @@ -2854,7 +2855,9 @@ mod tests { ..CompiledModule::new() }; let mut vm = Vm::new(); - let err = vm.run(&module).expect_err("unimplemented opcode should fail explicitly"); + let err = vm + .run(&Arc::new(module)) + .expect_err("unimplemented opcode should fail explicitly"); assert_eq!(err, "opcode PROFILE_SHAPE not yet implemented"); } diff --git a/crates/oxide_vm/src/vm_runtime.rs b/crates/oxide_vm/src/vm_runtime.rs index e404f264..a4dd8a05 100644 --- a/crates/oxide_vm/src/vm_runtime.rs +++ b/crates/oxide_vm/src/vm_runtime.rs @@ -9,12 +9,13 @@ use oxide_types::value::JsValue; /// 按 `flat_id` 下标收集整棵子模块树为平表,供 `run()` 装载。 /// -/// 子模块节点以 `Arc` 与调用方模块树共享:只做 Arc::clone(O(1) 引用计数), -/// 不再深拷贝 constants/upvalue_captures 等。顶层模块本身以浅拷贝包 Arc—— -/// 其自有 constants 仍逐 run 复制,但整棵子树零深拷贝。 -fn collect_flat_modules(module: &CompiledModule) -> Vec> { +/// 顶层与子模块一律 `Arc` 共享:只做 Arc::clone(O(1) 引用计数),run 期 +/// 零模块拷贝。唯一可写面 = bytecode 缓冲,经 `bytecode_mut` 的 COW 写时 +/// 复制——dispatch 期平表与 `Vm.bytecode` 双持(refcount ≥ 2),写必落在 +/// 私有拷贝上,宿主侧共享缓冲永不被写。 +fn collect_flat_modules(module: &Arc) -> Vec> { let mut out: Vec>> = Vec::new(); - let top = Arc::new(module.clone()); + let top = Arc::clone(module); place_flat(&top, &mut out); out.into_iter().map(|m| m.expect("flat_id slot must be filled")).collect() } @@ -518,9 +519,10 @@ impl Vm { /// 加载并执行一个已编译模块,返回模块顶层执行结果或未捕获异常消息。 /// - /// 内部初始化寄存器/bytecode/immutables 与 builtin 寄存器预绑定,然后进入 - /// dispatch 主循环;执行完成或异常展开后返回。 - pub fn run(&mut self, module: &CompiledModule) -> Result { + /// 模块以 `Arc` 与调用方共享(如 CodeForge 缓存条目):平表装载只做 + /// Arc::clone,run 期零模块拷贝。内部初始化寄存器/bytecode/immutables 与 + /// builtin 寄存器预绑定,然后进入 dispatch 主循环;执行完成或异常展开后返回。 + pub fn run(&mut self, module: &Arc) -> Result { vm_debug!("run: starting bytecode execution, {} instructions", module.bytecode.len()); self.clear_execution_state(); // 模板对象缓存按 run 清空:flat_id 每次 run 从 0 重新分配,跨 run 复用会 diff --git a/crates/oxide_vm/src/vm_support.rs b/crates/oxide_vm/src/vm_support.rs index 8e45534a..fea27f88 100644 --- a/crates/oxide_vm/src/vm_support.rs +++ b/crates/oxide_vm/src/vm_support.rs @@ -821,7 +821,7 @@ mod tests { let module = oxide_compiler::compiler::Compiler::new() .compile(&program) .expect("compile failed"); - vm.run(&module).expect("vm run failed") + vm.run(&Arc::new(module)).expect("vm run failed") } /// 计数往返:两条构造路径(独立核/共享核)的登记与 Drop 注销恰好配对, @@ -981,7 +981,9 @@ mod tests { let module = oxide_compiler::compiler::Compiler::new() .compile(&program) .expect("compile failed"); - let err = vm.run(&module).expect_err("runaway allocation must hit the alloc cap"); + let err = vm + .run(&Arc::new(module)) + .expect_err("runaway allocation must hit the alloc cap"); assert!(err.contains("memory limit"), "unexpected error: {err}"); assert!(!err.contains("step limit"), "cap 应先于步数上限生效: {err}"); } @@ -1015,7 +1017,7 @@ mod tests { let module = oxide_compiler::compiler::Compiler::new() .compile(&program) .expect("compile failed"); - let err = vm.run(&module).expect_err("reentry pump must hit the alloc cap"); + let err = vm.run(&Arc::new(module)).expect_err("reentry pump must hit the alloc cap"); assert!(err.contains("memory limit"), "unexpected error: {err}"); } diff --git a/crates/oxide_vm/tests/arguments_tests.rs b/crates/oxide_vm/tests/arguments_tests.rs index 21900457..720115f6 100644 --- a/crates/oxide_vm/tests/arguments_tests.rs +++ b/crates/oxide_vm/tests/arguments_tests.rs @@ -1,6 +1,8 @@ //! arguments 对象执行语义测试:实参个数/索引读取、箭头函数词法继承、 //! 默认参数引用、方法调用、闭包捕获、显式声明屏蔽、嵌套函数调用帧边界。 +use std::sync::Arc; + use oxide_compiler::compiler::Compiler; use oxide_types::value::JsValue; use oxide_vm::vm::Vm; @@ -9,7 +11,7 @@ fn eval(vm: &mut Vm, source: &str) -> Result { let allocator = oxide_parser::Allocator::default(); let program = oxide_parser::parse(&allocator, source).map_err(|e| format!("Parse error: {:?}", e))?; let module = Compiler::new().compile(&program).map_err(|e| format!("Compile error: {}", e))?; - vm.run(&module) + vm.run(&Arc::new(module)) } #[test] diff --git a/crates/oxide_vm/tests/arithmetic_tests.rs b/crates/oxide_vm/tests/arithmetic_tests.rs index 748df734..81530bee 100644 --- a/crates/oxide_vm/tests/arithmetic_tests.rs +++ b/crates/oxide_vm/tests/arithmetic_tests.rs @@ -1,3 +1,5 @@ +use std::sync::Arc; + use oxide_compiler::compiler::Compiler; use oxide_parser::Allocator; use oxide_vm::vm::Vm; @@ -13,7 +15,7 @@ fn eval(source: &str) -> String { Err(e) => return format!("compile error: {e}"), }; let mut vm = Vm::new(); - match vm.run(&module) { + match vm.run(&Arc::new(module)) { Ok(result) => format!("{result}"), Err(e) => format!("vm error: {e}"), } @@ -25,7 +27,7 @@ fn eval_str(source: &str) -> String { let program = oxide_parser::parse(&allocator, source).expect("parse ok"); let module = Compiler::new().compile(&program).expect("compile ok"); let mut vm = Vm::new(); - let val = vm.run(&module).expect("run ok"); + let val = vm.run(&Arc::new(module)).expect("run ok"); if val.is_string() { vm.lookup_str(val).unwrap_or_default() } else { diff --git a/crates/oxide_vm/tests/arrow_tests.rs b/crates/oxide_vm/tests/arrow_tests.rs index c41b4fcd..7d4353b2 100644 --- a/crates/oxide_vm/tests/arrow_tests.rs +++ b/crates/oxide_vm/tests/arrow_tests.rs @@ -1,3 +1,5 @@ +use std::sync::Arc; + use oxide_compiler::compiler::Compiler; use oxide_parser::Allocator; use oxide_types::value::JsValue; @@ -14,7 +16,7 @@ fn eval(source: &str) -> String { Err(e) => return format!("compile error: {}", e), }; let mut vm = Vm::new(); - match vm.run(&module) { + match vm.run(&Arc::new(module)) { Ok(result) => format!("{}", result), Err(e) => format!("vm error: {}", e), } @@ -31,7 +33,7 @@ fn eval_val(source: &str) -> (Vm, Result) { Err(e) => return (Vm::new(), Err(format!("compile error: {}", e))), }; let mut vm = Vm::new(); - let result = vm.run(&module); + let result = vm.run(&Arc::new(module)); (vm, result) } diff --git a/crates/oxide_vm/tests/async_tests.rs b/crates/oxide_vm/tests/async_tests.rs index bc1984e7..8b59b062 100644 --- a/crates/oxide_vm/tests/async_tests.rs +++ b/crates/oxide_vm/tests/async_tests.rs @@ -1,6 +1,8 @@ //! async/await 运行时测试:异步函数调用返回 promise、await 恢复、reject 进 catch、 //! 多 await 顺序、嵌套 async、微任务执行序。 +use std::sync::Arc; + use oxide_compiler::compiler::Compiler; use oxide_parser::Allocator; use oxide_vm::promise::promise_settled_value; @@ -18,7 +20,7 @@ fn eval(source: &str) -> String { Err(e) => return format!("compile error: {e}"), }; let mut vm = Vm::new(); - match vm.run(&module) { + match vm.run(&Arc::new(module)) { Ok(result) => format_value(&vm, result), Err(e) => format!("vm error: {e}"), } diff --git a/crates/oxide_vm/tests/block_function_decl_tests.rs b/crates/oxide_vm/tests/block_function_decl_tests.rs index 2e760200..105b5459 100644 --- a/crates/oxide_vm/tests/block_function_decl_tests.rs +++ b/crates/oxide_vm/tests/block_function_decl_tests.rs @@ -3,6 +3,8 @@ //! 覆盖:普通块内函数、块内后续调用、提前调用(阶段 1 现状)、与 let 同名冲突、 //! 捕获路径、嵌套块作用域隔离、重复声明(Annex B 最后生效)、单语句块体。 +use std::sync::Arc; + use oxide_compiler::compiler::Compiler; use oxide_types::value::JsValue; use oxide_vm::vm::Vm; @@ -12,7 +14,7 @@ fn eval(source: &str) -> Result { let program = oxide_parser::parse(&allocator, source).map_err(|e| format!("Parse: {:?}", e))?; let module = Compiler::new().compile(&program).map_err(|e| format!("Compile: {}", e))?; let mut vm = Vm::new(); - vm.run(&module) + vm.run(&Arc::new(module)) } #[test] diff --git a/crates/oxide_vm/tests/builtins_array_buffer_tests.rs b/crates/oxide_vm/tests/builtins_array_buffer_tests.rs index 97464e2b..34587810 100644 --- a/crates/oxide_vm/tests/builtins_array_buffer_tests.rs +++ b/crates/oxide_vm/tests/builtins_array_buffer_tests.rs @@ -1,3 +1,5 @@ +use std::sync::Arc; + use oxide_compiler::compiler::Compiler; use oxide_types::value::JsValue; use oxide_vm::vm::Vm; @@ -6,7 +8,7 @@ fn eval(vm: &mut Vm, source: &str) -> Result { let allocator = oxide_parser::Allocator::default(); let program = oxide_parser::parse(&allocator, source).map_err(|e| format!("Parse error: {:?}", e))?; let module = Compiler::new().compile(&program).map_err(|e| format!("Compile error: {}", e))?; - vm.run(&module) + vm.run(&Arc::new(module)) } fn to_str(vm: &Vm, val: JsValue) -> String { diff --git a/crates/oxide_vm/tests/builtins_array_tests.rs b/crates/oxide_vm/tests/builtins_array_tests.rs index 739f52af..a2212352 100644 --- a/crates/oxide_vm/tests/builtins_array_tests.rs +++ b/crates/oxide_vm/tests/builtins_array_tests.rs @@ -1,3 +1,5 @@ +use std::sync::Arc; + use oxide_builtins::array::{array_constructor, array_push}; use oxide_compiler::compiler::Compiler; use oxide_types::value::JsValue; @@ -8,7 +10,7 @@ fn eval(source: &str) -> Result<(Vm, JsValue), String> { let program = oxide_parser::parse(&allocator, source).map_err(|e| format!("Parse error: {:?}", e))?; let module = Compiler::new().compile(&program).map_err(|e| format!("Compile error: {}", e))?; let mut vm = Vm::new(); - let result = vm.run(&module)?; + let result = vm.run(&Arc::new(module))?; Ok((vm, result)) } diff --git a/crates/oxide_vm/tests/builtins_async_disposable_stack_tests.rs b/crates/oxide_vm/tests/builtins_async_disposable_stack_tests.rs index 4d7b7f47..4d2385e4 100644 --- a/crates/oxide_vm/tests/builtins_async_disposable_stack_tests.rs +++ b/crates/oxide_vm/tests/builtins_async_disposable_stack_tests.rs @@ -1,6 +1,8 @@ //! AsyncDisposableStack 内置对象测试:构造器/原型形状、use 读取顺序与入栈语义、 //! disposeAsync 状态机(微任务序/错误链/防重入/reject 而非抛)、move、GC 交叉。 +use std::sync::Arc; + use oxide_compiler::compiler::Compiler; use oxide_kernel::kernel::{KernelConfig, KernelCore}; use oxide_parser::Allocator; @@ -19,7 +21,7 @@ fn eval(source: &str) -> String { Err(e) => return format!("compile error: {e}"), }; let mut vm = Vm::new(); - match vm.run(&module) { + match vm.run(&Arc::new(module)) { Ok(result) => format_value(&vm, result), Err(e) => format!("vm error: {e}"), } @@ -487,11 +489,11 @@ fn gc_runtime_collection_keeps_entries() { ) .expect("parse"); let module = Compiler::new().compile(&program).expect("compile"); - vm.run(&module).expect("run1"); + vm.run(&Arc::new(module)).expect("run1"); let allocator = Allocator::default(); let program2 = oxide_parser::parse(&allocator, "globalThis.log.length + ''").expect("parse"); let module2 = Compiler::new().compile(&program2).expect("compile"); - let result = vm.run(&module2).expect("run2"); + let result = vm.run(&Arc::new(module2)).expect("run2"); let text = vm.lookup_str(result).unwrap_or_default().to_string(); assert_eq!(text, "200"); assert!(vm.session_gc_stats().total_collections > 0, "低阈值应触发执行期 GC"); @@ -512,7 +514,7 @@ fn promote_then_reset_keeps_entries_alive() { ) .expect("parse"); let module = Compiler::new().compile(&program).expect("compile"); - vm.run(&module).expect("run1"); + vm.run(&Arc::new(module)).expect("run1"); vm.reset(); let allocator = Allocator::default(); let program2 = oxide_parser::parse( @@ -522,7 +524,7 @@ fn promote_then_reset_keeps_entries_alive() { ) .expect("parse"); let module2 = Compiler::new().compile(&program2).expect("compile"); - let result = vm.run(&module2).expect("run2"); + let result = vm.run(&Arc::new(module2)).expect("run2"); let text = vm.lookup_str(result).unwrap_or_default().to_string(); assert_eq!(text, "true|false"); } @@ -535,7 +537,7 @@ fn drop_accounts_capability_bytes() { let program = oxide_parser::parse(&allocator, "for (var i = 0; i < 500; i++) { new AsyncDisposableStack(); } 0") .expect("parse"); let module = Compiler::new().compile(&program).expect("compile"); - vm.run(&module).expect("run"); + vm.run(&Arc::new(module)).expect("run"); let before = vm.session_gc_stats().total_bytes_freed; vm.reset(); let after = vm.session_gc_stats().total_bytes_freed; @@ -551,7 +553,7 @@ fn full_reset_rebuilds_async_disposable_stack() { let allocator = Allocator::default(); let program = oxide_parser::parse(&allocator, "new AsyncDisposableStack().disposeAsync(); 0").expect("parse"); let module = Compiler::new().compile(&program).expect("compile"); - vm.run(&module).expect("run1"); + vm.run(&Arc::new(module)).expect("run1"); vm.full_reset(); let allocator = Allocator::default(); let program2 = oxide_parser::parse( @@ -566,7 +568,7 @@ fn full_reset_rebuilds_async_disposable_stack() { ) .expect("parse"); let module2 = Compiler::new().compile(&program2).expect("compile"); - let result = vm.run(&module2).expect("run2"); + let result = vm.run(&Arc::new(module2)).expect("run2"); let text = match promise_settled_value(unsafe { &*result.as_js_object_ptr() }) { Some((true, v)) => vm.lookup_str(v).unwrap_or_default().to_string(), Some((false, v)) => format!("", vm.lookup_str(v).unwrap_or_default()), diff --git a/crates/oxide_vm/tests/builtins_boolean_tests.rs b/crates/oxide_vm/tests/builtins_boolean_tests.rs index 958455ae..bcb6bf50 100644 --- a/crates/oxide_vm/tests/builtins_boolean_tests.rs +++ b/crates/oxide_vm/tests/builtins_boolean_tests.rs @@ -1,3 +1,5 @@ +use std::sync::Arc; + use oxide_builtins::boolean::{boolean_constructor, boolean_prototype_to_string, boolean_prototype_value_of}; use oxide_compiler::compiler::Compiler; use oxide_types::object::JsObject; @@ -10,7 +12,7 @@ fn eval(vm: &mut Vm, source: &str) -> Result { let allocator = oxide_parser::Allocator::default(); let program = oxide_parser::parse(&allocator, source).map_err(|e| format!("Parse error: {:?}", e))?; let module = Compiler::new().compile(&program).map_err(|e| format!("Compile error: {}", e))?; - vm.run(&module) + vm.run(&Arc::new(module)) } fn str_val(vm: &Vm, val: JsValue) -> String { diff --git a/crates/oxide_vm/tests/builtins_data_view_tests.rs b/crates/oxide_vm/tests/builtins_data_view_tests.rs index 2b97bdf1..5a78dc4d 100644 --- a/crates/oxide_vm/tests/builtins_data_view_tests.rs +++ b/crates/oxide_vm/tests/builtins_data_view_tests.rs @@ -1,3 +1,5 @@ +use std::sync::Arc; + use oxide_compiler::compiler::Compiler; use oxide_types::value::JsValue; use oxide_vm::vm::Vm; @@ -6,7 +8,7 @@ fn eval(vm: &mut Vm, source: &str) -> Result { let allocator = oxide_parser::Allocator::default(); let program = oxide_parser::parse(&allocator, source).map_err(|e| format!("Parse error: {:?}", e))?; let module = Compiler::new().compile(&program).map_err(|e| format!("Compile error: {}", e))?; - vm.run(&module) + vm.run(&Arc::new(module)) } fn to_str(vm: &Vm, val: JsValue) -> String { diff --git a/crates/oxide_vm/tests/builtins_date_tests.rs b/crates/oxide_vm/tests/builtins_date_tests.rs index c55dcb70..117713d0 100644 --- a/crates/oxide_vm/tests/builtins_date_tests.rs +++ b/crates/oxide_vm/tests/builtins_date_tests.rs @@ -1,3 +1,5 @@ +use std::sync::Arc; + use oxide_compiler::compiler::Compiler; use oxide_vm::vm::Vm; @@ -5,7 +7,7 @@ fn eval(vm: &mut Vm, source: &str) -> Result String { diff --git a/crates/oxide_vm/tests/builtins_disposable_stack_tests.rs b/crates/oxide_vm/tests/builtins_disposable_stack_tests.rs index 37d2163a..1702fac5 100644 --- a/crates/oxide_vm/tests/builtins_disposable_stack_tests.rs +++ b/crates/oxide_vm/tests/builtins_disposable_stack_tests.rs @@ -1,3 +1,5 @@ +use std::sync::Arc; + use oxide_compiler::compiler::Compiler; use oxide_kernel::kernel::{KernelConfig, KernelCore}; use oxide_vm::vm::Vm; @@ -10,7 +12,7 @@ fn eval_in(vm: &mut Vm, source: &str) -> Result Result { let program = oxide_parser::parse(&allocator, source).map_err(|e| format!("Parse: {:?}", e))?; let module = Compiler::new().compile(&program).map_err(|e| format!("Compile: {}", e))?; let mut vm = make_vm(); - vm.run(&module) + vm.run(&Arc::new(module)) } /// 在既有 Vm 内编译执行:结果字符串须在同一 Vm 上下文解析(session 串随 Vm 释放)。 @@ -22,7 +24,7 @@ fn eval_in(vm: &mut Vm, source: &str) -> Result { let allocator = oxide_parser::Allocator::default(); let program = oxide_parser::parse(&allocator, source).map_err(|e| format!("Parse: {:?}", e))?; let module = Compiler::new().compile(&program).map_err(|e| format!("Compile: {}", e))?; - vm.run(&module) + vm.run(&Arc::new(module)) } #[test] @@ -482,7 +484,7 @@ fn error_stack_is_string() { let program = oxide_parser::parse(&allocator, "typeof new Error().stack()").unwrap(); let module = Compiler::new().compile(&program).unwrap(); let mut vm = make_vm(); - let result = vm.run(&module).unwrap(); + let result = vm.run(&Arc::new(module)).unwrap(); // typeof 结果复用进程级静态串,同 VM 上读取(跨 VM 指针存活由实现保证,不做假设)。 let s = vm.lookup_str(result); assert_eq!(s, Some("string".to_string())); diff --git a/crates/oxide_vm/tests/builtins_function_tests.rs b/crates/oxide_vm/tests/builtins_function_tests.rs index 53267293..a383acd6 100644 --- a/crates/oxide_vm/tests/builtins_function_tests.rs +++ b/crates/oxide_vm/tests/builtins_function_tests.rs @@ -1,3 +1,5 @@ +use std::sync::Arc; + use oxide_compiler::compiler::Compiler; use oxide_types::value::JsValue; use oxide_vm::vm::Vm; @@ -6,7 +8,7 @@ fn eval(vm: &mut Vm, source: &str) -> Result { let allocator = oxide_parser::Allocator::default(); let program = oxide_parser::parse(&allocator, source).map_err(|e| format!("Parse error: {:?}", e))?; let module = Compiler::new().compile(&program).map_err(|e| format!("Compile error: {}", e))?; - vm.run(&module) + vm.run(&Arc::new(module)) } /// 数值断言:整数运算保 int,容忍 int/double 两种表示。 diff --git a/crates/oxide_vm/tests/builtins_globals_tests.rs b/crates/oxide_vm/tests/builtins_globals_tests.rs index 5271d624..743a8d0a 100644 --- a/crates/oxide_vm/tests/builtins_globals_tests.rs +++ b/crates/oxide_vm/tests/builtins_globals_tests.rs @@ -1,3 +1,5 @@ +use std::sync::Arc; + use oxide_compiler::compiler::Compiler; use oxide_parser::Allocator; use oxide_types::value::JsValue; @@ -8,7 +10,7 @@ fn eval(source: &str) -> Result { let program = oxide_parser::parse(&allocator, source).map_err(|e| format!("Parse error: {:?}", e))?; let module = Compiler::new().compile(&program).map_err(|e| format!("Compile error: {}", e))?; let mut vm = Vm::new(); - vm.run(&module) + vm.run(&Arc::new(module)) } fn eval_with_vm(source: &str) -> (Vm, Result) { @@ -16,7 +18,7 @@ fn eval_with_vm(source: &str) -> (Vm, Result) { let program = oxide_parser::parse(&allocator, source).expect("parse"); let module = Compiler::new().compile(&program).expect("compile"); let mut vm = Vm::new(); - let result = vm.run(&module); + let result = vm.run(&Arc::new(module)); (vm, result) } diff --git a/crates/oxide_vm/tests/builtins_iterator_tests.rs b/crates/oxide_vm/tests/builtins_iterator_tests.rs index a9bebb3c..d4125f88 100644 --- a/crates/oxide_vm/tests/builtins_iterator_tests.rs +++ b/crates/oxide_vm/tests/builtins_iterator_tests.rs @@ -1,3 +1,5 @@ +use std::sync::Arc; + use oxide_compiler::compiler::Compiler; use oxide_types::object::JsObject; use oxide_types::value::JsValue; @@ -7,7 +9,7 @@ fn eval(vm: &mut Vm, source: &str) -> Result { let allocator = oxide_parser::Allocator::default(); let program = oxide_parser::parse(&allocator, source).map_err(|e| format!("Parse error: {:?}", e))?; let module = Compiler::new().compile(&program).map_err(|e| format!("Compile error: {}", e))?; - vm.run(&module) + vm.run(&Arc::new(module)) } fn to_str(vm: &Vm, val: JsValue) -> String { diff --git a/crates/oxide_vm/tests/builtins_map_tests.rs b/crates/oxide_vm/tests/builtins_map_tests.rs index 9961c197..50c3705a 100644 --- a/crates/oxide_vm/tests/builtins_map_tests.rs +++ b/crates/oxide_vm/tests/builtins_map_tests.rs @@ -1,3 +1,5 @@ +use std::sync::Arc; + use oxide_builtins::map::{map_clear, map_constructor as new_map, map_delete, map_get, map_has, map_set, map_size}; use oxide_compiler::compiler::Compiler; use oxide_kernel::shape_forge::EMPTY_SHAPE_ID; @@ -9,7 +11,7 @@ fn eval(vm: &mut Vm, source: &str) -> Result { let allocator = oxide_parser::Allocator::default(); let program = oxide_parser::parse(&allocator, source).map_err(|e| format!("Parse error: {:?}", e))?; let module = Compiler::new().compile(&program).map_err(|e| format!("Compile error: {}", e))?; - vm.run(&module) + vm.run(&Arc::new(module)) } fn str_val(vm: &Vm, val: JsValue) -> String { diff --git a/crates/oxide_vm/tests/builtins_math_tests.rs b/crates/oxide_vm/tests/builtins_math_tests.rs index 3aba0b2f..511d7658 100644 --- a/crates/oxide_vm/tests/builtins_math_tests.rs +++ b/crates/oxide_vm/tests/builtins_math_tests.rs @@ -1,3 +1,5 @@ +use std::sync::Arc; + use oxide_compiler::compiler::Compiler; use oxide_types::value::JsValue; use oxide_vm::vm::Vm; @@ -6,7 +8,7 @@ fn eval(vm: &mut Vm, source: &str) -> Result { let allocator = oxide_parser::Allocator::default(); let program = oxide_parser::parse(&allocator, source).map_err(|e| format!("Parse error: {:?}", e))?; let module = Compiler::new().compile(&program).map_err(|e| format!("Compile error: {}", e))?; - vm.run(&module) + vm.run(&Arc::new(module)) } #[test] diff --git a/crates/oxide_vm/tests/builtins_number_tests.rs b/crates/oxide_vm/tests/builtins_number_tests.rs index 426a31a2..65f6ced6 100644 --- a/crates/oxide_vm/tests/builtins_number_tests.rs +++ b/crates/oxide_vm/tests/builtins_number_tests.rs @@ -1,3 +1,5 @@ +use std::sync::Arc; + use oxide_compiler::compiler::Compiler; use oxide_types::value::JsValue; use oxide_vm::vm::Vm; @@ -6,7 +8,7 @@ fn eval(vm: &mut Vm, source: &str) -> Result { let allocator = oxide_parser::Allocator::default(); let program = oxide_parser::parse(&allocator, source).map_err(|e| format!("Parse error: {:?}", e))?; let module = Compiler::new().compile(&program).map_err(|e| format!("Compile error: {}", e))?; - vm.run(&module) + vm.run(&Arc::new(module)) } #[test] diff --git a/crates/oxide_vm/tests/builtins_object_tests.rs b/crates/oxide_vm/tests/builtins_object_tests.rs index 5d2c05ac..43233563 100644 --- a/crates/oxide_vm/tests/builtins_object_tests.rs +++ b/crates/oxide_vm/tests/builtins_object_tests.rs @@ -1,3 +1,5 @@ +use std::sync::Arc; + use oxide_compiler::compiler::Compiler; use oxide_types::value::JsValue; use oxide_vm::vm::Vm; @@ -7,7 +9,7 @@ fn eval(source: &str) -> Result<(Vm, JsValue), String> { let program = oxide_parser::parse(&allocator, source).map_err(|e| format!("Parse error: {:?}", e))?; let module = Compiler::new().compile(&program).map_err(|e| format!("Compile error: {}", e))?; let mut vm = Vm::new(); - let result = vm.run(&module)?; + let result = vm.run(&Arc::new(module))?; Ok((vm, result)) } diff --git a/crates/oxide_vm/tests/builtins_reflect_tests.rs b/crates/oxide_vm/tests/builtins_reflect_tests.rs index a5ffe7c6..4422e272 100644 --- a/crates/oxide_vm/tests/builtins_reflect_tests.rs +++ b/crates/oxide_vm/tests/builtins_reflect_tests.rs @@ -1,3 +1,5 @@ +use std::sync::Arc; + use oxide_compiler::compiler::Compiler; use oxide_types::value::JsValue; use oxide_vm::vm::Vm; @@ -6,7 +8,7 @@ fn eval(vm: &mut Vm, source: &str) -> Result { let allocator = oxide_parser::Allocator::default(); let program = oxide_parser::parse(&allocator, source).map_err(|e| format!("Parse error: {:?}", e))?; let module = Compiler::new().compile(&program).map_err(|e| format!("Compile error: {}", e))?; - vm.run(&module) + vm.run(&Arc::new(module)) } fn to_str(vm: &Vm, val: JsValue) -> String { diff --git a/crates/oxide_vm/tests/builtins_regexp_tests.rs b/crates/oxide_vm/tests/builtins_regexp_tests.rs index 9cca4dd4..7e9f7236 100644 --- a/crates/oxide_vm/tests/builtins_regexp_tests.rs +++ b/crates/oxide_vm/tests/builtins_regexp_tests.rs @@ -1,3 +1,5 @@ +use std::sync::Arc; + use oxide_compiler::compiler::Compiler; use oxide_types::value::JsValue; use oxide_vm::vm::Vm; @@ -6,7 +8,7 @@ fn eval(vm: &mut Vm, source: &str) -> Result { let allocator = oxide_parser::Allocator::default(); let program = oxide_parser::parse(&allocator, source).map_err(|e| format!("Parse error: {:?}", e))?; let module = Compiler::new().compile(&program).map_err(|e| format!("Compile error: {}", e))?; - vm.run(&module) + vm.run(&Arc::new(module)) } fn to_str(vm: &Vm, val: JsValue) -> String { diff --git a/crates/oxide_vm/tests/builtins_set_tests.rs b/crates/oxide_vm/tests/builtins_set_tests.rs index e1b8bb9e..6a73259a 100644 --- a/crates/oxide_vm/tests/builtins_set_tests.rs +++ b/crates/oxide_vm/tests/builtins_set_tests.rs @@ -1,3 +1,5 @@ +use std::sync::Arc; + use oxide_builtins::set::{set_add, set_clear, set_constructor as new_set, set_delete, set_has, set_size}; use oxide_compiler::compiler::Compiler; use oxide_kernel::shape_forge::EMPTY_SHAPE_ID; @@ -9,7 +11,7 @@ fn eval(vm: &mut Vm, source: &str) -> Result { let allocator = oxide_parser::Allocator::default(); let program = oxide_parser::parse(&allocator, source).map_err(|e| format!("Parse error: {:?}", e))?; let module = Compiler::new().compile(&program).map_err(|e| format!("Compile error: {}", e))?; - vm.run(&module) + vm.run(&Arc::new(module)) } /// 分配一个原型指向 Set.prototype 的占位对象并写入 reg 0,作为构造器调用的 `this`。 diff --git a/crates/oxide_vm/tests/builtins_string_tests.rs b/crates/oxide_vm/tests/builtins_string_tests.rs index 399e095d..8cbaf749 100644 --- a/crates/oxide_vm/tests/builtins_string_tests.rs +++ b/crates/oxide_vm/tests/builtins_string_tests.rs @@ -1,3 +1,5 @@ +use std::sync::Arc; + use oxide_compiler::compiler::Compiler; use oxide_types::value::JsValue; use oxide_vm::vm::Vm; @@ -6,7 +8,7 @@ fn eval(vm: &mut Vm, source: &str) -> Result { let allocator = oxide_parser::Allocator::default(); let program = oxide_parser::parse(&allocator, source).map_err(|e| format!("Parse error: {:?}", e))?; let module = Compiler::new().compile(&program).map_err(|e| format!("Compile error: {}", e))?; - vm.run(&module) + vm.run(&Arc::new(module)) } fn to_str(vm: &Vm, val: JsValue) -> String { diff --git a/crates/oxide_vm/tests/builtins_symbol_tests.rs b/crates/oxide_vm/tests/builtins_symbol_tests.rs index 84d3a1b3..1cddee90 100644 --- a/crates/oxide_vm/tests/builtins_symbol_tests.rs +++ b/crates/oxide_vm/tests/builtins_symbol_tests.rs @@ -1,3 +1,5 @@ +use std::sync::Arc; + use oxide_compiler::compiler::Compiler; use oxide_types::value::JsValue; use oxide_vm::vm::Vm; @@ -6,7 +8,7 @@ fn eval(vm: &mut Vm, source: &str) -> Result { let allocator = oxide_parser::Allocator::default(); let program = oxide_parser::parse(&allocator, source).map_err(|e| format!("Parse error: {:?}", e))?; let module = Compiler::new().compile(&program).map_err(|e| format!("Compile error: {}", e))?; - vm.run(&module) + vm.run(&Arc::new(module)) } fn to_str(vm: &Vm, val: JsValue) -> String { diff --git a/crates/oxide_vm/tests/builtins_temporal_tests.rs b/crates/oxide_vm/tests/builtins_temporal_tests.rs index b2bac855..ca97f09d 100644 --- a/crates/oxide_vm/tests/builtins_temporal_tests.rs +++ b/crates/oxide_vm/tests/builtins_temporal_tests.rs @@ -1,3 +1,5 @@ +use std::sync::Arc; + use oxide_compiler::compiler::Compiler; use oxide_vm::vm::Vm; @@ -5,7 +7,7 @@ fn eval(vm: &mut Vm, source: &str) -> Result String { diff --git a/crates/oxide_vm/tests/builtins_typed_array_tests.rs b/crates/oxide_vm/tests/builtins_typed_array_tests.rs index 43042f92..ef1ead0e 100644 --- a/crates/oxide_vm/tests/builtins_typed_array_tests.rs +++ b/crates/oxide_vm/tests/builtins_typed_array_tests.rs @@ -1,3 +1,5 @@ +use std::sync::Arc; + use oxide_compiler::compiler::Compiler; use oxide_types::value::JsValue; use oxide_vm::vm::Vm; @@ -6,7 +8,7 @@ fn eval(vm: &mut Vm, source: &str) -> Result { let allocator = oxide_parser::Allocator::default(); let program = oxide_parser::parse(&allocator, source).map_err(|e| format!("Parse error: {:?}", e))?; let module = Compiler::new().compile(&program).map_err(|e| format!("Compile error: {}", e))?; - vm.run(&module) + vm.run(&Arc::new(module)) } fn to_str(vm: &Vm, val: JsValue) -> String { diff --git a/crates/oxide_vm/tests/call_frame_window_tests.rs b/crates/oxide_vm/tests/call_frame_window_tests.rs index 78953a21..1deb1f73 100644 --- a/crates/oxide_vm/tests/call_frame_window_tests.rs +++ b/crates/oxide_vm/tests/call_frame_window_tests.rs @@ -1,6 +1,8 @@ //! 调用帧窗口按存活上界拷贝的语义测试:验证压帧窗口缩小后调用方存活寄存器、 //! this/new.target、spill 区与异常展开在各类调用路径下恢复正确。 +use std::sync::Arc; + use oxide_compiler::compiler::Compiler; use oxide_parser::Allocator; use oxide_vm::promise::promise_settled_value; @@ -19,7 +21,7 @@ fn eval(source: &str) -> String { Err(e) => return format!("compile error: {e}"), }; let mut vm = Vm::new(); - match vm.run(&module) { + match vm.run(&Arc::new(module)) { Ok(result) => format_value(&vm, result), Err(e) => format!("vm error: {e}"), } diff --git a/crates/oxide_vm/tests/call_spread_tests.rs b/crates/oxide_vm/tests/call_spread_tests.rs index 12c05534..6328f06f 100644 --- a/crates/oxide_vm/tests/call_spread_tests.rs +++ b/crates/oxide_vm/tests/call_spread_tests.rs @@ -1,6 +1,8 @@ //! 调用实参 spread 执行语义测试:`f(...args)`、`new F(...args)`、`super(...args)`。 //! 覆盖静态/混合实参顺序、迭代器协议、IteratorClose、native 目标、求值顺序。 +use std::sync::Arc; + use oxide_compiler::compiler::Compiler; use oxide_types::value::JsValue; use oxide_vm::vm::Vm; @@ -9,7 +11,7 @@ fn eval(vm: &mut Vm, source: &str) -> Result { let allocator = oxide_parser::Allocator::default(); let program = oxide_parser::parse(&allocator, source).map_err(|e| format!("Parse error: {:?}", e))?; let module = Compiler::new().compile(&program).map_err(|e| format!("Compile error: {}", e))?; - vm.run(&module) + vm.run(&Arc::new(module)) } fn to_str(vm: &Vm, val: JsValue) -> String { diff --git a/crates/oxide_vm/tests/class_tests.rs b/crates/oxide_vm/tests/class_tests.rs index 950a875c..a39b50f4 100644 --- a/crates/oxide_vm/tests/class_tests.rs +++ b/crates/oxide_vm/tests/class_tests.rs @@ -1,3 +1,5 @@ +use std::sync::Arc; + use oxide_compiler::compiler::Compiler; use oxide_types::value::JsValue; use oxide_vm::vm::Vm; @@ -6,7 +8,7 @@ fn eval(vm: &mut Vm, source: &str) -> Result { let allocator = oxide_parser::Allocator::default(); let program = oxide_parser::parse(&allocator, source).map_err(|e| format!("Parse error: {:?}", e))?; let module = Compiler::new().compile(&program).map_err(|e| format!("Compile error: {}", e))?; - vm.run(&module) + vm.run(&Arc::new(module)) } fn assert_num(value: JsValue, expected: f64) { diff --git a/crates/oxide_vm/tests/coercion_tests.rs b/crates/oxide_vm/tests/coercion_tests.rs index 0076dc1b..5f177bbd 100644 --- a/crates/oxide_vm/tests/coercion_tests.rs +++ b/crates/oxide_vm/tests/coercion_tests.rs @@ -1,3 +1,5 @@ +use std::sync::Arc; + use oxide_compiler::compiler::Compiler; use oxide_parser::Allocator; use oxide_runtime_api as coercion; @@ -15,7 +17,7 @@ fn eval(source: &str) -> String { Err(e) => return format!("compile error: {e}"), }; let mut vm = Vm::new(); - match vm.run(&module) { + match vm.run(&Arc::new(module)) { Ok(result) => format!("{result}"), Err(e) => format!("vm error: {e}"), } @@ -258,7 +260,7 @@ fn eval_ty(source: &str) -> Result<(Vm, JsValue), String> { let program = oxide_parser::parse(&allocator, source).map_err(|e| format!("Parse error: {:?}", e))?; let module = Compiler::new().compile(&program).map_err(|e| format!("Compile error: {}", e))?; let mut vm = Vm::new(); - let result = vm.run(&module)?; + let result = vm.run(&Arc::new(module))?; Ok((vm, result)) } diff --git a/crates/oxide_vm/tests/comparison_tests.rs b/crates/oxide_vm/tests/comparison_tests.rs index c7072ed1..acacf28d 100644 --- a/crates/oxide_vm/tests/comparison_tests.rs +++ b/crates/oxide_vm/tests/comparison_tests.rs @@ -1,3 +1,5 @@ +use std::sync::Arc; + use oxide_compiler::compiler::Compiler; use oxide_parser::Allocator; use oxide_vm::vm::Vm; @@ -13,7 +15,7 @@ fn eval(source: &str) -> String { Err(e) => return format!("compile error: {e}"), }; let mut vm = Vm::new(); - match vm.run(&module) { + match vm.run(&Arc::new(module)) { Ok(result) => format!("{result}"), Err(e) => format!("vm error: {e}"), } diff --git a/crates/oxide_vm/tests/compiler_alignment_binding_tests.rs b/crates/oxide_vm/tests/compiler_alignment_binding_tests.rs index 7d33fe09..3f9dfe2a 100644 --- a/crates/oxide_vm/tests/compiler_alignment_binding_tests.rs +++ b/crates/oxide_vm/tests/compiler_alignment_binding_tests.rs @@ -1,3 +1,5 @@ +use std::sync::Arc; + use oxide_compiler::compiler::Compiler; use oxide_parser::Allocator; use oxide_vm::vm::Vm; @@ -13,7 +15,7 @@ fn eval(source: &str) -> String { Err(e) => return format!("compile error: {e}"), }; let mut vm = Vm::new(); - match vm.run(&module) { + match vm.run(&Arc::new(module)) { Ok(result) => format!("{result}"), Err(e) => format!("vm error: {e}"), } diff --git a/crates/oxide_vm/tests/compiler_alignment_class_tests.rs b/crates/oxide_vm/tests/compiler_alignment_class_tests.rs index 5c22241c..4074121f 100644 --- a/crates/oxide_vm/tests/compiler_alignment_class_tests.rs +++ b/crates/oxide_vm/tests/compiler_alignment_class_tests.rs @@ -1,3 +1,5 @@ +use std::sync::Arc; + use oxide_compiler::compiler::Compiler; use oxide_parser::Allocator; use oxide_vm::vm::Vm; @@ -13,7 +15,7 @@ fn eval(source: &str) -> String { Err(e) => return format!("compile error: {e}"), }; let mut vm = Vm::new(); - match vm.run(&module) { + match vm.run(&Arc::new(module)) { Ok(result) => format!("{result}"), Err(e) => format!("vm error: {e}"), } diff --git a/crates/oxide_vm/tests/compiler_alignment_expr_tests.rs b/crates/oxide_vm/tests/compiler_alignment_expr_tests.rs index 6279ccea..cc2e4975 100644 --- a/crates/oxide_vm/tests/compiler_alignment_expr_tests.rs +++ b/crates/oxide_vm/tests/compiler_alignment_expr_tests.rs @@ -1,3 +1,5 @@ +use std::sync::Arc; + use oxide_compiler::compiler::Compiler; use oxide_parser::Allocator; use oxide_vm::vm::Vm; @@ -13,7 +15,7 @@ fn eval(source: &str) -> String { Err(e) => return format!("compile error: {e}"), }; let mut vm = Vm::new(); - match vm.run(&module) { + match vm.run(&Arc::new(module)) { Ok(result) => format!("{result}"), Err(e) => format!("vm error: {e}"), } diff --git a/crates/oxide_vm/tests/concat_n_tests.rs b/crates/oxide_vm/tests/concat_n_tests.rs index b12f8d1f..98946874 100644 --- a/crates/oxide_vm/tests/concat_n_tests.rs +++ b/crates/oxide_vm/tests/concat_n_tests.rs @@ -4,6 +4,8 @@ //! 对象 ToPrimitive 副作用顺序、Symbol 行为与二元 ADD 一致、f64 结合性(右括号不拆)、 //! 求值顺序、2 操作数与 3+ 操作数等价性、长链拼接正确性。 +use std::sync::Arc; + use oxide_compiler::compiler::Compiler; use oxide_types::value::JsValue; use oxide_vm::vm::Vm; @@ -12,7 +14,7 @@ fn eval(vm: &mut Vm, source: &str) -> Result { let allocator = oxide_parser::Allocator::default(); let program = oxide_parser::parse(&allocator, source).map_err(|e| format!("Parse error: {:?}", e))?; let module = Compiler::new().compile(&program).map_err(|e| format!("Compile error: {e}"))?; - vm.run(&module) + vm.run(&Arc::new(module)) } fn to_str(vm: &Vm, val: JsValue) -> String { diff --git a/crates/oxide_vm/tests/const_guard_tests.rs b/crates/oxide_vm/tests/const_guard_tests.rs index 2e13e5de..f1d6fa1b 100644 --- a/crates/oxide_vm/tests/const_guard_tests.rs +++ b/crates/oxide_vm/tests/const_guard_tests.rs @@ -4,6 +4,8 @@ //! 声明路径带 b=1 时,checkpoint/寄存器复用残留的陈旧值会误抛 "Assignment to constant variable"。 //! 寄存器分配复用寄存器后此问题必现——本测试锁死声明路径恒 b=0 的行为。 +use std::sync::Arc; + use oxide_compiler::compiler::Compiler; use oxide_parser::Allocator; use oxide_vm::vm::Vm; @@ -19,7 +21,7 @@ fn eval(source: &str) -> String { Err(e) => return format!("compile error: {e}"), }; let mut vm = Vm::new(); - match vm.run(&module) { + match vm.run(&Arc::new(module)) { Ok(result) => format!("{result}"), Err(e) => format!("vm error: {e}"), } diff --git a/crates/oxide_vm/tests/control_flow_tests.rs b/crates/oxide_vm/tests/control_flow_tests.rs index 841e1f95..59ebebe1 100644 --- a/crates/oxide_vm/tests/control_flow_tests.rs +++ b/crates/oxide_vm/tests/control_flow_tests.rs @@ -1,3 +1,5 @@ +use std::sync::Arc; + use oxide_compiler::compiler::Compiler; use oxide_parser::Allocator; use oxide_vm::vm::Vm; @@ -13,7 +15,7 @@ fn eval(source: &str) -> String { Err(e) => return format!("compile error: {e}"), }; let mut vm = Vm::new(); - match vm.run(&module) { + match vm.run(&Arc::new(module)) { Ok(result) => format!("{result}"), Err(e) => format!("vm error: {e}"), } diff --git a/crates/oxide_vm/tests/define_property_descriptor_tests.rs b/crates/oxide_vm/tests/define_property_descriptor_tests.rs index 5278b4de..79fbbeeb 100644 --- a/crates/oxide_vm/tests/define_property_descriptor_tests.rs +++ b/crates/oxide_vm/tests/define_property_descriptor_tests.rs @@ -1,3 +1,5 @@ +use std::sync::Arc; + use oxide_compiler::compiler::Compiler; use oxide_types::value::JsValue; use oxide_vm::vm::Vm; @@ -7,7 +9,7 @@ fn eval(source: &str) -> Result<(Vm, JsValue), String> { let program = oxide_parser::parse(&allocator, source).map_err(|e| format!("Parse error: {:?}", e))?; let module = Compiler::new().compile(&program).map_err(|e| format!("Compile error: {}", e))?; let mut vm = Vm::new(); - let result = vm.run(&module)?; + let result = vm.run(&Arc::new(module))?; Ok((vm, result)) } diff --git a/crates/oxide_vm/tests/destructuring_tests.rs b/crates/oxide_vm/tests/destructuring_tests.rs index 2d110d53..c1a6ec72 100644 --- a/crates/oxide_vm/tests/destructuring_tests.rs +++ b/crates/oxide_vm/tests/destructuring_tests.rs @@ -1,3 +1,5 @@ +use std::sync::Arc; + use oxide_compiler::compiler::Compiler; use oxide_types::value::JsValue; use oxide_vm::vm::Vm; @@ -6,7 +8,7 @@ fn eval(vm: &mut Vm, source: &str) -> Result { let allocator = oxide_parser::Allocator::default(); let program = oxide_parser::parse(&allocator, source).map_err(|e| format!("Parse error: {:?}", e))?; let module = Compiler::new().compile(&program).map_err(|e| format!("Compile error: {}", e))?; - vm.run(&module) + vm.run(&Arc::new(module)) } fn assert_num(value: JsValue, expected: f64) { diff --git a/crates/oxide_vm/tests/eval_script_global_tests.rs b/crates/oxide_vm/tests/eval_script_global_tests.rs index c77f6f4a..808ee9e4 100644 --- a/crates/oxide_vm/tests/eval_script_global_tests.rs +++ b/crates/oxide_vm/tests/eval_script_global_tests.rs @@ -1,6 +1,8 @@ //! eval 脚本 var/函数声明落全局对象的属性语义测试:configurable:true(区别于普通 //! 脚本顶层的 false)、可 delete、跨 eval 轮次经全局对象可见。 +use std::sync::Arc; + use oxide_compiler::compiler::Compiler; use oxide_types::value::JsValue; use oxide_vm::vm::Vm; @@ -10,7 +12,7 @@ fn eval(source: &str) -> Result { let program = oxide_parser::parse(&allocator, source).map_err(|e| format!("Parse error: {:?}", e))?; let module = Compiler::new().compile(&program).map_err(|e| format!("Compile error: {}", e))?; let mut vm = Vm::new(); - vm.run(&module) + vm.run(&Arc::new(module)) } fn eval_many(lines: &[&str]) -> Result { @@ -30,7 +32,7 @@ fn eval_str(source: &str) -> String { let program = oxide_parser::parse(&allocator, source).expect("parse"); let module = Compiler::new().compile(&program).expect("compile"); let mut vm = Vm::new(); - let result = vm.run(&module).expect("run"); + let result = vm.run(&Arc::new(module)).expect("run"); vm.lookup_str(result).unwrap_or_else(|| format!("{result}")) } diff --git a/crates/oxide_vm/tests/eval_tests.rs b/crates/oxide_vm/tests/eval_tests.rs index 97cd2ba7..cfb7277b 100644 --- a/crates/oxide_vm/tests/eval_tests.rs +++ b/crates/oxide_vm/tests/eval_tests.rs @@ -1,3 +1,5 @@ +use std::sync::Arc; + use oxide_compiler::compiler::Compiler; use oxide_types::object::JsObject; use oxide_types::value::JsValue; @@ -7,7 +9,7 @@ fn eval(vm: &mut Vm, source: &str) -> Result { let allocator = oxide_parser::Allocator::default(); let program = oxide_parser::parse(&allocator, source).map_err(|e| format!("Parse error: {:?}", e))?; let module = Compiler::new().compile(&program).map_err(|e| format!("Compile error: {}", e))?; - vm.run(&module) + vm.run(&Arc::new(module)) } /// 数值断言:整数运算保 int,容忍 int/double 两种表示。 diff --git a/crates/oxide_vm/tests/exception_channel_tests.rs b/crates/oxide_vm/tests/exception_channel_tests.rs index 9b42821f..621b17ee 100644 --- a/crates/oxide_vm/tests/exception_channel_tests.rs +++ b/crates/oxide_vm/tests/exception_channel_tests.rs @@ -2,6 +2,8 @@ //! 忽略路径(IteratorClose 的 return() 抛错被丢弃)不得把值残留进槽,unwind 进入 //! finally/catch 接住异常后槽作废,否则后续 take 会误取残留值污染拒绝原因。 +use std::sync::Arc; + use oxide_compiler::compiler::Compiler; use oxide_parser::Allocator; use oxide_vm::promise::promise_settled_value; @@ -19,7 +21,7 @@ fn eval(source: &str) -> String { Err(e) => return format!("compile error: {e}"), }; let mut vm = Vm::new(); - match vm.run(&module) { + match vm.run(&Arc::new(module)) { Ok(result) => format_value(&vm, result), Err(e) => format!("vm error: {e}"), } diff --git a/crates/oxide_vm/tests/for_in_null_undefined_tests.rs b/crates/oxide_vm/tests/for_in_null_undefined_tests.rs index 932dcbcd..2e8085bf 100644 --- a/crates/oxide_vm/tests/for_in_null_undefined_tests.rs +++ b/crates/oxide_vm/tests/for_in_null_undefined_tests.rs @@ -1,3 +1,5 @@ +use std::sync::Arc; + use oxide_compiler::compiler::Compiler; use oxide_parser::Allocator; use oxide_vm::vm::Vm; @@ -13,7 +15,7 @@ fn eval(source: &str) -> String { Err(e) => return format!("compile error: {e}"), }; let mut vm = Vm::new(); - match vm.run(&module) { + match vm.run(&Arc::new(module)) { Ok(result) => format!("{result}"), Err(e) => format!("vm error: {e}"), } diff --git a/crates/oxide_vm/tests/for_in_ordering_tests.rs b/crates/oxide_vm/tests/for_in_ordering_tests.rs index 1c7e1037..6de7896b 100644 --- a/crates/oxide_vm/tests/for_in_ordering_tests.rs +++ b/crates/oxide_vm/tests/for_in_ordering_tests.rs @@ -1,3 +1,5 @@ +use std::sync::Arc; + use oxide_compiler::compiler::Compiler; use oxide_parser::Allocator; use oxide_vm::vm::Vm; @@ -13,7 +15,7 @@ fn eval(source: &str) -> String { Err(e) => return format!("compile error: {e}"), }; let mut vm = Vm::new(); - match vm.run(&module) { + match vm.run(&Arc::new(module)) { Ok(result) => format!("{result}"), Err(e) => format!("vm error: {e}"), } diff --git a/crates/oxide_vm/tests/for_of_abrupt_completion_tests.rs b/crates/oxide_vm/tests/for_of_abrupt_completion_tests.rs index 2cf3ab98..c9d905d8 100644 --- a/crates/oxide_vm/tests/for_of_abrupt_completion_tests.rs +++ b/crates/oxide_vm/tests/for_of_abrupt_completion_tests.rs @@ -1,3 +1,5 @@ +use std::sync::Arc; + use oxide_compiler::compiler::Compiler; use oxide_parser::Allocator; use oxide_vm::vm::Vm; @@ -13,7 +15,7 @@ fn eval(source: &str) -> String { Err(e) => return format!("compile error: {e}"), }; let mut vm = Vm::new(); - match vm.run(&module) { + match vm.run(&Arc::new(module)) { Ok(result) => format!("{result}"), Err(e) => format!("vm error: {e}"), } diff --git a/crates/oxide_vm/tests/for_of_builtin_iter_tests.rs b/crates/oxide_vm/tests/for_of_builtin_iter_tests.rs index b9a35ea5..542a712e 100644 --- a/crates/oxide_vm/tests/for_of_builtin_iter_tests.rs +++ b/crates/oxide_vm/tests/for_of_builtin_iter_tests.rs @@ -1,3 +1,5 @@ +use std::sync::Arc; + use oxide_compiler::compiler::Compiler; use oxide_parser::Allocator; use oxide_vm::vm::Vm; @@ -13,7 +15,7 @@ fn eval(source: &str) -> String { Err(e) => return format!("compile error: {e}"), }; let mut vm = Vm::new(); - match vm.run(&module) { + match vm.run(&Arc::new(module)) { Ok(result) => format!("{result}"), Err(e) => format!("vm error: {e}"), } diff --git a/crates/oxide_vm/tests/function_length_tests.rs b/crates/oxide_vm/tests/function_length_tests.rs index 669ae9f1..4684575e 100644 --- a/crates/oxide_vm/tests/function_length_tests.rs +++ b/crates/oxide_vm/tests/function_length_tests.rs @@ -1,6 +1,8 @@ //! 函数 length/name 属性集成测试:普通字节码函数、箭头函数、bind 包装器、 //! getter/setter 前缀。每个用例独立编译执行,断言顶层表达式结果。 +use std::sync::Arc; + use oxide_bytecode::module::CompiledModule; use oxide_compiler::compiler::Compiler; use oxide_parser::Allocator; @@ -10,11 +12,11 @@ use oxide_vm::vm::Vm; fn eval(source: &str) -> JsValue { let allocator = Allocator::default(); let program = oxide_parser::parse(&allocator, source).expect("parse failed"); - let module = Compiler::new().compile(&program).expect("compile failed"); + let module = Arc::new(Compiler::new().compile(&program).expect("compile failed")); run(&module) } -fn run(module: &CompiledModule) -> JsValue { +fn run(module: &Arc) -> JsValue { let mut vm = Vm::new(); vm.run(module).expect("vm run failed") } @@ -22,7 +24,7 @@ fn run(module: &CompiledModule) -> JsValue { fn eval_str(source: &str) -> String { let allocator = Allocator::default(); let program = oxide_parser::parse(&allocator, source).expect("parse failed"); - let module = Compiler::new().compile(&program).expect("compile failed"); + let module = Arc::new(Compiler::new().compile(&program).expect("compile failed")); let mut vm = Vm::new(); let v = vm.run(&module).expect("vm run failed"); // 字符串结果须在同一 VM 上读:perm 串指向 VM 私有内核,VM drop 后指针悬垂。 diff --git a/crates/oxide_vm/tests/function_tests.rs b/crates/oxide_vm/tests/function_tests.rs index ad9a3304..3ef96797 100644 --- a/crates/oxide_vm/tests/function_tests.rs +++ b/crates/oxide_vm/tests/function_tests.rs @@ -1,3 +1,5 @@ +use std::sync::Arc; + use oxide_compiler::compiler::Compiler; use oxide_types::value::JsValue; use oxide_vm::vm::Vm; @@ -6,7 +8,7 @@ fn eval(vm: &mut Vm, source: &str) -> Result { let allocator = oxide_parser::Allocator::default(); let program = oxide_parser::parse(&allocator, source).map_err(|e| format!("Parse error: {:?}", e))?; let module = Compiler::new().compile(&program).map_err(|e| format!("Compile error: {}", e))?; - vm.run(&module) + vm.run(&Arc::new(module)) } /// 数值断言:整数运算保 int,容忍 int/double 两种表示。 diff --git a/crates/oxide_vm/tests/gc_runtime_tests.rs b/crates/oxide_vm/tests/gc_runtime_tests.rs index f4abffcb..2b30a502 100644 --- a/crates/oxide_vm/tests/gc_runtime_tests.rs +++ b/crates/oxide_vm/tests/gc_runtime_tests.rs @@ -1,3 +1,5 @@ +use std::sync::Arc; + use oxide_compiler::compiler::Compiler; use oxide_kernel::kernel::{KernelConfig, KernelCore}; use oxide_parser::Allocator; @@ -21,7 +23,7 @@ fn vm_with_threshold(bytes: usize) -> Vm { fn long_string_loop_triggers_runtime_gc_and_bounds_session() { let mut vm = vm_with_threshold(4096); let module = compile("var s; for (var i = 0; i < 500000; i++) { s = 'str' + i; } s.length"); - let result = vm.run(&module).expect("run"); + let result = vm.run(&Arc::new(module)).expect("run"); assert_eq!(format!("{}", result), "9"); assert!(vm.session_gc_stats().total_collections > 0, "执行期应触发字符串 GC"); @@ -38,10 +40,10 @@ fn long_string_loop_triggers_runtime_gc_and_bounds_session() { fn session_string_survives_across_runs_with_runtime_gc() { let mut vm = vm_with_threshold(4096); let first = compile("globalThis.kept = 'he' + 'llo'; 0"); - vm.run(&first).expect("run1"); + vm.run(&Arc::new(first)).expect("run1"); let second = compile("var s; for (var i = 0; i < 500000; i++) { s = 'y' + i; } globalThis.kept"); - let result = vm.run(&second).expect("run2"); + let result = vm.run(&Arc::new(second)).expect("run2"); let text = vm.lookup_str(result).expect("kept 应为字符串").to_string(); assert_eq!(text, "hello"); @@ -53,11 +55,11 @@ fn session_string_survives_across_runs_with_runtime_gc() { fn reset_preserves_session_strings_after_runtime_gc() { let mut vm = vm_with_threshold(4096); let first = compile("globalThis.kept = 'x' + 'y'; 0"); - vm.run(&first).expect("run1"); + vm.run(&Arc::new(first)).expect("run1"); vm.reset(); let second = compile("globalThis.kept"); - let result = vm.run(&second).expect("run2"); + let result = vm.run(&Arc::new(second)).expect("run2"); let text = vm.lookup_str(result).expect("kept 应为字符串").to_string(); assert_eq!(text, "xy"); } @@ -69,12 +71,12 @@ fn strings_only_then_reset_keeps_global_subtree_strings() { let mut vm = vm_with_threshold(4096); let first = compile("globalThis.kept = { s: 'he' + 'llo' }; var t; for (var i = 0; i < 500000; i++) { t = 'x' + i; } 0"); - vm.run(&first).expect("run1"); + vm.run(&Arc::new(first)).expect("run1"); assert!(vm.session_gc_stats().total_collections > 0, "run1 应触发执行期字符串 GC"); vm.reset(); let second = compile("globalThis.kept.s"); - let result = vm.run(&second).expect("run2"); + let result = vm.run(&Arc::new(second)).expect("run2"); let text = vm.lookup_str(result).expect("kept.s 应为字符串").to_string(); assert_eq!(text, "hello"); } @@ -89,7 +91,7 @@ fn regexp_exec_strings_survive_runtime_gc() { "var text = 'a'.repeat(500) + 'b'.repeat(500); var m = /(a+)(b+)/.exec(text); \ m[0] + '|' + m[1] + '|' + m[2]", ); - let result = vm.run(&module).expect("run"); + let result = vm.run(&Arc::new(module)).expect("run"); let text = vm.lookup_str(result).expect("exec 结果应为字符串").to_string(); let expected = format!("{}|{}|{}", "a".repeat(500) + &"b".repeat(500), "a".repeat(500), "b".repeat(500)); assert_eq!(text, expected); @@ -105,7 +107,7 @@ fn temporal_zoned_date_time_strings_survive_runtime_gc() { "var g = {}; for (var i = 0; i < 20; i++) { g['k' + i] = 'v'.repeat(64); } \ var z = new Temporal.ZonedDateTime(0n, 'UTC'); z.timeZoneId + '|' + z.calendarId", ); - let result = vm.run(&module).expect("run"); + let result = vm.run(&Arc::new(module)).expect("run"); let text = vm.lookup_str(result).expect("ZDT 槽应为字符串").to_string(); assert_eq!(text, "UTC|iso8601"); assert!(vm.session_gc_stats().total_collections > 0, "执行期应触发字符串 GC"); @@ -120,7 +122,7 @@ fn replace_replacer_args_survive_runtime_gc() { "var g = {}; for (var i = 0; i < 20; i++) { g['k' + i] = 'v'.repeat(64); } \ 'a-b-c'.replace(/(a)-(b)-(c)/g, function(m, p1, p2, p3, pos, s) { return p1 + p2 + p3; })", ); - let result = vm.run(&module).expect("run"); + let result = vm.run(&Arc::new(module)).expect("run"); let text = vm.lookup_str(result).expect("replace 结果应为字符串").to_string(); assert_eq!(text, "abc"); assert!(vm.session_gc_stats().total_collections > 0, "执行期应触发字符串 GC"); @@ -141,7 +143,7 @@ fn map_callback_caller_reg_strings_survive_nested_dispatch() { return held; } \ var out = middle('mid' + 'str'); out", ); - let result = vm.run(&module).expect("run"); + let result = vm.run(&Arc::new(module)).expect("run"); let text = vm.lookup_str(result).expect("held 应为字符串").to_string(); assert_eq!(text, "midstr"); assert!(vm.session_gc_stats().total_collections > 0, "执行期应触发字符串 GC"); @@ -159,7 +161,7 @@ fn replace_replacer_caller_reg_strings_survive_nested_dispatch() { return held + '|' + out; } \ var out = middle('repl' + 'acer'); out", ); - let result = vm.run(&module).expect("run"); + let result = vm.run(&Arc::new(module)).expect("run"); let text = vm.lookup_str(result).expect("结果应为字符串").to_string(); assert_eq!(text, "replacer|a[-]b[-]c"); assert!(vm.session_gc_stats().total_collections > 0, "执行期应触发字符串 GC"); @@ -178,7 +180,7 @@ fn generator_next_loop_caller_reg_strings_survive_nested_dispatch() { return held + '|' + acc; } \ var out = middle('gen' + 'str'); out", ); - let result = vm.run(&module).expect("run"); + let result = vm.run(&Arc::new(module)).expect("run"); let text = vm.lookup_str(result).expect("结果应为字符串").to_string(); assert_eq!(text, "genstr|10"); assert!(vm.session_gc_stats().total_collections > 0, "执行期应触发字符串 GC"); @@ -198,7 +200,7 @@ fn nested_inline_callbacks_caller_reg_strings_survive_runtime_gc() { return held + '|' + r.join(','); } \ var out = middle('nest' + 'ed'); out", ); - let result = vm.run(&module).expect("run"); + let result = vm.run(&Arc::new(module)).expect("run"); let text = vm.lookup_str(result).expect("结果应为字符串").to_string(); assert_eq!(text, "nested|31,32"); assert!(vm.session_gc_stats().total_collections > 0, "执行期应触发字符串 GC"); @@ -210,14 +212,14 @@ fn nested_inline_callbacks_caller_reg_strings_survive_runtime_gc() { fn full_reset_clears_session_after_runtime_gc() { let mut vm = vm_with_threshold(4096); let first = compile("var s; for (var i = 0; i < 200000; i++) { s = 'a' + i; } s.length"); - vm.run(&first).expect("run1"); + vm.run(&Arc::new(first)).expect("run1"); assert!(vm.session_gc_stats().total_collections > 0, "run1 应触发执行期字符串 GC"); vm.full_reset(); assert_eq!(vm.session_bytes_allocated(), 0, "full_reset 后 session 字节应为 0"); let second = compile("'ok' + '!'"); - let result = vm.run(&second).expect("run2"); + let result = vm.run(&Arc::new(second)).expect("run2"); let text = vm.lookup_str(result).expect("拼接结果应为字符串").to_string(); assert_eq!(text, "ok!"); } @@ -233,13 +235,13 @@ fn reset_sweep_preserves_global_function_object() { for (var i = 0; i < 2000; i++) { var t = 'p' + i + 'q' + i; } \ typeof globalThis.fn === 'function'", ); - let result = vm.run(&first).expect("run1"); + let result = vm.run(&Arc::new(first)).expect("run1"); assert!(result.is_bool() && result.as_bool()); assert!(vm.session_gc_stats().total_collections > 0, "低阈值应触发执行期收集"); vm.reset(); let second = compile("typeof globalThis.fn === 'function'"); - let result = vm.run(&second).expect("run2"); + let result = vm.run(&Arc::new(second)).expect("run2"); assert!(result.is_bool() && result.as_bool()); } @@ -249,13 +251,13 @@ fn reset_sweep_preserves_global_function_object() { fn closure_cells_freed_by_full_reset_without_double_free() { let mut vm = vm_with_threshold(1); let first = compile("var x = 1; function f() { return x; } globalThis.f = f; f()"); - let result = vm.run(&first).expect("run1"); + let result = vm.run(&Arc::new(first)).expect("run1"); assert_eq!(format!("{}", result), "1"); vm.full_reset(); let second = compile("'ok' + '!'"); - let result = vm.run(&second).expect("run2"); + let result = vm.run(&Arc::new(second)).expect("run2"); let text = vm.lookup_str(result).expect("拼接结果应为字符串").to_string(); assert_eq!(text, "ok!"); } @@ -274,12 +276,12 @@ fn dead_closure_upvalues_freed_by_sweep_without_double_free() { globalThis.dead = function() { return a + b + c; }; \ globalThis.live = function() { return a + b + c; }; globalThis.live()", ); - let result = vm.run(&first).expect("run1"); + let result = vm.run(&Arc::new(first)).expect("run1"); assert_eq!(format!("{}", result), "6"); // run2:撤销死闭包的根引用(不可达)。 let second = compile("globalThis.dead = undefined; 0"); - vm.run(&second).expect("run2"); + vm.run(&Arc::new(second)).expect("run2"); // 完整收集:死闭包走死分支(释放 upvalue 列表),存活闭包走存活分支 // (克隆与原件共享 Box,不在死分支释放)。 @@ -289,7 +291,7 @@ fn dead_closure_upvalues_freed_by_sweep_without_double_free() { // 跨 run 存活核(只读属性;跨 run 调用受 sub_module_index 缺口限制): // sweep 后存活闭包克隆仍挂在 global 上。 let third = compile("typeof globalThis.live === 'function'"); - let result = vm.run(&third).expect("run3"); + let result = vm.run(&Arc::new(third)).expect("run3"); assert!(result.is_bool() && result.as_bool()); // 收尾统一 upvalue 释放与死分支不双放(字段已置空、死对象已出表)。 @@ -300,7 +302,7 @@ fn dead_closure_upvalues_freed_by_sweep_without_double_free() { "var x = 10; var y = 20; var z = 30; \ globalThis.f = function() { return x + y + z; }; globalThis.f()", ); - let result = vm.run(&fourth).expect("run4"); + let result = vm.run(&Arc::new(fourth)).expect("run4"); assert_eq!(format!("{}", result), "60"); // 字节账目 A/B 差分样本:两条同构 arrow 仅 upvalue 数不同(3 vs 0), @@ -310,8 +312,9 @@ fn dead_closure_upvalues_freed_by_sweep_without_double_free() { // 死分支不释放 upvalue 列表(泄漏)时差分为 0,本断言转红。 let collect_freed = |src: &str| -> u64 { let mut v = vm_with_threshold(4096); - v.run(&compile(src)).expect("run create"); - v.run(&compile("globalThis.arrow = undefined; 0")).expect("run unroot"); + v.run(&Arc::new(compile(src))).expect("run create"); + v.run(&Arc::new(compile("globalThis.arrow = undefined; 0"))) + .expect("run unroot"); v.collect_session_gc(); let stats = v.session_gc_stats(); assert!(stats.last_collection_objects_dead >= 1, "arrow 闭包应经 sweep 死分支"); diff --git a/crates/oxide_vm/tests/generator_gc_tests.rs b/crates/oxide_vm/tests/generator_gc_tests.rs index 6d8365aa..401a0bfd 100644 --- a/crates/oxide_vm/tests/generator_gc_tests.rs +++ b/crates/oxide_vm/tests/generator_gc_tests.rs @@ -3,6 +3,8 @@ //! sweep 变体与闭包捕获变体见 `vm_support.rs` 内部测试(需 crate 内 `resume_generator` //! 在模块表未重建时恢复执行,integration 层无法触达)。 +use std::sync::Arc; + use oxide_compiler::compiler::Compiler; use oxide_parser::Allocator; use oxide_vm::vm::Vm; @@ -18,9 +20,9 @@ fn compile(source: &str) -> oxide_bytecode::module::CompiledModule { #[test] fn generator_promoted_to_global_survives_full_reset_cleanly() { let mut vm = Vm::new(); - vm.run(&compile( + vm.run(&Arc::new(compile( "function* g(){ yield 1; yield 2; } globalThis.it = g(); globalThis.it.next(); 0", - )) + ))) .expect("run1"); assert!(vm.session_object_count() > 0, "生成器挂 global 应被 promote 进 session"); @@ -29,12 +31,12 @@ fn generator_promoted_to_global_survives_full_reset_cleanly() { vm.full_reset(); assert_eq!(vm.session_object_count(), 0, "full_reset 应清空 session 对象"); - let result = vm.run(&compile("typeof it")).expect("run2"); + let result = vm.run(&Arc::new(compile("typeof it"))).expect("run2"); let text = vm.lookup_str(result).expect("typeof 应返回字符串").to_string(); assert_eq!(text, "undefined"); // 新会话可正常创建并推进生成器。 let ok = vm - .run(&compile("function* h(){ yield 9; } var it2 = h(); it2.next().value")) + .run(&Arc::new(compile("function* h(){ yield 9; } var it2 = h(); it2.next().value"))) .expect("run3"); assert_eq!(format!("{ok}"), "9"); } diff --git a/crates/oxide_vm/tests/generator_yield_star_tests.rs b/crates/oxide_vm/tests/generator_yield_star_tests.rs index 643b715f..93ff1e85 100644 --- a/crates/oxide_vm/tests/generator_yield_star_tests.rs +++ b/crates/oxide_vm/tests/generator_yield_star_tests.rs @@ -1,6 +1,8 @@ //! `yield*` 委托语法运行时测试:委托数组/字符串/生成器,next/return/throw 转发, //! 委托完成值传递与空委托场景。 +use std::sync::Arc; + use oxide_compiler::compiler::Compiler; use oxide_parser::Allocator; use oxide_vm::vm::Vm; @@ -16,7 +18,7 @@ fn eval(source: &str) -> String { Err(e) => return format!("compile error: {e}"), }; let mut vm = Vm::new(); - match vm.run(&module) { + match vm.run(&Arc::new(module)) { Ok(result) => { if result.is_string() { vm.lookup_str(result).unwrap_or_default() diff --git a/crates/oxide_vm/tests/global_builtin_constant_descriptor_tests.rs b/crates/oxide_vm/tests/global_builtin_constant_descriptor_tests.rs index 367ec4de..11ac3968 100644 --- a/crates/oxide_vm/tests/global_builtin_constant_descriptor_tests.rs +++ b/crates/oxide_vm/tests/global_builtin_constant_descriptor_tests.rs @@ -5,6 +5,8 @@ //! 保持(writable 不翻位、NaN/Infinity 不被抹成 undefined)、var 初始化声明的值 //! 落槽、枚举面不泄漏、任务只读拦截与 strict TypeError、eval 路径、for-in 枚举面。 +use std::sync::Arc; + use oxide_compiler::compiler::Compiler; use oxide_parser::Allocator; use oxide_vm::vm::Vm; @@ -17,13 +19,13 @@ fn compile(source: &str) -> oxide_bytecode::module::CompiledModule { fn run_truthy(source: &str) { let mut vm = Vm::new(); - let result = vm.run(&compile(source)).expect("run"); + let result = vm.run(&Arc::new(compile(source))).expect("run"); assert!(result.is_bool() && result.as_bool(), "expected true, got: {result:?}\nsource: {source}"); } fn run_string(source: &str) -> String { let mut vm = Vm::new(); - let result = vm.run(&compile(source)).expect("run"); + let result = vm.run(&Arc::new(compile(source))).expect("run"); if result.is_undefined() { return "undefined".to_string(); } @@ -33,7 +35,7 @@ fn run_string(source: &str) -> String { /// 求值并返回完成值字符串;运行期异常返回错误文本(供 TypeError 断言)。 fn eval(source: &str) -> String { let mut vm = Vm::new(); - match vm.run(&compile(source)) { + match vm.run(&Arc::new(compile(source))) { Ok(result) => vm.lookup_str(result).unwrap_or_default(), Err(e) => e, } diff --git a/crates/oxide_vm/tests/global_prop_desc_tests.rs b/crates/oxide_vm/tests/global_prop_desc_tests.rs index fe686b73..baf7f65c 100644 --- a/crates/oxide_vm/tests/global_prop_desc_tests.rs +++ b/crates/oxide_vm/tests/global_prop_desc_tests.rs @@ -2,6 +2,8 @@ //! enumerable=false(不泄漏进 Object.keys(globalThis) / for-in), //! 全局 NaN/undefined/Infinity 三常量不可写不可枚举可配置。 +use std::sync::Arc; + use oxide_compiler::compiler::Compiler; use oxide_parser::Allocator; use oxide_vm::vm::Vm; @@ -11,7 +13,7 @@ fn eval_truthy(source: &str) { let program = oxide_parser::parse(&allocator, source).expect("parse"); let module = Compiler::new().compile(&program).expect("compile"); let mut vm = Vm::new(); - let result = vm.run(&module).expect("run"); + let result = vm.run(&Arc::new(module)).expect("run"); assert!(result.is_bool() && result.as_bool(), "expected true, got: {result:?}\nsource: {source}"); } diff --git a/crates/oxide_vm/tests/global_var_binding_tests.rs b/crates/oxide_vm/tests/global_var_binding_tests.rs index 89f9a13d..a577acc2 100644 --- a/crates/oxide_vm/tests/global_var_binding_tests.rs +++ b/crates/oxide_vm/tests/global_var_binding_tests.rs @@ -1,5 +1,7 @@ //! 脚本顶层 var/function 声明落 globalThis 的运行时行为测试。 +use std::sync::Arc; + use oxide_compiler::compiler::Compiler; use oxide_parser::Allocator; use oxide_vm::vm::Vm; @@ -9,7 +11,7 @@ fn eval_truthy(source: &str) { let program = oxide_parser::parse(&allocator, source).expect("parse"); let module = Compiler::new().compile(&program).expect("compile"); let mut vm = Vm::new(); - let result = vm.run(&module).expect("run"); + let result = vm.run(&Arc::new(module)).expect("run"); assert!(result.is_bool() && result.as_bool(), "expected true, got: {result:?}\nsource: {source}"); } @@ -18,7 +20,7 @@ fn eval_string(source: &str) -> String { let program = oxide_parser::parse(&allocator, source).expect("parse"); let module = Compiler::new().compile(&program).expect("compile"); let mut vm = Vm::new(); - let result = vm.run(&module).expect("run"); + let result = vm.run(&Arc::new(module)).expect("run"); vm.lookup_str(result).unwrap_or_default() } @@ -31,9 +33,9 @@ fn compile(source: &str) -> oxide_bytecode::module::CompiledModule { /// 两阶段执行:phase1 → `reset()`(轻量重置,epoch 清空、session 保留)→ phase2。 fn eval_two_phases(phase1: &str, phase2: &str) -> bool { let mut vm = Vm::new(); - vm.run(&compile(phase1)).expect("run1"); + vm.run(&Arc::new(compile(phase1))).expect("run1"); vm.reset(); - let result = vm.run(&compile(phase2)).expect("run2"); + let result = vm.run(&Arc::new(compile(phase2))).expect("run2"); result.is_bool() && result.as_bool() } diff --git a/crates/oxide_vm/tests/ic_polymorphic_tests.rs b/crates/oxide_vm/tests/ic_polymorphic_tests.rs index c398b4aa..5a7ef682 100644 --- a/crates/oxide_vm/tests/ic_polymorphic_tests.rs +++ b/crates/oxide_vm/tests/ic_polymorphic_tests.rs @@ -5,6 +5,8 @@ //! 覆盖的 shape 只产生"每 shape 一次"的学习 miss,超出槽容量的轮换则 //! 每次访问都 miss(FIFO 逐访问滚动)。 +use std::sync::Arc; + use oxide_compiler::compiler::Compiler; use oxide_parser::Allocator; use oxide_vm::vm::Vm; @@ -15,7 +17,7 @@ fn run_once(source: &str) -> (String, u64, u64) { let program = oxide_parser::parse(&allocator, source).expect("parse"); let module = Compiler::new().compile(&program).expect("compile"); let mut vm = Vm::new(); - let r = vm.run(&module).expect("run").to_string(); + let r = vm.run(&Arc::new(module)).expect("run").to_string(); (r, vm.ic_hit_count(), vm.ic_miss_count()) } @@ -143,7 +145,7 @@ fn rerun_clears_polymorphic_slots() { .expect("parse"); let module = Compiler::new().compile(&program).expect("compile"); let mut vm = Vm::new(); - vm.run(&module).expect("run1"); + vm.run(&Arc::new(module)).expect("run1"); let learned = vm.ic_miss_count(); // run() 每次冷启动,此处直接验证 rerun 的可重入性:清除后仍能正常执行。 assert_eq!(format!("{}", vm.rerun().expect("rerun")), "1500"); diff --git a/crates/oxide_vm/tests/implicit_global_write_tests.rs b/crates/oxide_vm/tests/implicit_global_write_tests.rs index 11831b2b..fd01e5f5 100644 --- a/crates/oxide_vm/tests/implicit_global_write_tests.rs +++ b/crates/oxide_vm/tests/implicit_global_write_tests.rs @@ -3,6 +3,8 @@ //! 覆盖脚本顶层、函数体(全局对象经 session 解析,不依赖 this)、解构目标、 //! 更新式/逻辑赋值、for-in/for-of 左侧与不可扩展全局对象分支。 +use std::sync::Arc; + use oxide_compiler::compiler::Compiler; use oxide_types::value::JsValue; use oxide_vm::vm::Vm; @@ -12,7 +14,7 @@ fn eval(source: &str) -> Result { let program = oxide_parser::parse(&allocator, source).map_err(|e| format!("Parse error: {:?}", e))?; let module = Compiler::new().compile(&program).map_err(|e| format!("Compile error: {}", e))?; let mut vm = Vm::new(); - vm.run(&module) + vm.run(&Arc::new(module)) } fn eval_many(lines: &[&str]) -> Result { @@ -32,7 +34,7 @@ fn eval_str(source: &str) -> String { let program = oxide_parser::parse(&allocator, source).expect("parse"); let module = Compiler::new().compile(&program).expect("compile"); let mut vm = Vm::new(); - let result = vm.run(&module).expect("run"); + let result = vm.run(&Arc::new(module)).expect("run"); vm.lookup_str(result).unwrap_or_else(|| format!("{result}")) } diff --git a/crates/oxide_vm/tests/inline_dispatch_scoping_tests.rs b/crates/oxide_vm/tests/inline_dispatch_scoping_tests.rs index 742aa8a0..80782bc2 100644 --- a/crates/oxide_vm/tests/inline_dispatch_scoping_tests.rs +++ b/crates/oxide_vm/tests/inline_dispatch_scoping_tests.rs @@ -8,6 +8,8 @@ //! 覆盖生成器体内 C 侧路径触发的构造后 throw 与取值两种形态;帧边界 //! (字节码 GET_PROP 压 getter 帧)形态与循环失控形态(test262 族)另行回测。 +use std::sync::Arc; + use oxide_compiler::compiler::Compiler; use oxide_vm::vm::Vm; @@ -16,7 +18,7 @@ fn eval_str(source: &str) -> String { let program = oxide_parser::parse(&allocator, source).expect("parse"); let module = Compiler::new().compile(&program).expect("compile"); let mut vm = Vm::new(); - let result = vm.run(&module).expect("run"); + let result = vm.run(&Arc::new(module)).expect("run"); vm.lookup_str(result).unwrap_or_else(|| format!("{result}")) } diff --git a/crates/oxide_vm/tests/json_tests.rs b/crates/oxide_vm/tests/json_tests.rs index 05d3ef4b..21d8ff6f 100644 --- a/crates/oxide_vm/tests/json_tests.rs +++ b/crates/oxide_vm/tests/json_tests.rs @@ -1,3 +1,5 @@ +use std::sync::Arc; + use oxide_compiler::compiler::Compiler; use oxide_types::value::JsValue; use oxide_vm::vm::Vm; @@ -6,7 +8,7 @@ fn eval(vm: &mut Vm, source: &str) -> Result { let allocator = oxide_parser::Allocator::default(); let program = oxide_parser::parse(&allocator, source).map_err(|e| format!("Parse error: {:?}", e))?; let module = Compiler::new().compile(&program).map_err(|e| format!("Compile error: {}", e))?; - vm.run(&module) + vm.run(&Arc::new(module)) } fn string_value(vm: &Vm, val: JsValue) -> String { diff --git a/crates/oxide_vm/tests/logical_tests.rs b/crates/oxide_vm/tests/logical_tests.rs index f272fa84..9565e238 100644 --- a/crates/oxide_vm/tests/logical_tests.rs +++ b/crates/oxide_vm/tests/logical_tests.rs @@ -1,3 +1,5 @@ +use std::sync::Arc; + use oxide_compiler::compiler::Compiler; use oxide_parser::Allocator; use oxide_vm::vm::Vm; @@ -13,7 +15,7 @@ fn eval(source: &str) -> String { Err(e) => return format!("compile error: {e}"), }; let mut vm = Vm::new(); - match vm.run(&module) { + match vm.run(&Arc::new(module)) { Ok(result) => format!("{result}"), Err(e) => format!("vm error: {e}"), } diff --git a/crates/oxide_vm/tests/loop_closure_binding_tests.rs b/crates/oxide_vm/tests/loop_closure_binding_tests.rs index 25280bcb..68b9a4d2 100644 --- a/crates/oxide_vm/tests/loop_closure_binding_tests.rs +++ b/crates/oxide_vm/tests/loop_closure_binding_tests.rs @@ -1,6 +1,8 @@ //! 循环每迭代绑定(CreatePerIterationEnvironment):for/for-of/for-in 的 let/const //! 闭包捕获各自迭代快照。对应 PLAN 06-01(正确性报告 P1/P2)。 +use std::sync::Arc; + use oxide_compiler::compiler::Compiler; use oxide_types::value::JsValue; use oxide_vm::vm::Vm; @@ -10,7 +12,7 @@ fn eval(source: &str) -> Result<(Vm, JsValue), String> { let program = oxide_parser::parse(&allocator, source).map_err(|e| format!("Parse error: {:?}", e))?; let module = Compiler::new().compile(&program).map_err(|e| format!("Compile error: {}", e))?; let mut vm = Vm::new(); - let result = vm.run(&module)?; + let result = vm.run(&Arc::new(module))?; Ok((vm, result)) } diff --git a/crates/oxide_vm/tests/member_write_ic_tests.rs b/crates/oxide_vm/tests/member_write_ic_tests.rs index 391613ba..3f10b7ba 100644 --- a/crates/oxide_vm/tests/member_write_ic_tests.rs +++ b/crates/oxide_vm/tests/member_write_ic_tests.rs @@ -6,6 +6,8 @@ //! //! 计数断言基于单次 run 内 miss/hit 对比(run() 每次冷启动,IC 学习不跨 run)。 +use std::sync::Arc; + use oxide_compiler::compiler::Compiler; use oxide_parser::Allocator; use oxide_vm::vm::Vm; @@ -16,7 +18,7 @@ fn run_once(source: &str) -> (String, u64, u64) { let program = oxide_parser::parse(&allocator, source).expect("parse"); let module = Compiler::new().compile(&program).expect("compile"); let mut vm = Vm::new(); - let result = vm.run(&module).expect("run"); + let result = vm.run(&Arc::new(module)).expect("run"); // 字符串结果经 lookup_str 提取内容(JsValue Display 只打印 {string})。 let r = vm.lookup_str(result).unwrap_or_else(|| format!("{result}")); (r, vm.ic_hit_count(), vm.ic_miss_count()) @@ -184,7 +186,7 @@ fn member_write_counts_in_ic_hit_rate() { .expect("parse"); let module = Compiler::new().compile(&program).expect("compile"); let mut vm = Vm::new(); - let result = vm.run(&module).expect("run"); + let result = vm.run(&Arc::new(module)).expect("run"); let r = vm.lookup_str(result).unwrap_or_else(|| format!("{result}")); assert_eq!(r, "1000"); // 循环写侧 1000 命中 + 末尾 IC_GET 1 miss → 命中率 ~0.999(写侧计入后趋近真实)。 diff --git a/crates/oxide_vm/tests/new_target_tests.rs b/crates/oxide_vm/tests/new_target_tests.rs index 198cdaaf..3aa88ad8 100644 --- a/crates/oxide_vm/tests/new_target_tests.rs +++ b/crates/oxide_vm/tests/new_target_tests.rs @@ -1,3 +1,5 @@ +use std::sync::Arc; + use oxide_compiler::compiler::Compiler; use oxide_types::value::JsValue; use oxide_vm::vm::Vm; @@ -6,7 +8,7 @@ fn eval(vm: &mut Vm, source: &str) -> Result { let allocator = oxide_parser::Allocator::default(); let program = oxide_parser::parse(&allocator, source).map_err(|e| format!("Parse error: {:?}", e))?; let module = Compiler::new().compile(&program).map_err(|e| format!("Compile error: {}", e))?; - vm.run(&module) + vm.run(&Arc::new(module)) } fn assert_bool(value: JsValue, expected: bool) { diff --git a/crates/oxide_vm/tests/object_graph_retention_tests.rs b/crates/oxide_vm/tests/object_graph_retention_tests.rs index 2de70f43..e266a225 100644 --- a/crates/oxide_vm/tests/object_graph_retention_tests.rs +++ b/crates/oxide_vm/tests/object_graph_retention_tests.rs @@ -5,6 +5,8 @@ //! 变化,说明双计机制已变——须对照 tests/stress/mem_object_graph.js 的基线 //! (benchmark_baseline.json)复核后再更新本锚。 +use std::sync::Arc; + use oxide_compiler::compiler::Compiler; use oxide_parser::Allocator; use oxide_vm::vm::Vm; @@ -32,7 +34,7 @@ fn run_module(source: &str) -> Vm { let program = oxide_parser::parse(&allocator, source).expect("parse"); let module = Compiler::new().compile(&program).expect("compile"); let mut vm = Vm::new(); - let result = vm.run(&module).expect("run"); + let result = vm.run(&Arc::new(module)).expect("run"); assert_eq!(result.to_string(), "9", "root.left.id(2) + root.right.right.id(7)"); vm } diff --git a/crates/oxide_vm/tests/object_tests.rs b/crates/oxide_vm/tests/object_tests.rs index cb6c742d..13b25dae 100644 --- a/crates/oxide_vm/tests/object_tests.rs +++ b/crates/oxide_vm/tests/object_tests.rs @@ -1,3 +1,5 @@ +use std::sync::Arc; + use oxide_compiler::compiler::Compiler; use oxide_parser::Allocator; use oxide_vm::vm::Vm; @@ -13,7 +15,7 @@ fn eval(source: &str) -> String { Err(e) => return format!("compile error: {e}"), }; let mut vm = Vm::new(); - match vm.run(&module) { + match vm.run(&Arc::new(module)) { Ok(result) => format!("{result}"), Err(e) => format!("vm error: {e}"), } @@ -26,7 +28,7 @@ fn object_create_and_read() { let program = oxide_parser::parse(&allocator, source).expect("parse failed"); let module = Compiler::new().compile(&program).expect("compile failed"); let mut vm = Vm::new(); - let obj = vm.run(&module).expect("vm run failed"); + let obj = vm.run(&Arc::new(module)).expect("vm run failed"); assert!(obj.is_object()); let obj_ref = unsafe { &*obj.as_js_object_ptr() }; assert_eq!(obj_ref.prop_count(), 1, "object should have 1 property"); @@ -273,7 +275,7 @@ fn eval_string(source: &str) -> String { let mut vm = Vm::new(); let program = oxide_parser::parse(&allocator, source).expect("parse failed"); let module = Compiler::new().compile(&program).expect("compile failed"); - let result = vm.run(&module).expect("vm run failed"); + let result = vm.run(&Arc::new(module)).expect("vm run failed"); vm.lookup_str(result).unwrap_or_default() } diff --git a/crates/oxide_vm/tests/promise_tests.rs b/crates/oxide_vm/tests/promise_tests.rs index 23a6f16c..ea7d2c1a 100644 --- a/crates/oxide_vm/tests/promise_tests.rs +++ b/crates/oxide_vm/tests/promise_tests.rs @@ -1,3 +1,5 @@ +use std::sync::Arc; + use oxide_compiler::compiler::Compiler; use oxide_types::value::JsValue; use oxide_vm::promise::promise_settled_value; @@ -7,7 +9,7 @@ fn eval(vm: &mut Vm, source: &str) -> Result { let allocator = oxide_parser::Allocator::default(); let program = oxide_parser::parse(&allocator, source).map_err(|e| format!("Parse error: {:?}", e))?; let module = Compiler::new().compile(&program).map_err(|e| format!("Compile error: {}", e))?; - vm.run(&module) + vm.run(&Arc::new(module)) } /// 顶层表达式返回 Promise 时,run() 末尾 drain 已执行微任务,读其结算值。 diff --git a/crates/oxide_vm/tests/property_array_fastpath_tests.rs b/crates/oxide_vm/tests/property_array_fastpath_tests.rs index e0ddf119..c0499682 100644 --- a/crates/oxide_vm/tests/property_array_fastpath_tests.rs +++ b/crates/oxide_vm/tests/property_array_fastpath_tests.rs @@ -2,6 +2,8 @@ //! (密集数组 int 键界内直读写)与各回退场景(越界、hole、accessor、非数组、 //! 非对象 receiver)与 ordinary 属性路径行为一致。 +use std::sync::Arc; + use oxide_compiler::compiler::Compiler; use oxide_types::value::JsValue; use oxide_vm::vm::Vm; @@ -11,7 +13,7 @@ fn eval(source: &str) -> Result<(Vm, JsValue), String> { let program = oxide_parser::parse(&allocator, source).map_err(|e| format!("Parse error: {:?}", e))?; let module = Compiler::new().compile(&program).map_err(|e| format!("Compile error: {}", e))?; let mut vm = Vm::new(); - let result = vm.run(&module)?; + let result = vm.run(&Arc::new(module))?; Ok((vm, result)) } diff --git a/crates/oxide_vm/tests/property_delete_tests.rs b/crates/oxide_vm/tests/property_delete_tests.rs index 724d3a70..1a19bdf0 100644 --- a/crates/oxide_vm/tests/property_delete_tests.rs +++ b/crates/oxide_vm/tests/property_delete_tests.rs @@ -1,3 +1,5 @@ +use std::sync::Arc; + use oxide_compiler::compiler::Compiler; use oxide_types::value::JsValue; use oxide_vm::vm::Vm; @@ -7,7 +9,7 @@ fn eval(source: &str) -> Result { let program = oxide_parser::parse(&allocator, source).map_err(|e| format!("Parse error: {:?}", e))?; let module = Compiler::new().compile(&program).map_err(|e| format!("Compile error: {}", e))?; let mut vm = Vm::new(); - vm.run(&module) + vm.run(&Arc::new(module)) } fn eval_many(lines: &[&str]) -> Result { diff --git a/crates/oxide_vm/tests/property_keys_order_tests.rs b/crates/oxide_vm/tests/property_keys_order_tests.rs index e997ea6b..28f67316 100644 --- a/crates/oxide_vm/tests/property_keys_order_tests.rs +++ b/crates/oxide_vm/tests/property_keys_order_tests.rs @@ -1,3 +1,5 @@ +use std::sync::Arc; + use oxide_compiler::compiler::Compiler; use oxide_types::value::JsValue; use oxide_vm::vm::Vm; @@ -7,7 +9,7 @@ fn eval(source: &str) -> Result<(Vm, JsValue), String> { let program = oxide_parser::parse(&allocator, source).map_err(|e| format!("Parse error: {:?}", e))?; let module = Compiler::new().compile(&program).map_err(|e| format!("Compile error: {}", e))?; let mut vm = Vm::new(); - let result = vm.run(&module)?; + let result = vm.run(&Arc::new(module))?; Ok((vm, result)) } diff --git a/crates/oxide_vm/tests/property_receiver_tests.rs b/crates/oxide_vm/tests/property_receiver_tests.rs index e3c39947..24482a64 100644 --- a/crates/oxide_vm/tests/property_receiver_tests.rs +++ b/crates/oxide_vm/tests/property_receiver_tests.rs @@ -1,3 +1,5 @@ +use std::sync::Arc; + use oxide_compiler::compiler::Compiler; use oxide_types::value::JsValue; use oxide_vm::vm::Vm; @@ -7,7 +9,7 @@ fn eval(source: &str) -> Result<(Vm, JsValue), String> { let program = oxide_parser::parse(&allocator, source).map_err(|e| format!("Parse error: {:?}", e))?; let module = Compiler::new().compile(&program).map_err(|e| format!("Compile error: {}", e))?; let mut vm = Vm::new(); - let result = vm.run(&module)?; + let result = vm.run(&Arc::new(module))?; Ok((vm, result)) } diff --git a/crates/oxide_vm/tests/property_write_protection_tests.rs b/crates/oxide_vm/tests/property_write_protection_tests.rs index 185b80a5..b6aba72d 100644 --- a/crates/oxide_vm/tests/property_write_protection_tests.rs +++ b/crates/oxide_vm/tests/property_write_protection_tests.rs @@ -1,3 +1,5 @@ +use std::sync::Arc; + use oxide_compiler::compiler::Compiler; use oxide_types::value::JsValue; use oxide_vm::vm::Vm; @@ -7,7 +9,7 @@ fn eval(source: &str) -> Result { let program = oxide_parser::parse(&allocator, source).map_err(|e| format!("Parse error: {:?}", e))?; let module = Compiler::new().compile(&program).map_err(|e| format!("Compile error: {}", e))?; let mut vm = Vm::new(); - vm.run(&module) + vm.run(&Arc::new(module)) } // 返回保活的 Vm:结果可能含对象指针(数组/描述符),读取前必须保持 Vm 存活, @@ -17,7 +19,7 @@ fn eval_keep_vm(source: &str) -> Result<(Vm, JsValue), String> { let program = oxide_parser::parse(&allocator, source).map_err(|e| format!("Parse error: {:?}", e))?; let module = Compiler::new().compile(&program).map_err(|e| format!("Compile error: {}", e))?; let mut vm = Vm::new(); - let result = vm.run(&module)?; + let result = vm.run(&Arc::new(module))?; Ok((vm, result)) } diff --git a/crates/oxide_vm/tests/proto_chain_tests.rs b/crates/oxide_vm/tests/proto_chain_tests.rs index cf0a7e47..89e1e21d 100644 --- a/crates/oxide_vm/tests/proto_chain_tests.rs +++ b/crates/oxide_vm/tests/proto_chain_tests.rs @@ -1,3 +1,5 @@ +use std::sync::Arc; + use oxide_compiler::compiler::Compiler; use oxide_types::value::JsValue; use oxide_vm::vm::Vm; @@ -7,7 +9,7 @@ fn eval(source: &str) -> Result { let program = oxide_parser::parse(&allocator, source).map_err(|e| format!("Parse: {:?}", e))?; let module = Compiler::new().compile(&program).map_err(|e| format!("Compile: {}", e))?; let mut vm = Vm::new(); - vm.run(&module) + vm.run(&Arc::new(module)) } macro_rules! assert_bool { diff --git a/crates/oxide_vm/tests/readonly_global_builtin_tests.rs b/crates/oxide_vm/tests/readonly_global_builtin_tests.rs index 4918c96c..aa137df9 100644 --- a/crates/oxide_vm/tests/readonly_global_builtin_tests.rs +++ b/crates/oxide_vm/tests/readonly_global_builtin_tests.rs @@ -5,6 +5,8 @@ //! 绑定(var/let/参数)与其他可写内置(Math)不受影响。逻辑赋值额外钉住 //! 短路时序:短路未通过不发生 put(strict 不抛),通过才在写点拦截。 +use std::sync::Arc; + use oxide_compiler::compiler::Compiler; use oxide_types::value::JsValue; use oxide_vm::vm::Vm; @@ -14,7 +16,7 @@ fn eval(source: &str) -> Result { let program = oxide_parser::parse(&allocator, source).map_err(|e| format!("Parse error: {:?}", e))?; let module = Compiler::new().compile(&program).map_err(|e| format!("Compile error: {}", e))?; let mut vm = Vm::new(); - vm.run(&module) + vm.run(&Arc::new(module)) } fn eval_many(lines: &[&str]) -> Result { @@ -34,7 +36,7 @@ fn eval_str(source: &str) -> String { let program = oxide_parser::parse(&allocator, source).expect("parse"); let module = Compiler::new().compile(&program).expect("compile"); let mut vm = Vm::new(); - let result = vm.run(&module).expect("run"); + let result = vm.run(&Arc::new(module)).expect("run"); vm.lookup_str(result).unwrap_or_else(|| format!("{result}")) } diff --git a/crates/oxide_vm/tests/regression_tests.rs b/crates/oxide_vm/tests/regression_tests.rs index 6dfbf269..890842f2 100644 --- a/crates/oxide_vm/tests/regression_tests.rs +++ b/crates/oxide_vm/tests/regression_tests.rs @@ -16,7 +16,7 @@ fn eval(source: &str) -> String { Err(e) => return format!("compile error: {e}"), }; let mut vm = Vm::new(); - match vm.run(&module) { + match vm.run(&Arc::new(module)) { Ok(result) => format!("{result}"), Err(e) => format!("vm error: {e}"), } @@ -33,7 +33,7 @@ fn eval_with_kernel(source: &str, kernel: Arc) -> String { Err(e) => return format!("compile error: {e}"), }; let mut vm = Vm::with_kernel_core(kernel); - match vm.run(&module) { + match vm.run(&Arc::new(module)) { Ok(result) => format!("{result}"), Err(e) => format!("vm error: {e}"), } @@ -52,12 +52,12 @@ fn regression_rerun_clears_ic_cache() { let program = oxide_parser::parse(&allocator, source).expect("parse"); let module = Compiler::new().compile(&program).expect("compile"); let mut vm = Vm::new(); - assert_eq!(format!("{}", vm.run(&module).unwrap()), "1"); + assert_eq!(format!("{}", vm.run(&Arc::new(module)).unwrap()), "1"); let source2 = "var o = {a: 2}; o.a"; let program2 = oxide_parser::parse(&allocator, source2).expect("parse"); let module2 = Compiler::new().compile(&program2).expect("compile"); - vm.run(&module2).unwrap(); + vm.run(&Arc::new(module2)).unwrap(); assert_eq!( format!("{}", vm.rerun().unwrap()), "2", @@ -188,7 +188,7 @@ fn eval_shallow(source: &str, depth: usize) -> String { let mut cfg = KernelConfig::minimal(); cfg.max_call_depth = depth; let mut vm = Vm::with_kernel_core(KernelCore::new(cfg)); - match vm.run(&module) { + match vm.run(&Arc::new(module)) { Ok(val) => { if val.is_string() { vm.lookup_str(val).unwrap_or_default().to_string() diff --git a/crates/oxide_vm/tests/rest_params_tests.rs b/crates/oxide_vm/tests/rest_params_tests.rs index 4609305a..1f0050f7 100644 --- a/crates/oxide_vm/tests/rest_params_tests.rs +++ b/crates/oxide_vm/tests/rest_params_tests.rs @@ -1,6 +1,8 @@ //! rest 参数集成测试:实参收集、length 交互、与 spread/箭头/闭包组合。 //! 每个用例独立编译执行,断言顶层表达式结果。 +use std::sync::Arc; + use oxide_compiler::compiler::Compiler; use oxide_parser::Allocator; use oxide_types::value::JsValue; @@ -11,7 +13,7 @@ fn eval(source: &str) -> JsValue { let program = oxide_parser::parse(&allocator, source).expect("parse failed"); let module = Compiler::new().compile(&program).expect("compile failed"); let mut vm = Vm::new(); - vm.run(&module).expect("vm run failed") + vm.run(&Arc::new(module)).expect("vm run failed") } fn eval_int(source: &str) -> i32 { @@ -30,7 +32,7 @@ fn eval_str(source: &str) -> String { let program = oxide_parser::parse(&allocator, source).expect("parse failed"); let module = Compiler::new().compile(&program).expect("compile failed"); let mut vm = Vm::new(); - let v = vm.run(&module).expect("vm run failed"); + let v = vm.run(&Arc::new(module)).expect("vm run failed"); // 字符串结果须在同一 VM 上读:perm 串指向 VM 私有内核,VM drop 后指针悬垂。 if v.is_string() { vm.lookup_str(v).unwrap_or_default() diff --git a/crates/oxide_vm/tests/scoping_tests.rs b/crates/oxide_vm/tests/scoping_tests.rs index 60901751..9edcf692 100644 --- a/crates/oxide_vm/tests/scoping_tests.rs +++ b/crates/oxide_vm/tests/scoping_tests.rs @@ -1,3 +1,5 @@ +use std::sync::Arc; + use oxide_compiler::compiler::Compiler; use oxide_types::value::JsValue; use oxide_vm::vm::Vm; @@ -7,7 +9,7 @@ fn eval(source: &str) -> Result { let program = oxide_parser::parse(&allocator, source).map_err(|e| format!("Parse: {:?}", e))?; let module = Compiler::new().compile(&program).map_err(|e| format!("Compile: {}", e))?; let mut vm = Vm::new(); - vm.run(&module) + vm.run(&Arc::new(module)) } #[test] diff --git a/crates/oxide_vm/tests/session_arena_tests.rs b/crates/oxide_vm/tests/session_arena_tests.rs index b2605c9d..16369657 100644 --- a/crates/oxide_vm/tests/session_arena_tests.rs +++ b/crates/oxide_vm/tests/session_arena_tests.rs @@ -1,3 +1,5 @@ +use std::sync::Arc; + use oxide_compiler::compiler::Compiler; use oxide_parser::Allocator; use oxide_types::value::JsValue; @@ -7,7 +9,7 @@ fn run_source(vm: &mut Vm, source: &str) -> JsValue { let allocator = Allocator::default(); let program = oxide_parser::parse(&allocator, source).expect("parse failed"); let module = Compiler::new().compile(&program).expect("compile failed"); - vm.run(&module).expect("vm run failed") + vm.run(&Arc::new(module)).expect("vm run failed") } fn global_prop(vm: &Vm, name: &str) -> JsValue { diff --git a/crates/oxide_vm/tests/sloppy_assignment_silent_tests.rs b/crates/oxide_vm/tests/sloppy_assignment_silent_tests.rs index 02ad9d8c..f783a54c 100644 --- a/crates/oxide_vm/tests/sloppy_assignment_silent_tests.rs +++ b/crates/oxide_vm/tests/sloppy_assignment_silent_tests.rs @@ -3,6 +3,8 @@ //! 覆盖脚本顶层(`top_level_strict`)、函数级(帧 `strict`)与内联内置回调 //! (forEach 等,`inline_strict` + 帧基线)三种执行上下文。 +use std::sync::Arc; + use oxide_compiler::compiler::Compiler; use oxide_types::value::JsValue; use oxide_vm::vm::Vm; @@ -12,7 +14,7 @@ fn eval(source: &str) -> Result { let program = oxide_parser::parse(&allocator, source).map_err(|e| format!("Parse error: {:?}", e))?; let module = Compiler::new().compile(&program).map_err(|e| format!("Compile error: {}", e))?; let mut vm = Vm::new(); - vm.run(&module) + vm.run(&Arc::new(module)) } fn eval_many(lines: &[&str]) -> Result { @@ -32,7 +34,7 @@ fn eval_str(source: &str) -> String { let program = oxide_parser::parse(&allocator, source).expect("parse"); let module = Compiler::new().compile(&program).expect("compile"); let mut vm = Vm::new(); - let result = vm.run(&module).expect("run"); + let result = vm.run(&Arc::new(module)).expect("run"); vm.lookup_str(result).unwrap_or_else(|| format!("{result}")) } diff --git a/crates/oxide_vm/tests/spill_stack_tests.rs b/crates/oxide_vm/tests/spill_stack_tests.rs index 58c11619..1ed572df 100644 --- a/crates/oxide_vm/tests/spill_stack_tests.rs +++ b/crates/oxide_vm/tests/spill_stack_tests.rs @@ -3,6 +3,8 @@ //! //! 手工 IR 是唯一可达路径——RegAlloc 未接入,真实 JS 编译产物不会含三指令。 +use std::sync::Arc; + use oxide_bytecode::module::Constant; use oxide_bytecode::opcode::OpCode; use oxide_ir::inst::Inst; @@ -15,7 +17,7 @@ fn run_ir(ir: IRFunction) -> String { // 手工 IR 不经 Compiler::compile,需手动扁平化子模块(create_closure 相对索引)。 oxide_compiler::flatten::flatten_submodules(&mut module); let mut vm = Vm::new(); - match vm.run(&module) { + match vm.run(&Arc::new(module)) { Ok(v) => format!("{v}"), Err(e) => format!("vm error: {e}"), } diff --git a/crates/oxide_vm/tests/string_rope_tests.rs b/crates/oxide_vm/tests/string_rope_tests.rs index 5e2d0ba8..03ec8f7d 100644 --- a/crates/oxide_vm/tests/string_rope_tests.rs +++ b/crates/oxide_vm/tests/string_rope_tests.rs @@ -4,6 +4,8 @@ //! for-of/属性键/模板/JSON/展开)的惰性扁平化正确性、数字/对象叶子混合、CONCAT_N //! 产物作 rope 叶子、低 GC 阈值下跨执行期字符串回收的存活与 mark 传播。 +use std::sync::Arc; + use oxide_compiler::compiler::Compiler; use oxide_kernel::kernel::{KernelConfig, KernelCore}; use oxide_types::value::JsValue; @@ -13,7 +15,7 @@ fn eval(vm: &mut Vm, source: &str) -> Result { let allocator = oxide_parser::Allocator::default(); let program = oxide_parser::parse(&allocator, source).map_err(|e| format!("Parse error: {:?}", e))?; let module = Compiler::new().compile(&program).map_err(|e| format!("Compile error: {e}"))?; - vm.run(&module) + vm.run(&Arc::new(module)) } fn eval_str(source: &str) -> String { diff --git a/crates/oxide_vm/tests/template_tests.rs b/crates/oxide_vm/tests/template_tests.rs index 1df29f63..3d16d559 100644 --- a/crates/oxide_vm/tests/template_tests.rs +++ b/crates/oxide_vm/tests/template_tests.rs @@ -1,3 +1,5 @@ +use std::sync::Arc; + use oxide_bytecode::module::Constant; use oxide_bytecode::opcode::OpCode; use oxide_compiler::compiler::Compiler; @@ -19,7 +21,7 @@ fn eval(source: &str) -> String { Err(e) => return format!("compile error: {}", e), }; let mut vm = Vm::new(); - match vm.run(&module) { + match vm.run(&Arc::new(module)) { Ok(result) => format!("{}", result), Err(e) => format!("vm error: {}", e), } @@ -36,7 +38,7 @@ fn eval_val(source: &str) -> (Vm, Result) { Err(e) => return (Vm::new(), Err(format!("compile error: {}", e))), }; let mut vm = Vm::new(); - let result = vm.run(&module); + let result = vm.run(&Arc::new(module)); (vm, result) } @@ -134,7 +136,7 @@ fn template_expression_reads_physical_register_above_127() { let module = oxide_ir::lower::lower(&ir).expect("lower template IR"); let mut vm = Vm::new(); - let result = vm.run(&module).expect("run template IR"); + let result = vm.run(&Arc::new(module)).expect("run template IR"); assert_eq!(to_str(&vm, result), "value"); } diff --git a/crates/oxide_vm/tests/test262_host_tests.rs b/crates/oxide_vm/tests/test262_host_tests.rs index 565a664d..642a77c5 100644 --- a/crates/oxide_vm/tests/test262_host_tests.rs +++ b/crates/oxide_vm/tests/test262_host_tests.rs @@ -1,6 +1,8 @@ //! test262 宿主对象 `$262` 的最小绑定验证:对象存在、`global` 指向当前 realm //! 全局、evalScript 可执行、未实现方法抛能力缺失错误。 +use std::sync::Arc; + use oxide_compiler::compiler::Compiler; use oxide_parser::Allocator; use oxide_vm::vm::Vm; @@ -17,7 +19,7 @@ fn eval(source: &str) -> String { Err(e) => return format!("compile error: {e}"), }; let mut vm = Vm::new(); - match vm.run(&module) { + match vm.run(&Arc::new(module)) { Ok(result) => vm.lookup_str(result).unwrap_or_else(|| format!("{result}")), Err(e) => format!("vm error: {e}"), } diff --git a/crates/oxide_vm/tests/this_binding_tests.rs b/crates/oxide_vm/tests/this_binding_tests.rs index d5cc7075..573eb07c 100644 --- a/crates/oxide_vm/tests/this_binding_tests.rs +++ b/crates/oxide_vm/tests/this_binding_tests.rs @@ -2,6 +2,8 @@ //! 时替换为全局对象;箭头/严格/method/构造/显式 receiver 均不替换。 //! 覆盖普通调用、call/apply/bind、builtin 回调、构造、生成器、async、derived 构造。 +use std::sync::Arc; + use oxide_compiler::compiler::Compiler; use oxide_types::object::JsObject; use oxide_types::value::JsValue; @@ -11,7 +13,7 @@ fn eval(vm: &mut Vm, source: &str) -> Result { let allocator = oxide_parser::Allocator::default(); let program = oxide_parser::parse(&allocator, source).map_err(|e| format!("Parse error: {:?}", e))?; let module = Compiler::new().compile(&program).map_err(|e| format!("Compile error: {}", e))?; - vm.run(&module) + vm.run(&Arc::new(module)) } /// 断言表达式结果为 `true`。 diff --git a/crates/oxide_vm/tests/try_finally_control_flow_tests.rs b/crates/oxide_vm/tests/try_finally_control_flow_tests.rs index 4fb752a7..ac9b1025 100644 --- a/crates/oxide_vm/tests/try_finally_control_flow_tests.rs +++ b/crates/oxide_vm/tests/try_finally_control_flow_tests.rs @@ -4,6 +4,8 @@ //! 异常路径不回归、嵌套 try/finally、for-of 迭代器关闭、普通循环零开销路径。 //! 字符串值在此引擎 Display 为 `{string}`,断言一律用数值编码。 +use std::sync::Arc; + use oxide_compiler::compiler::Compiler; use oxide_parser::Allocator; use oxide_vm::vm::Vm; @@ -19,7 +21,7 @@ fn eval(source: &str) -> String { Err(e) => return format!("compile error: {e}"), }; let mut vm = Vm::new(); - match vm.run(&module) { + match vm.run(&Arc::new(module)) { Ok(result) => format!("{result}"), Err(e) => format!("vm error: {e}"), } diff --git a/crates/oxide_vm/tests/undeclared_read_tests.rs b/crates/oxide_vm/tests/undeclared_read_tests.rs index 09377b84..54ba7433 100644 --- a/crates/oxide_vm/tests/undeclared_read_tests.rs +++ b/crates/oxide_vm/tests/undeclared_read_tests.rs @@ -3,6 +3,8 @@ //! 覆盖:读未声明抛 ReferenceError;typeof 未声明返回 "undefined"; //! sloppy 写后读正常;harness 全局 var 声明安全;内置标识符不误判。 +use std::sync::Arc; + use oxide_compiler::compiler::Compiler; use oxide_types::value::JsValue; use oxide_vm::vm::Vm; @@ -12,7 +14,7 @@ fn eval(source: &str) -> Result { let program = oxide_parser::parse(&allocator, source).map_err(|e| format!("Parse: {:?}", e))?; let module = Compiler::new().compile(&program).map_err(|e| format!("Compile: {}", e))?; let mut vm = Vm::new(); - vm.run(&module) + vm.run(&Arc::new(module)) } /// 求值并取字符串结果内容(字符串值走 lookup_str,非字符串走 Display)。 @@ -21,7 +23,7 @@ fn eval_str(source: &str) -> Result { let allocator = oxide_parser::Allocator::default(); let program = oxide_parser::parse(&allocator, source).map_err(|e| format!("Parse: {:?}", e))?; let module = Compiler::new().compile(&program).map_err(|e| format!("Compile: {}", e))?; - let result = vm.run(&module)?; + let result = vm.run(&Arc::new(module))?; Ok(vm.lookup_str(result).unwrap_or_default()) } diff --git a/crates/oxide_vm/tests/update_tests.rs b/crates/oxide_vm/tests/update_tests.rs index 42ecbf22..1a23b033 100644 --- a/crates/oxide_vm/tests/update_tests.rs +++ b/crates/oxide_vm/tests/update_tests.rs @@ -1,3 +1,5 @@ +use std::sync::Arc; + use oxide_compiler::compiler::Compiler; use oxide_parser::Allocator; use oxide_vm::vm::Vm; @@ -13,7 +15,7 @@ fn eval(source: &str) -> String { Err(e) => return format!("compile error: {e}"), }; let mut vm = Vm::new(); - match vm.run(&module) { + match vm.run(&Arc::new(module)) { Ok(result) => format!("{result}"), Err(e) => format!("vm error: {e}"), } diff --git a/crates/oxide_vm/tests/var_binding_tests.rs b/crates/oxide_vm/tests/var_binding_tests.rs index 466a0be9..af791df9 100644 --- a/crates/oxide_vm/tests/var_binding_tests.rs +++ b/crates/oxide_vm/tests/var_binding_tests.rs @@ -1,3 +1,5 @@ +use std::sync::Arc; + use oxide_compiler::compiler::Compiler; use oxide_parser::Allocator; use oxide_vm::vm::Vm; @@ -13,7 +15,7 @@ fn eval(source: &str) -> String { Err(e) => return format!("compile error: {e}"), }; let mut vm = Vm::new(); - match vm.run(&module) { + match vm.run(&Arc::new(module)) { Ok(result) => format!("{result}"), Err(e) => format!("vm error: {e}"), } diff --git a/crates/oxide_vm/tests/vm_tests.rs b/crates/oxide_vm/tests/vm_tests.rs index 64c00112..4e2d53af 100644 --- a/crates/oxide_vm/tests/vm_tests.rs +++ b/crates/oxide_vm/tests/vm_tests.rs @@ -1,3 +1,5 @@ +use std::sync::Arc; + use oxide_compiler::compiler::Compiler; use oxide_parser::Allocator; use oxide_vm::vm::Vm; @@ -13,7 +15,7 @@ fn eval(source: &str) -> String { Err(e) => return format!("compile error: {e}"), }; let mut vm = Vm::new(); - match vm.run(&module) { + match vm.run(&Arc::new(module)) { Ok(result) => format!("{result}"), Err(e) => format!("vm error: {e}"), }