From 7457740c362bfc4911fb2e606e7110c1bf16db95 Mon Sep 17 00:00:00 2001 From: pjh456 <147148383@qq.com> Date: Wed, 23 Sep 2026 12:44:00 +0000 Subject: [PATCH] =?UTF-8?q?fix:=20Number=20=E5=AD=97=E7=AC=A6=E4=B8=B2?= =?UTF-8?q?=E9=A6=96=E5=B0=BE=E7=A9=BA=E7=99=BD=E8=A1=A5=20U+FEFF=20?= =?UTF-8?q?=E5=AF=B9=E9=BD=90=20ES=20=E7=A9=BA=E7=99=BD=E9=9B=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- crates/oxide_runtime_api/src/coercion.rs | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/crates/oxide_runtime_api/src/coercion.rs b/crates/oxide_runtime_api/src/coercion.rs index bd30486a..cc13f32e 100644 --- a/crates/oxide_runtime_api/src/coercion.rs +++ b/crates/oxide_runtime_api/src/coercion.rs @@ -125,11 +125,13 @@ pub fn to_number(val: JsValue) -> f64 { /// 需先按十进制字符集排除这些令牌(JS 只接受精确的 "Infinity")。 /// /// # 边界与前提 -/// - trim 后空串 → 0 +/// - 首尾空白(Unicode White_Space 并 BOM U+FEFF,即 StringNumericLiteral +/// 的 WhiteSpace 集)trim 后空串 → 0 /// - 十六/八/二进制要求全部字符为有效数字,含非法字符 → NaN /// - 十进制结果与 Rust parse 一致,溢出时归 ±inf / 0 fn parse_js_number(s: &str) -> f64 { - let t = s.trim(); + // Rust trim 的 White_Space 不含 U+FEFF,按 ES 空白集显式补齐。 + let t = s.trim_matches(|c: char| c.is_whitespace() || c == '\u{FEFF}'); if t.is_empty() { return 0.0; } @@ -1049,4 +1051,17 @@ mod tests { assert_eq!(parse_js_number("-0"), -0.0); assert!(parse_js_number("1abc").is_nan()); } + + #[test] + fn parse_js_number_es_whitespace_set() { + // StringNumericLiteral 的 WhiteSpace 集 = Unicode White_Space 并 BOM + // U+FEFF:首尾均容忍,数字内部空白仍 NaN。 + let ws = "\t\u{000B}\u{000C}\u{FEFF}\u{3000}\n\r\u{2028}\u{2029} "; + assert_eq!(parse_js_number(&format!("{ws}0{ws}")), 0.0); + assert_eq!(parse_js_number(&format!("{ws}1{ws}")), 1.0); + assert_eq!(parse_js_number("\u{FEFF}0"), 0.0); + assert_eq!(parse_js_number("0\u{FEFF}"), 0.0); + assert_eq!(parse_js_number("\u{FEFF}"), 0.0); + assert!(parse_js_number("1\u{FEFF}2").is_nan()); + } }