From 00e607f67ef9231f6d7bdf16e7ea3d13d9867cd3 Mon Sep 17 00:00:00 2001 From: pjh456 <147148383@qq.com> Date: Sat, 26 Sep 2026 05:33:10 +0000 Subject: [PATCH] =?UTF-8?q?fix:=20IsHTMLDDA=20=E5=AE=BF=E4=B8=BB=E5=AF=B9?= =?UTF-8?q?=E8=B1=A1=E8=A1=A5=E5=8F=AF=E8=B0=83=E7=94=A8=E5=B9=B6=E8=B0=83?= =?UTF-8?q?=E6=95=B4=20typeof=20=E5=88=A4=E5=AE=9A=E5=BA=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- crates/oxide_vm/src/dispatch/misc.rs | 11 ++++++----- crates/oxide_vm/src/test262_host.rs | 18 +++++++++++++++--- 2 files changed, 21 insertions(+), 8 deletions(-) diff --git a/crates/oxide_vm/src/dispatch/misc.rs b/crates/oxide_vm/src/dispatch/misc.rs index 7e353781..ec88c673 100644 --- a/crates/oxide_vm/src/dispatch/misc.rs +++ b/crates/oxide_vm/src/dispatch/misc.rs @@ -85,13 +85,14 @@ impl Vm { JsType::Symbol => 5, JsType::BigInt => 6, JsType::Object => { - // 函数对象归为 "function"(语言类型是 object,typeof 有专属分支); - // [[IsHTMLDDA]] 宿主对象按 "undefined" 报告(B.3.4,Type 仍是 object)。 + // [[IsHTMLDDA]] 宿主对象按 "undefined" 报告(B.3.4,Type 仍是 object); + // 宿主对象可调用,判定须先于函数分支,typeof 仍报 "undefined"。 + // 其余函数对象归为 "function"(语言类型是 object,typeof 有专属分支)。 let obj = unsafe { &*val.as_js_object_ptr() }; - if obj.is_function() { - 7 - } else if obj.is_html_dda_obj() { + if obj.is_html_dda_obj() { 0 + } else if obj.is_function() { + 7 } else { 1 } diff --git a/crates/oxide_vm/src/test262_host.rs b/crates/oxide_vm/src/test262_host.rs index 6095f678..e77a78ca 100644 --- a/crates/oxide_vm/src/test262_host.rs +++ b/crates/oxide_vm/src/test262_host.rs @@ -10,7 +10,7 @@ use std::sync::Arc; use oxide_kernel::kernel::{KernelCore, KernelSession}; use oxide_kernel::shape_forge::EMPTY_SHAPE_ID; use oxide_runtime_api::{to_units_full, NativeResult}; -use oxide_types::object::JsObject; +use oxide_types::object::{JsObject, NativeFnPtr}; use oxide_types::value::JsValue; use crate::bindings::{apply_binding_table, bind_global_value}; @@ -91,12 +91,21 @@ pub fn agent(vm: &mut Vm, _args: &[u8]) -> NativeResult { not_supported(vm, "agent") } +/// `$262.IsHTMLDDA(...)`:B.3.4 宿主对象本体,被调用时返回 null。 +/// +/// 规范定义无参或首参空串时返回 null(String 方法、迭代器协议经 GetMethod +/// 读得后按可调用值调用即得 null);其余调用形态行为未定义,统一返回 null。 +pub fn is_html_dda_call(_vm: &mut Vm, _args: &[u8]) -> NativeResult { + NativeResult::Ok(JsValue::null()) +} + /// 把 `$262` 宿主对象绑定到 global:对象本体 + 标准方法 + `global` 数据属性。 /// /// # 步骤 /// 1. 建 `$262` 普通对象(Object.prototype)。 /// 2. 绑定 evalScript/detachArrayBuffer/createRealm/gc/agent 方法。 /// 3. `global` 数据属性指向当前 session global;`$262` 本体挂到 global。 +/// 4. `IsHTMLDDA` 宿主对象挂到 `$262`(可调用,被调用时返回 null)。 /// /// # 注意事项 /// - 宿主对象登记进 world 释放表,session 收尾时统一释放(与 Reflect/Iterator @@ -119,10 +128,13 @@ pub fn bind_test262_host(core: &Arc, session: &KernelSession, global ); let global_this = JsValue::from_js_object(global as *mut JsObject); bind_global_value(core, &mut host, "global", global_this); - // [[IsHTMLDDA]] 宿主值(B.3.4):ToBoolean/typeof/宽松相等按 undefined 处理, - // Type 与其余强制转换按普通对象处理。无额外内部载荷,挂 Object.prototype。 + // [[IsHTMLDDA]] 宿主值(B.3.4):可调用(被调用时返回 null), + // ToBoolean/typeof/宽松相等按 undefined 处理,Type 与其余强制转换按普通对象处理。 let mut dda = JsObject::new_empty(EMPTY_SHAPE_ID, JsValue::from_js_object(object_proto)); dda.type_tag = JsObject::OBJ_TYPE_HTML_DDA; + dda.set_function(true); + dda.set_native_fn(Some(unsafe { NativeFnPtr::from_raw(is_html_dda_call as *const ()) })); + dda.set_native_arg_count(0); let dda_ptr = Box::into_raw(Box::new(dda)); session.builtin_world().track_leaked_object(dda_ptr); bind_global_value(core, &mut host, "IsHTMLDDA", JsValue::from_js_object(dda_ptr));