From 7ba5da9513486342a034aefbb846d9d13137983a Mon Sep 17 00:00:00 2001 From: pjh456 <147148383@qq.com> Date: Sat, 27 Jun 2026 13:49:37 +0800 Subject: [PATCH] =?UTF-8?q?refactor:=20=E7=94=A8=E6=88=B7=E6=95=B0?= =?UTF-8?q?=E5=AD=97=E5=8F=82=E6=95=B0=E6=94=B9=E8=B5=B0=20coerce=5Fnumber?= =?UTF-8?q?=5Fbounded=EF=BC=8C=E5=AF=B9=E8=B1=A1=E5=8F=82=E6=95=B0?= =?UTF-8?q?=E6=94=AF=E6=8C=81=20ToPrimitive?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- crates/oxide_builtins/src/array.rs | 24 ++++++++-------- crates/oxide_builtins/src/array_buffer.rs | 6 ++-- crates/oxide_builtins/src/data_view.rs | 4 +-- crates/oxide_builtins/src/date.rs | 30 ++++++++++---------- crates/oxide_builtins/src/math.rs | 16 +++++------ crates/oxide_builtins/src/number.rs | 24 +++++++++------- crates/oxide_builtins/src/regexp.rs | 4 +-- crates/oxide_builtins/src/string.rs | 34 +++++++++++++---------- crates/oxide_builtins/src/typed_array.rs | 10 +++---- 9 files changed, 80 insertions(+), 72 deletions(-) diff --git a/crates/oxide_builtins/src/array.rs b/crates/oxide_builtins/src/array.rs index 8dd0ad19..608dac59 100644 --- a/crates/oxide_builtins/src/array.rs +++ b/crates/oxide_builtins/src/array.rs @@ -68,7 +68,7 @@ fn create_new_array(vm: &mut H, n: usize) -> *mut JsObject { } fn array_length_arg(vm: &mut H, value: JsValue) -> Result { - let n = oxide_runtime_api::to_number(value); + let n = vm.coerce_number_bounded(value).unwrap_or(f64::NAN); if !n.is_finite() || n < 0.0 || n.fract() != 0.0 || n > MAX_DENSE_PROPS as f64 { return Err(crate::error::create_range_error(vm, "Invalid array length")); } @@ -195,12 +195,12 @@ pub fn array_slice(vm: &mut H, args: &[u8]) -> NativeResult { let arr = unsafe { &*arr_ptr }; let n = arr.prop_count() as usize; let start = if args.len() > 1 { - (oxide_runtime_api::to_number(vm.reg(args[1])) as i32) as usize + (vm.coerce_number_bounded(vm.reg(args[1])).unwrap_or(f64::NAN) as i32) as usize } else { 0 }; let end = if args.len() > 2 { - (oxide_runtime_api::to_number(vm.reg(args[2])) as i32) as usize + (vm.coerce_number_bounded(vm.reg(args[2])).unwrap_or(f64::NAN) as i32) as usize } else { n }; @@ -225,7 +225,7 @@ pub fn array_splice(vm: &mut H, args: &[u8]) -> NativeResult { let n = arr.prop_count() as usize; let start = if args.len() > 1 { - let v = oxide_runtime_api::to_number(vm.reg(args[1])); + let v = vm.coerce_number_bounded(vm.reg(args[1])).unwrap_or(f64::NAN); let s = v as i32; if s < 0 { (n as i32 + s).max(0) as usize @@ -237,7 +237,7 @@ pub fn array_splice(vm: &mut H, args: &[u8]) -> NativeResult { }; let delete_count = if args.len() > 2 { - let v = oxide_runtime_api::to_number(vm.reg(args[2])); + let v = vm.coerce_number_bounded(vm.reg(args[2])).unwrap_or(f64::NAN); (v as usize).min(n - start) } else { n - start @@ -413,7 +413,7 @@ pub fn array_flat(vm: &mut H, args: &[u8]) -> NativeResult { let arr = unsafe { &*arr_ptr }; let n = arr.prop_count() as usize; let depth = if args.len() > 1 { - let n = oxide_runtime_api::to_number(vm.reg(args[1])); + let n = vm.coerce_number_bounded(vm.reg(args[1])).unwrap_or(f64::NAN); if !n.is_finite() { vm.kernel_core().config.max_call_depth } else { @@ -834,12 +834,12 @@ pub fn array_fill(vm: &mut H, args: &[u8]) -> NativeResult { let len = arr.prop_count() as usize; let value = if args.len() > 1 { vm.reg(args[1]) } else { JsValue::undefined() }; let start = if args.len() > 2 { - (oxide_runtime_api::to_number(vm.reg(args[2])) as i32).max(0) as usize + (vm.coerce_number_bounded(vm.reg(args[2])).unwrap_or(f64::NAN) as i32).max(0) as usize } else { 0 }; let end = if args.len() > 3 { - let e = oxide_runtime_api::to_number(vm.reg(args[3])) as i32; + let e = vm.coerce_number_bounded(vm.reg(args[3])).unwrap_or(f64::NAN) as i32; (e as usize).min(len) } else { len @@ -859,17 +859,17 @@ pub fn array_copy_within(vm: &mut H, args: &[u8]) -> NativeResult { return NativeResult::Ok(vm.reg(args[0])); } let target = if args.len() > 1 { - (oxide_runtime_api::to_number(vm.reg(args[1])) as i32) as usize + (vm.coerce_number_bounded(vm.reg(args[1])).unwrap_or(f64::NAN) as i32) as usize } else { 0 }; let start = if args.len() > 2 { - (oxide_runtime_api::to_number(vm.reg(args[2])) as i32) as usize + (vm.coerce_number_bounded(vm.reg(args[2])).unwrap_or(f64::NAN) as i32) as usize } else { 0 }; let end = if args.len() > 3 { - (oxide_runtime_api::to_number(vm.reg(args[3])) as i32 as usize).min(len) + (vm.coerce_number_bounded(vm.reg(args[3])).unwrap_or(f64::NAN) as i32 as usize).min(len) } else { len }; @@ -891,7 +891,7 @@ pub fn array_at(vm: &mut H, args: &[u8]) -> NativeResult { let arr = unsafe { &*arr_ptr }; let len = arr.prop_count() as i32; let mut index = if args.len() > 1 { - oxide_runtime_api::to_number(vm.reg(args[1])) as i32 + vm.coerce_number_bounded(vm.reg(args[1])).unwrap_or(f64::NAN) as i32 } else { 0 }; diff --git a/crates/oxide_builtins/src/array_buffer.rs b/crates/oxide_builtins/src/array_buffer.rs index 3b928bae..9edf406a 100644 --- a/crates/oxide_builtins/src/array_buffer.rs +++ b/crates/oxide_builtins/src/array_buffer.rs @@ -20,7 +20,7 @@ fn type_error(vm: &mut H, msg: &str) -> NativeResult { } fn to_index(vm: &mut H, value: JsValue) -> Result { - let n = oxide_runtime_api::to_number(value); + let n = vm.coerce_number_bounded(value).unwrap_or(f64::NAN); if n.is_nan() { return Ok(0); } @@ -30,8 +30,8 @@ fn to_index(vm: &mut H, value: JsValue) -> Result { Ok(n.trunc() as usize) } -fn normalize_index(_vm: &mut H, value: JsValue, len: usize) -> usize { - let n = oxide_runtime_api::to_number(value); +fn normalize_index(vm: &mut H, value: JsValue, len: usize) -> usize { + let n = vm.coerce_number_bounded(value).unwrap_or(f64::NAN); if n.is_nan() { return 0; } diff --git a/crates/oxide_builtins/src/data_view.rs b/crates/oxide_builtins/src/data_view.rs index 2550048e..5dbf63f5 100644 --- a/crates/oxide_builtins/src/data_view.rs +++ b/crates/oxide_builtins/src/data_view.rs @@ -23,7 +23,7 @@ macro_rules! native_try { } fn to_index(vm: &mut H, value: JsValue, msg: &str) -> Result { - let n = oxide_runtime_api::to_number(value); + let n = vm.coerce_number_bounded(value).unwrap_or(f64::NAN); if n.is_nan() { return Ok(0); } @@ -41,7 +41,7 @@ fn is_little_endian(vm: &mut H, args: &[u8], idx: usize) -> bool { fn numeric_arg(vm: &mut H, args: &[u8], idx: usize) -> f64 { args.get(idx) - .map(|reg| oxide_runtime_api::to_number(vm.reg(*reg))) + .map(|reg| vm.coerce_number_bounded(vm.reg(*reg)).unwrap_or(f64::NAN)) .unwrap_or(0.0) } diff --git a/crates/oxide_builtins/src/date.rs b/crates/oxide_builtins/src/date.rs index d8112c78..e130ac42 100644 --- a/crates/oxide_builtins/src/date.rs +++ b/crates/oxide_builtins/src/date.rs @@ -102,30 +102,30 @@ pub fn date_constructor(vm: &mut H, args: &[u8]) -> NativeResult { let timestamp = if args.len() < 2 { Utc::now().timestamp_millis() as f64 } else if args.len() > 2 { - let y = oxide_runtime_api::to_number(vm.reg(args[1])) as i32; - let m = oxide_runtime_api::to_number(vm.reg(args[2])) as u32; + let y = vm.coerce_number_bounded(vm.reg(args[1])).unwrap_or(f64::NAN) as i32; + let m = vm.coerce_number_bounded(vm.reg(args[2])).unwrap_or(f64::NAN) as u32; let d = if args.len() > 3 { - oxide_runtime_api::to_number(vm.reg(args[3])) as u32 + vm.coerce_number_bounded(vm.reg(args[3])).unwrap_or(f64::NAN) as u32 } else { 1 }; let h = if args.len() > 4 { - oxide_runtime_api::to_number(vm.reg(args[4])) as u32 + vm.coerce_number_bounded(vm.reg(args[4])).unwrap_or(f64::NAN) as u32 } else { 0 }; let min = if args.len() > 5 { - oxide_runtime_api::to_number(vm.reg(args[5])) as u32 + vm.coerce_number_bounded(vm.reg(args[5])).unwrap_or(f64::NAN) as u32 } else { 0 }; let sec = if args.len() > 6 { - oxide_runtime_api::to_number(vm.reg(args[6])) as u32 + vm.coerce_number_bounded(vm.reg(args[6])).unwrap_or(f64::NAN) as u32 } else { 0 }; let ms = if args.len() > 7 { - oxide_runtime_api::to_number(vm.reg(args[7])) as u32 + vm.coerce_number_bounded(vm.reg(args[7])).unwrap_or(f64::NAN) as u32 } else { 0 }; @@ -316,7 +316,7 @@ fn get_opt_arg(vm: &H, args: &[u8], idx: usize, default: u32) -> u32 pub fn date_set_time(vm: &mut H, args: &[u8]) -> NativeResult { let obj = unsafe { &mut *native_try!(date_this_mut(vm, args)) }; let val = if args.len() > 1 { - oxide_runtime_api::to_number(vm.reg(args[1])) + vm.coerce_number_bounded(vm.reg(args[1])).unwrap_or(f64::NAN) } else { f64::NAN }; @@ -326,7 +326,7 @@ pub fn date_set_time(vm: &mut H, args: &[u8]) -> NativeResult { pub fn date_set_full_year(vm: &mut H, args: &[u8]) -> NativeResult { let val = if args.len() > 1 { vm.reg(args[1]) } else { JsValue::undefined() }; - let v = oxide_runtime_api::to_number(val); + let v = vm.coerce_number_bounded(val).unwrap_or(f64::NAN); let obj = unsafe { &mut *native_try!(date_this_mut(vm, args)) }; let ms = get_timestamp(obj); if !ms.is_finite() { @@ -349,7 +349,7 @@ pub fn date_set_full_year(vm: &mut H, args: &[u8]) -> NativeResult { } pub fn date_set_month(vm: &mut H, args: &[u8]) -> NativeResult { let val = if args.len() > 1 { vm.reg(args[1]) } else { JsValue::undefined() }; - let v = oxide_runtime_api::to_number(val); + let v = vm.coerce_number_bounded(val).unwrap_or(f64::NAN); let obj = unsafe { &mut *native_try!(date_this_mut(vm, args)) }; let ms = get_timestamp(obj); if !ms.is_finite() { @@ -367,7 +367,7 @@ pub fn date_set_month(vm: &mut H, args: &[u8]) -> NativeResult { } pub fn date_set_date(vm: &mut H, args: &[u8]) -> NativeResult { let val = if args.len() > 1 { vm.reg(args[1]) } else { JsValue::undefined() }; - let v = oxide_runtime_api::to_number(val); + let v = vm.coerce_number_bounded(val).unwrap_or(f64::NAN); let obj = unsafe { &mut *native_try!(date_this_mut(vm, args)) }; let ms = get_timestamp(obj); if !ms.is_finite() { @@ -384,7 +384,7 @@ pub fn date_set_date(vm: &mut H, args: &[u8]) -> NativeResult { } pub fn date_set_hours(vm: &mut H, args: &[u8]) -> NativeResult { let val = if args.len() > 1 { vm.reg(args[1]) } else { JsValue::undefined() }; - let v = oxide_runtime_api::to_number(val); + let v = vm.coerce_number_bounded(val).unwrap_or(f64::NAN); let obj = unsafe { &mut *native_try!(date_this_mut(vm, args)) }; let ms = get_timestamp(obj); if !ms.is_finite() { @@ -409,7 +409,7 @@ pub fn date_set_hours(vm: &mut H, args: &[u8]) -> NativeResult { } pub fn date_set_minutes(vm: &mut H, args: &[u8]) -> NativeResult { let val = if args.len() > 1 { vm.reg(args[1]) } else { JsValue::undefined() }; - let v = oxide_runtime_api::to_number(val); + let v = vm.coerce_number_bounded(val).unwrap_or(f64::NAN); let obj = unsafe { &mut *native_try!(date_this_mut(vm, args)) }; let ms = get_timestamp(obj); if !ms.is_finite() { @@ -432,7 +432,7 @@ pub fn date_set_minutes(vm: &mut H, args: &[u8]) -> NativeResult { } pub fn date_set_seconds(vm: &mut H, args: &[u8]) -> NativeResult { let val = if args.len() > 1 { vm.reg(args[1]) } else { JsValue::undefined() }; - let v = oxide_runtime_api::to_number(val); + let v = vm.coerce_number_bounded(val).unwrap_or(f64::NAN); let obj = unsafe { &mut *native_try!(date_this_mut(vm, args)) }; let ms = get_timestamp(obj); if !ms.is_finite() { @@ -453,7 +453,7 @@ pub fn date_set_seconds(vm: &mut H, args: &[u8]) -> NativeResult { } pub fn date_set_milliseconds(vm: &mut H, args: &[u8]) -> NativeResult { let val = if args.len() > 1 { vm.reg(args[1]) } else { JsValue::undefined() }; - let v = oxide_runtime_api::to_number(val); + let v = vm.coerce_number_bounded(val).unwrap_or(f64::NAN); let obj = unsafe { &mut *native_try!(date_this_mut(vm, args)) }; let ms = get_timestamp(obj); if !ms.is_finite() { diff --git a/crates/oxide_builtins/src/math.rs b/crates/oxide_builtins/src/math.rs index 23866870..c48be7ed 100644 --- a/crates/oxide_builtins/src/math.rs +++ b/crates/oxide_builtins/src/math.rs @@ -2,11 +2,11 @@ use oxide_types::value::JsValue; use oxide_runtime_api::{NativeResult, VmHost}; -fn num(vm: &H, reg: u8) -> f64 { - oxide_runtime_api::to_number(vm.reg(reg)) +fn num(vm: &mut H, reg: u8) -> f64 { + vm.coerce_number_bounded(vm.reg(reg)).unwrap_or(f64::NAN) } -fn arg1(vm: &H, args: &[u8]) -> f64 { +fn arg1(vm: &mut H, args: &[u8]) -> f64 { if args.len() < 2 { f64::NAN } else { @@ -14,11 +14,11 @@ fn arg1(vm: &H, args: &[u8]) -> f64 { } } -fn arg2(vm: &H, args: &[u8]) -> (f64, f64) { - ( - if args.len() > 1 { num(vm, args[1]) } else { f64::NAN }, - if args.len() > 2 { num(vm, args[2]) } else { f64::NAN }, - ) +fn arg2(vm: &mut H, args: &[u8]) -> (f64, f64) { + // Sequenced (not a tuple literal) so the two coercions take &mut H one at a time. + let a = if args.len() > 1 { num(vm, args[1]) } else { f64::NAN }; + let b = if args.len() > 2 { num(vm, args[2]) } else { f64::NAN }; + (a, b) } pub fn math_abs(vm: &mut H, args: &[u8]) -> NativeResult { diff --git a/crates/oxide_builtins/src/number.rs b/crates/oxide_builtins/src/number.rs index fb0998a8..cdd01d1d 100644 --- a/crates/oxide_builtins/src/number.rs +++ b/crates/oxide_builtins/src/number.rs @@ -3,7 +3,11 @@ use oxide_types::value::JsValue; use oxide_runtime_api::{NativeResult, VmHost}; pub fn number_constructor(vm: &mut H, args: &[u8]) -> NativeResult { - let n = if args.len() > 1 { oxide_runtime_api::to_number(vm.reg(args[1])) } else { 0.0 }; + let n = if args.len() > 1 { + vm.coerce_number_bounded(vm.reg(args[1])).unwrap_or(f64::NAN) + } else { + 0.0 + }; let number_proto = vm.session().builtin_world().number_proto.as_ptr() as *mut oxide_types::object::JsObject; let is_ctor = if let Some(this_reg) = args.first().copied() { let this_val = vm.reg(this_reg); @@ -81,7 +85,7 @@ pub fn number_parse_int(vm: &mut H, args: &[u8]) -> NativeResult { } let radix = if args.len() > 2 { - let r = oxide_runtime_api::to_number(vm.reg(args[2])) as i32; + let r = vm.coerce_number_bounded(vm.reg(args[2])).unwrap_or(f64::NAN) as i32; if r == 0 { 10 } else { @@ -128,9 +132,9 @@ pub fn number_parse_float(vm: &mut H, args: &[u8]) -> NativeResult { } pub fn number_to_string(vm: &mut H, args: &[u8]) -> NativeResult { - let n = oxide_runtime_api::to_number(vm.reg(args[0])); + let n = vm.coerce_number_bounded(vm.reg(args[0])).unwrap_or(f64::NAN); let radix = if args.len() > 1 { - let r = oxide_runtime_api::to_number(vm.reg(args[1])) as u32; + let r = vm.coerce_number_bounded(vm.reg(args[1])).unwrap_or(f64::NAN) as u32; r.clamp(2, 36) } else { 10u32 @@ -179,9 +183,9 @@ pub fn number_to_string(vm: &mut H, args: &[u8]) -> NativeResult { } pub fn number_to_fixed(vm: &mut H, args: &[u8]) -> NativeResult { - let n = oxide_runtime_api::to_number(vm.reg(args[0])); + let n = vm.coerce_number_bounded(vm.reg(args[0])).unwrap_or(f64::NAN); let digits = if args.len() > 1 { - oxide_runtime_api::to_number(vm.reg(args[1])) as usize + vm.coerce_number_bounded(vm.reg(args[1])).unwrap_or(f64::NAN) as usize } else { 0usize } @@ -205,9 +209,9 @@ pub fn number_is_safe_integer(vm: &mut H, args: &[u8]) -> NativeResul } pub fn number_to_exponential(vm: &mut H, args: &[u8]) -> NativeResult { - let n = oxide_runtime_api::to_number(vm.reg(args[0])); + let n = vm.coerce_number_bounded(vm.reg(args[0])).unwrap_or(f64::NAN); let digits = if args.len() > 1 { - oxide_runtime_api::to_number(vm.reg(args[1])) as usize + vm.coerce_number_bounded(vm.reg(args[1])).unwrap_or(f64::NAN) as usize } else { 0usize } @@ -223,9 +227,9 @@ pub fn number_to_exponential(vm: &mut H, args: &[u8]) -> NativeResult } pub fn number_to_precision(vm: &mut H, args: &[u8]) -> NativeResult { - let n = oxide_runtime_api::to_number(vm.reg(args[0])); + let n = vm.coerce_number_bounded(vm.reg(args[0])).unwrap_or(f64::NAN); let precision = if args.len() > 1 { - oxide_runtime_api::to_number(vm.reg(args[1])) as usize + vm.coerce_number_bounded(vm.reg(args[1])).unwrap_or(f64::NAN) as usize } else { 0usize } diff --git a/crates/oxide_builtins/src/regexp.rs b/crates/oxide_builtins/src/regexp.rs index 948b2b98..60109278 100644 --- a/crates/oxide_builtins/src/regexp.rs +++ b/crates/oxide_builtins/src/regexp.rs @@ -148,7 +148,7 @@ pub fn regexp_test(vm: &mut H, args: &[u8]) -> NativeResult { // SAFETY: fn_ptr holds a Box pointer stored by regexp_constructor. let regex = unsafe { &*(fn_ptr.as_ptr() as *const regex::Regex) }; let haystack = oxide_runtime_api::to_string(vm.reg(if args.len() > 1 { args[1] } else { args[0] })); - let last_index = oxide_runtime_api::to_number(get_prop(re, 0)) as usize; + let last_index = vm.coerce_number_bounded(get_prop(re, 0)).unwrap_or(f64::NAN) as usize; let is_global = get_prop(re, 3).as_bool(); if is_global { @@ -181,7 +181,7 @@ pub fn regexp_exec(vm: &mut H, args: &[u8]) -> NativeResult { let (last_index, is_global) = { let re = unsafe { &*re_ptr }; - let li = oxide_runtime_api::to_number(get_prop(re, 0)) as usize; + let li = vm.coerce_number_bounded(get_prop(re, 0)).unwrap_or(f64::NAN) as usize; let g = get_prop(re, 3).as_bool(); (li, g) }; diff --git a/crates/oxide_builtins/src/string.rs b/crates/oxide_builtins/src/string.rs index 8d983496..44fd6e3a 100644 --- a/crates/oxide_builtins/src/string.rs +++ b/crates/oxide_builtins/src/string.rs @@ -171,7 +171,7 @@ pub fn string_index_of(vm: &mut H, args: &[u8]) -> NativeResult { } let search = as_string(vm, vm.reg(args[1])); let pos = if args.len() > 2 { - (oxide_runtime_api::to_number(vm.reg(args[2])) as usize).min(n) + (vm.coerce_number_bounded(vm.reg(args[2])).unwrap_or(f64::NAN) as usize).min(n) } else { 0 }; @@ -203,7 +203,7 @@ pub fn string_includes(vm: &mut H, args: &[u8]) -> NativeResult { } let search = as_string(vm, vm.reg(args[1])); let pos = if args.len() > 2 { - (oxide_runtime_api::to_number(vm.reg(args[2])) as usize).min(n) + (vm.coerce_number_bounded(vm.reg(args[2])).unwrap_or(f64::NAN) as usize).min(n) } else { 0 }; @@ -229,7 +229,7 @@ pub fn string_char_at(vm: &mut H, args: &[u8]) -> NativeResult { } return NativeResult::Ok(vm.new_string(&take_chars(&s, 1))); } - let idx = oxide_runtime_api::to_number(vm.reg(args[1])) as i32; + let idx = vm.coerce_number_bounded(vm.reg(args[1])).unwrap_or(f64::NAN) as i32; if idx < 0 || idx as usize >= char_len(&s) { return NativeResult::Ok(vm.new_string("")); } @@ -246,7 +246,7 @@ pub fn string_char_code_at(vm: &mut H, args: &[u8]) -> NativeResult { } return NativeResult::Ok(JsValue::int(s.chars().next().unwrap() as i32)); } - let idx = oxide_runtime_api::to_number(vm.reg(args[1])) as i32; + let idx = vm.coerce_number_bounded(vm.reg(args[1])).unwrap_or(f64::NAN) as i32; if idx < 0 || idx as usize >= char_len(&s) { return NativeResult::Ok(JsValue::float(f64::NAN)); } @@ -267,7 +267,7 @@ pub fn string_slice(vm: &mut H, args: &[u8]) -> NativeResult { let s = this_string(vm, args); let n = char_len(&s) as i32; let start = if args.len() > 1 { - let v = oxide_runtime_api::to_number(vm.reg(args[1])) as i32; + let v = vm.coerce_number_bounded(vm.reg(args[1])).unwrap_or(f64::NAN) as i32; if v < 0 { (n + v).max(0) } else { @@ -277,7 +277,7 @@ pub fn string_slice(vm: &mut H, args: &[u8]) -> NativeResult { 0 }; let end = if args.len() > 2 { - let v = oxide_runtime_api::to_number(vm.reg(args[2])) as i32; + let v = vm.coerce_number_bounded(vm.reg(args[2])).unwrap_or(f64::NAN) as i32; if v < 0 { (n + v).max(0) } else { @@ -297,12 +297,16 @@ pub fn string_substring(vm: &mut H, args: &[u8]) -> NativeResult { let s = this_string(vm, args); let n = char_len(&s) as i32; let mut start = if args.len() > 1 { - (oxide_runtime_api::to_number(vm.reg(args[1])) as i32).max(0).min(n) + (vm.coerce_number_bounded(vm.reg(args[1])).unwrap_or(f64::NAN) as i32) + .max(0) + .min(n) } else { 0 }; let mut end = if args.len() > 2 { - (oxide_runtime_api::to_number(vm.reg(args[2])) as i32).max(0).min(n) + (vm.coerce_number_bounded(vm.reg(args[2])).unwrap_or(f64::NAN) as i32) + .max(0) + .min(n) } else { n }; @@ -335,7 +339,7 @@ pub fn string_repeat(vm: &mut H, args: &[u8]) -> NativeResult { builtins_debug!("String.prototype.repeat called with {} args", args.len()); let s = this_string(vm, args); let n = if args.len() > 1 { - (oxide_runtime_api::to_number(vm.reg(args[1])) as usize).min(10000) + (vm.coerce_number_bounded(vm.reg(args[1])).unwrap_or(f64::NAN) as usize).min(10000) } else { 1 }; @@ -347,7 +351,7 @@ pub fn string_pad_start(vm: &mut H, args: &[u8]) -> NativeResult { let s = this_string(vm, args); let s_len = char_len(&s); let target = if args.len() > 1 { - oxide_runtime_api::to_number(vm.reg(args[1])) as usize + vm.coerce_number_bounded(vm.reg(args[1])).unwrap_or(f64::NAN) as usize } else { s_len }; @@ -372,7 +376,7 @@ pub fn string_pad_end(vm: &mut H, args: &[u8]) -> NativeResult { let s = this_string(vm, args); let s_len = char_len(&s); let target = if args.len() > 1 { - oxide_runtime_api::to_number(vm.reg(args[1])) as usize + vm.coerce_number_bounded(vm.reg(args[1])).unwrap_or(f64::NAN) as usize } else { s_len }; @@ -401,7 +405,7 @@ pub fn string_starts_with(vm: &mut H, args: &[u8]) -> NativeResult { } let search = as_string(vm, vm.reg(args[1])); let pos = if args.len() > 2 { - (oxide_runtime_api::to_number(vm.reg(args[2])) as usize).min(n) + (vm.coerce_number_bounded(vm.reg(args[2])).unwrap_or(f64::NAN) as usize).min(n) } else { 0 }; @@ -417,7 +421,7 @@ pub fn string_ends_with(vm: &mut H, args: &[u8]) -> NativeResult { } let search = as_string(vm, vm.reg(args[1])); let end_pos = if args.len() > 2 { - (oxide_runtime_api::to_number(vm.reg(args[2])) as usize).min(n) + (vm.coerce_number_bounded(vm.reg(args[2])).unwrap_or(f64::NAN) as usize).min(n) } else { n }; @@ -433,7 +437,7 @@ pub fn string_split(vm: &mut H, args: &[u8]) -> NativeResult { } let sep_val = vm.reg(args[1]); let limit = if args.len() > 2 { - oxide_runtime_api::to_number(vm.reg(args[2])) as usize + vm.coerce_number_bounded(vm.reg(args[2])).unwrap_or(f64::NAN) as usize } else { usize::MAX }; @@ -565,7 +569,7 @@ pub fn string_code_point_at(vm: &mut H, args: &[u8]) -> NativeResult builtins_debug!("String.prototype.codePointAt called with {} args", args.len()); let s = this_string(vm, args); let pos = if args.len() > 1 { - oxide_runtime_api::to_number(vm.reg(args[1])) as usize + vm.coerce_number_bounded(vm.reg(args[1])).unwrap_or(f64::NAN) as usize } else { 0 }; diff --git a/crates/oxide_builtins/src/typed_array.rs b/crates/oxide_builtins/src/typed_array.rs index bfc80dab..49d03a14 100644 --- a/crates/oxide_builtins/src/typed_array.rs +++ b/crates/oxide_builtins/src/typed_array.rs @@ -32,7 +32,7 @@ fn range_error(vm: &mut H, msg: &str) -> JsValue { } fn to_index(vm: &mut H, value: JsValue, msg: &str) -> Result { - let n = oxide_runtime_api::to_number(value); + let n = vm.coerce_number_bounded(value).unwrap_or(f64::NAN); if n.is_nan() { return Ok(0); } @@ -42,8 +42,8 @@ fn to_index(vm: &mut H, value: JsValue, msg: &str) -> Result(_vm: &mut H, value: JsValue, len: usize) -> usize { - let n = oxide_runtime_api::to_number(value); +fn normalize_index(vm: &mut H, value: JsValue, len: usize) -> usize { + let n = vm.coerce_number_bounded(value).unwrap_or(f64::NAN); if n.is_nan() { return 0; } @@ -235,8 +235,8 @@ fn read_element(kind: TypedArrayKind, bytes: &[u8], offset: usize) -> JsValue { } } -fn numeric_value(_vm: &mut H, value: JsValue) -> f64 { - oxide_runtime_api::to_number(value) +fn numeric_value(vm: &mut H, value: JsValue) -> f64 { + vm.coerce_number_bounded(value).unwrap_or(f64::NAN) } fn write_element(kind: TypedArrayKind, bytes: &mut [u8], offset: usize, value: f64) {