From 58c39783387549328a7037bfc4bba96e333e7af5 Mon Sep 17 00:00:00 2001 From: pjh456 <147148383@qq.com> Date: Sun, 18 Oct 2026 18:32:12 +0000 Subject: [PATCH] =?UTF-8?q?feat:=20=E7=A7=BB=E9=99=A4=20Proxy=20=E4=B8=89?= =?UTF-8?q?=E9=97=A8=E5=B9=B6=E5=85=A8=E9=87=8F=E5=9B=9E=E6=B5=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Cargo.lock | 42 +++++++++---------- Cargo.toml | 2 +- crates/oxide_test262/src/discovery.rs | 2 +- crates/oxide_test262/src/harness.rs | 14 +++++-- crates/oxide_test262/src/judge.rs | 1 - crates/oxide_vm/src/promise/aggregate.rs | 52 +++++++++++++++--------- scripts/asan_gate.sh | 11 ++++- 7 files changed, 75 insertions(+), 49 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 99e69f48..b982358b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1160,7 +1160,7 @@ dependencies = [ [[package]] name = "oxide_builtins" -version = "0.20.16" +version = "0.21.0" dependencies = [ "chrono", "fast-float", @@ -1185,7 +1185,7 @@ dependencies = [ [[package]] name = "oxide_bytecode" -version = "0.20.16" +version = "0.21.0" dependencies = [ "num-bigint", "oxide_log", @@ -1193,7 +1193,7 @@ dependencies = [ [[package]] name = "oxide_cfg" -version = "0.20.16" +version = "0.21.0" dependencies = [ "oxide_bytecode", "oxide_emit", @@ -1204,7 +1204,7 @@ dependencies = [ [[package]] name = "oxide_cli" -version = "0.20.16" +version = "0.21.0" dependencies = [ "ansi_term", "bumpalo", @@ -1228,7 +1228,7 @@ dependencies = [ [[package]] name = "oxide_code_cache" -version = "0.20.16" +version = "0.21.0" dependencies = [ "lru", "oxide_bytecode", @@ -1237,7 +1237,7 @@ dependencies = [ [[package]] name = "oxide_compiler" -version = "0.20.16" +version = "0.21.0" dependencies = [ "oxide_bytecode", "oxide_cfg", @@ -1258,7 +1258,7 @@ dependencies = [ [[package]] name = "oxide_dce" -version = "0.20.16" +version = "0.21.0" dependencies = [ "oxide_bytecode", "oxide_cfg", @@ -1272,7 +1272,7 @@ dependencies = [ [[package]] name = "oxide_emit" -version = "0.20.16" +version = "0.21.0" dependencies = [ "num-bigint", "oxc_allocator", @@ -1288,7 +1288,7 @@ dependencies = [ [[package]] name = "oxide_engine" -version = "0.20.16" +version = "0.21.0" dependencies = [ "oxide_bytecode", "oxide_compiler", @@ -1300,7 +1300,7 @@ dependencies = [ [[package]] name = "oxide_fold" -version = "0.20.16" +version = "0.21.0" dependencies = [ "num-bigint", "oxide_bytecode", @@ -1312,7 +1312,7 @@ dependencies = [ [[package]] name = "oxide_ir" -version = "0.20.16" +version = "0.21.0" dependencies = [ "oxide_bytecode", "oxide_log", @@ -1321,7 +1321,7 @@ dependencies = [ [[package]] name = "oxide_kernel" -version = "0.20.16" +version = "0.21.0" dependencies = [ "bumpalo", "dashmap", @@ -1335,7 +1335,7 @@ dependencies = [ [[package]] name = "oxide_liveness" -version = "0.20.16" +version = "0.21.0" dependencies = [ "oxide_bytecode", "oxide_cfg", @@ -1347,7 +1347,7 @@ dependencies = [ [[package]] name = "oxide_log" -version = "0.20.16" +version = "0.21.0" dependencies = [ "tracing", "tracing-appender", @@ -1356,11 +1356,11 @@ dependencies = [ [[package]] name = "oxide_net" -version = "0.20.16" +version = "0.21.0" [[package]] name = "oxide_parser" -version = "0.20.16" +version = "0.21.0" dependencies = [ "oxc_allocator", "oxc_ast", @@ -1375,7 +1375,7 @@ dependencies = [ [[package]] name = "oxide_regalloc" -version = "0.20.16" +version = "0.21.0" dependencies = [ "oxide_bytecode", "oxide_cfg", @@ -1391,7 +1391,7 @@ dependencies = [ [[package]] name = "oxide_runtime_api" -version = "0.20.16" +version = "0.21.0" dependencies = [ "num-bigint", "num-traits", @@ -1404,7 +1404,7 @@ dependencies = [ [[package]] name = "oxide_test262" -version = "0.20.16" +version = "0.21.0" dependencies = [ "oxide_bytecode", "oxide_compiler", @@ -1424,7 +1424,7 @@ dependencies = [ [[package]] name = "oxide_types" -version = "0.20.16" +version = "0.21.0" dependencies = [ "bumpalo", "dashmap", @@ -1437,7 +1437,7 @@ dependencies = [ [[package]] name = "oxide_vm" -version = "0.20.16" +version = "0.21.0" dependencies = [ "bumpalo", "chrono", diff --git a/Cargo.toml b/Cargo.toml index f40888c7..fe95894e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -25,7 +25,7 @@ members = [ ] [workspace.package] -version = "0.20.16" +version = "0.21.0" edition = "2021" license = "MIT" rust-version = "1.80" diff --git a/crates/oxide_test262/src/discovery.rs b/crates/oxide_test262/src/discovery.rs index b582c2bd..91323767 100644 --- a/crates/oxide_test262/src/discovery.rs +++ b/crates/oxide_test262/src/discovery.rs @@ -36,7 +36,7 @@ pub(crate) fn is_skipped(meta: &TestMeta) -> Option { // 保持大范围已实现 feature tag 可运行;只排除真正未实现的子特性。 // 其余一切让测试实际运行,依赖运行时跳过逻辑 // ("too many registers"、"not yet implemented" 等)判定失败。 - let excluded_features = ["Proxy", "Intl", "Atomics", "cross-realm"]; + let excluded_features = ["Intl", "Atomics", "cross-realm"]; for feat in &meta.features { if excluded_features.contains(&feat.as_str()) || feat.starts_with("Intl") { diff --git a/crates/oxide_test262/src/harness.rs b/crates/oxide_test262/src/harness.rs index 57320502..52fe044b 100644 --- a/crates/oxide_test262/src/harness.rs +++ b/crates/oxide_test262/src/harness.rs @@ -1,4 +1,4 @@ -//! test262 harness 内嵌注册表与前缀拼接/缓存:`HarnessSources`(24 处 `include_str!`)、`HARNESS`、黑名单、 +//! test262 harness 内嵌注册表与前缀拼接/缓存:`HarnessSources`(26 处 `include_str!`)、`HARNESS`、黑名单、 //! 前缀拼接与缓存。全部 `include_str!` 路径相对上 3 级到仓库根,依赖本文件平铺 `src/` 一级,禁子目录。 use crate::meta::TestMeta; @@ -66,6 +66,14 @@ impl HarnessSources { "resizableArrayBufferUtils.js", include_str!("../../../tests/test262/harness/resizableArrayBufferUtils.js"), ); + sources.insert( + "proxyTrapsHelper.js", + include_str!("../../../tests/test262/harness/proxyTrapsHelper.js"), + ); + sources.insert( + "iteratorZipUtils.js", + include_str!("../../../tests/test262/harness/iteratorZipUtils.js"), + ); Self { sources } } @@ -77,17 +85,15 @@ impl HarnessSources { pub(crate) static HARNESS: OnceLock = OnceLock::new(); -/// 判断 harness 文件是否在支持范围之外(依赖 Proxy/Intl/async 等未实现特性)。 +/// 判断 harness 文件是否在支持范围之外(依赖 Intl/async 等未实现特性)。 fn is_blacklisted_harness(name: &str) -> bool { matches!( name, "testIntl.js" | "atomicsHelper.js" - | "proxyTrapsHelper.js" | "tcoHelper.js" | "byteConversionValues.js" | "compareIterator.js" - | "iteratorZipUtils.js" ) } diff --git a/crates/oxide_test262/src/judge.rs b/crates/oxide_test262/src/judge.rs index 5cf5f559..1feb71df 100644 --- a/crates/oxide_test262/src/judge.rs +++ b/crates/oxide_test262/src/judge.rs @@ -371,7 +371,6 @@ mod tests { #[test] fn unimplemented_shapes_stay_skipped() { for e in [ - "not yet implemented: Proxy", "feature is not supported", "unsupported syntax", "vm error: NEW_EXPRESSION not supported", diff --git a/crates/oxide_vm/src/promise/aggregate.rs b/crates/oxide_vm/src/promise/aggregate.rs index 3798c889..352d4ce3 100644 --- a/crates/oxide_vm/src/promise/aggregate.rs +++ b/crates/oxide_vm/src/promise/aggregate.rs @@ -10,7 +10,7 @@ use oxide_kernel::shape_forge::EMPTY_SHAPE_ID; use oxide_runtime_api::NativeResult; use oxide_types::object::{JsObject, NativeFnPtr, PropAttributes}; -use oxide_types::private_key::{decode_symbol_key, encode_symbol_key, is_symbol_key, make_int_key}; +use oxide_types::private_key::{decode_symbol_key, is_symbol_key, make_int_key}; use oxide_types::value::JsValue; use crate::native::NativeFn; @@ -706,28 +706,42 @@ fn perform_promise_combine_keyed( let keys = vm.make_plain_array(Vec::new()); let record = vm.make_agg_record_keyed(values, keys, resolve, reject); - // OwnKeys 序:整数键升序、字符串键插入序;符号键按插入序追加(shape 位置 - // 换算绝对存储下标,与 walk_own_keys 口径一致)。 - let mut all_keys = oxide_builtins::object::walk_own_keys(vm, promises_obj); - for sym in oxide_builtins::object::own_symbol_key_values(vm, promises_obj) { - let si = encode_symbol_key(vm.realm_id(), sym.as_symbol_index()); - if let Some(pos) = vm.kernel_core.shape_forge().lookup_position(promises_obj.shape_id(), si) { - let store = if promises_obj.is_array() { promises_obj.array_prop_count + pos } else { pos }; - all_keys.push((si, store)); + // OwnKeys 序:整数键升序、字符串键插入序;符号键按插入序追加。代理感知: + // 代理经 ownKeys trap(缺失落穿 target 自身键),trap 抛错异步拒绝。 + let (all_keys, _storage) = match oxide_builtins::object::own_keys_proxy_aware(vm, promises_obj) { + Ok(ks) => ks, + Err(exc) => { + let _ = vm.call_function_sync(reject, JsValue::undefined(), &[exc]); + return Ok(promise); } - } + }; let mut index: i32 = 0; - for (si, store) in all_keys { - // 可枚举性:TA 元素键(哨兵存储下标)恒在场且可枚举;其余查元数据区 - // (无元数据 = 默认数据描述符,可枚举)。 - let enumerable = if store == u32::MAX { - true - } else { - promises_obj - .prop_meta_at(store) - .map_or(true, |m| !m.is_hole() && m.attributes.enumerable()) + for (si, _store) in all_keys { + // [[GetOwnProperty]](key):代理经 getOwnPropertyDescriptor trap 路由, + // 缺失跳过,抛错异步拒绝;可枚举性取描述符 enumerable 属性(缺省为真)。 + let desc = match oxide_builtins::object::own_descriptor_value(vm, promises_obj, si) { + Ok(d) => d, + Err(exc) => { + let _ = vm.call_function_sync(reject, JsValue::undefined(), &[exc]); + return Ok(promise); + } }; + let Some(desc) = desc else { + continue; + }; + // SAFETY: desc 是存活描述符对象。 + let desc_obj = unsafe { &*desc.as_js_object_ptr() }; + let en_si = vm.kernel_core.perm_interner().intern("enumerable").0; + let en = match vm.ordinary_get(desc_obj, en_si, desc) { + Ok(v) => v, + Err(e) => { + let exc = agg_engine_error(vm, &e); + let _ = vm.call_function_sync(reject, JsValue::undefined(), &[exc]); + return Ok(promise); + } + }; + let enumerable = if en.is_undefined() { true } else { oxide_runtime_api::to_boolean(en) }; if !enumerable { continue; } diff --git a/scripts/asan_gate.sh b/scripts/asan_gate.sh index 265c628d..f1f24697 100755 --- a/scripts/asan_gate.sh +++ b/scripts/asan_gate.sh @@ -2,7 +2,7 @@ # ASan 常设门:按地址 sanitizer 配方跑全 workspace 单测。 # # 用法: scripts/asan_gate.sh -# 无参数。nightly 工具链加地址 sanitizer 构建并跑 cargo test --workspace。 +# 无参数。nightly 工具链加地址 sanitizer 构建并跑 cargo test --workspace --no-fail-fast。 # # 配方说明:detect_leaks=0 因 PermInterner 与静态表设计性永久泄漏, # 泄漏检测纯噪声;quarantine_size_mb=64 收隔离区,压高并发下内存放大。 @@ -28,5 +28,12 @@ export ASAN_OPTIONS="detect_leaks=0:quarantine_size_mb=64" # proc-macro 动态库加载进无 ASan 运行时的 rustc 会失败, # 经包装器剥离其 sanitizer 标志(见包装器头部注释)。 export RUSTC="$PWD/scripts/asan_rustc_wrapper.sh" +# 禁用 sccache:其 Rust direct mode 由 server 自行解析工具链 rustc 直接编译 +# rlib 单元,绕过上面的 RUSTC 包装器链,依赖树(version_check、autocfg 等) +# 会带着 sanitizer 插桩编译,链接进 build script 时因缺 ASan 运行时而失败。 +# 门的构建量小(仅依赖树多一次编译),不需要 sccache 加速。 +export CARGO_BUILD_RUSTC_WRAPPER="" -cargo test --workspace +# no-fail-fast:预存失败测试不应中断内存安全门,须跑完全部测试目标 +# 再汇总(门判据是 ASan 报告与失败清单,任一失败目标不阻断其余目标)。 +cargo test --workspace --no-fail-fast