From ae330e2b3449d7030d18fde730009c64e88abb4a Mon Sep 17 00:00:00 2001 From: pjh456 <147148383@qq.com> Date: Fri, 25 Sep 2026 06:52:46 +0000 Subject: [PATCH] =?UTF-8?q?fix:=20=E8=A3=85=E7=AE=B1=20Symbol=20=E5=BC=BA?= =?UTF-8?q?=E8=BD=AC=E6=81=92=E8=BF=94=20Symbol=20=E5=B9=B6=E4=BF=AE?= =?UTF-8?q?=E6=AD=A3=E8=BF=AD=E4=BB=A3=E5=99=A8=20name?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- crates/oxide_builtins/src/string/basic.rs | 6 +++-- crates/oxide_builtins/src/symbol.rs | 29 +++------------------ crates/oxide_runtime_api/src/coercion.rs | 15 ++++++++--- crates/oxide_vm/src/bindings/bind_string.rs | 5 ++-- 4 files changed, 21 insertions(+), 34 deletions(-) diff --git a/crates/oxide_builtins/src/string/basic.rs b/crates/oxide_builtins/src/string/basic.rs index deffd7b5..7de9e1f3 100644 --- a/crates/oxide_builtins/src/string/basic.rs +++ b/crates/oxide_builtins/src/string/basic.rs @@ -137,12 +137,14 @@ pub fn string_constructor(vm: &mut H, args: &[u8]) -> NativeResult { let v = oxide_runtime_api::to_string_for_string_constructor(v, vm); match v { Ok(s) => vm.new_string_owned(s), - Err(_) => { + Err(msg) => { // ToString on an object may throw via toString/valueOf; propagate the original exception. if let Some(exc) = vm.take_uncaught_value() { return NativeResult::Err(exc); } - return NativeResult::Err(crate::error::create_type_error(vm, "Cannot convert value to a string")); + // 无在途异常时按格式化文本恢复 kind 与消息(装箱 Symbol 走 ToString + // 抛 TypeError,消息须与原始异常一致)。 + return NativeResult::Err(crate::error::create_from_text(vm, &msg)); } } } else { diff --git a/crates/oxide_builtins/src/symbol.rs b/crates/oxide_builtins/src/symbol.rs index f86b1be5..626ae43f 100644 --- a/crates/oxide_builtins/src/symbol.rs +++ b/crates/oxide_builtins/src/symbol.rs @@ -95,41 +95,18 @@ pub fn symbol_to_string(vm: &mut H, args: &[u8]) -> NativeResult { NativeResult::Ok(vm.new_string_owned(result)) } -/// `Symbol.prototype[Symbol.toPrimitive](hint)`:thisSymbolValue 校验后按 -/// hint 返回 Symbol 或其描述串。 +/// `Symbol.prototype[Symbol.toPrimitive](hint)`:thisSymbolValue 校验后忽略 +/// hint,恒返回 Symbol 本体(规范 ThisSymbolValue,不转描述串、不触发 hint 转换)。 /// /// # 步骤 /// 1. this 非 Symbol 或 Symbol 包装对象 → TypeError。 -/// 2. hint 缺省 → 返回 Symbol。 -/// 3. hint 做完整 ToString(异常传播);结果串为 "string" → 返回 -/// `Symbol(description)` 描述串,其余值(含 "number")→ 返回 Symbol。 +/// 2. 返回 Symbol(hint 缺省与否均忽略)。 pub fn symbol_to_primitive(vm: &mut H, args: &[u8]) -> NativeResult { let this_val = vm.reg(args[0]); let sym = match this_symbol_value(vm, this_val) { Ok(v) => v, Err(e) => return NativeResult::Err(e), }; - if args.len() <= 1 { - return NativeResult::Ok(sym); - } - let hint = vm.reg(args[1]); - if hint.is_undefined() { - return NativeResult::Ok(sym); - } - let hint_str = match oxide_runtime_api::to_string_full(hint, vm) { - Ok(s) => s, - Err(_) => { - if let Some(exc) = vm.take_uncaught_value() { - return NativeResult::Err(exc); - } - return NativeResult::Err(crate::error::create_type_error(vm, "Cannot convert value to a string")); - } - }; - if hint_str == "string" { - let idx = sym.as_symbol_index(); - let desc = vm.symbol_description(idx).unwrap_or("").to_string(); - return NativeResult::Ok(vm.new_string_owned(format!("Symbol({})", desc))); - } NativeResult::Ok(sym) } diff --git a/crates/oxide_runtime_api/src/coercion.rs b/crates/oxide_runtime_api/src/coercion.rs index d9d0044e..3dab2a15 100644 --- a/crates/oxide_runtime_api/src/coercion.rs +++ b/crates/oxide_runtime_api/src/coercion.rs @@ -977,8 +977,10 @@ fn string_to_bigint_full(host: &mut H, s: &str) -> Result(val: JsValue, host: &mut H) -> Result { if val.is_object() { if let Some(id) = well_known_symbol_id(host, val.as_js_object_ptr()) { @@ -987,10 +989,15 @@ pub fn to_string_for_string_constructor(val: JsValue, host: &mut H) - } } } + // 原始 Symbol:步骤 2a,SymbolDescriptiveString(不经 ToString)。 + if val.is_symbol() { + let desc = host.symbol_description(val.as_symbol_index()).unwrap_or(""); + return Ok(format!("Symbol({desc})")); + } + // 步骤 3:ToString。装箱 Symbol 经 ToPrimitive 得 Symbol 本体,ToString 抛 TypeError。 let primitive = to_primitive(val, ToPrimitiveHint::String, host)?; if primitive.is_symbol() { - let desc = host.symbol_description(primitive.as_symbol_index()).unwrap_or(""); - return Ok(format!("Symbol({desc})")); + return Err(host.error_message_text("TypeError", "Cannot convert a Symbol value to a string")); } Ok(to_string(primitive)) } diff --git a/crates/oxide_vm/src/bindings/bind_string.rs b/crates/oxide_vm/src/bindings/bind_string.rs index 6e5b9146..175fcb10 100644 --- a/crates/oxide_vm/src/bindings/bind_string.rs +++ b/crates/oxide_vm/src/bindings/bind_string.rs @@ -85,13 +85,14 @@ pub fn bind_string(core: &Arc, session: &KernelSession, global: &mut core, &[("toString", oxide_builtins::string::string_to_string:: as *const (), 0)], ); - // String.prototype[@@iterator]:逐 code point 迭代字符。 + // String.prototype[@@iterator]:逐 code point 迭代字符;name 属性按规范 + // 落 "[Symbol.iterator]"。 super::bind_well_known_method( session.builtin_world(), core, proto, 0, - "iterator", + "[Symbol.iterator]", oxide_builtins::string::string_symbol_iterator:: as *const (), 0, );