From 442bc606e253474d474afd388fcca2b085663301 Mon Sep 17 00:00:00 2001 From: Hans Larsen Date: Mon, 16 Dec 2024 13:08:10 -0800 Subject: [PATCH] Fix tests and test262 on 32 and 64 bits platforms --- core/engine/src/builtins/array/mod.rs | 4 ++++ core/engine/src/builtins/regexp/mod.rs | 2 +- core/engine/src/builtins/string/mod.rs | 18 ++++++++++-------- core/engine/src/value/integer.rs | 8 +++++--- core/engine/src/value/tests.rs | 4 ++-- 5 files changed, 22 insertions(+), 14 deletions(-) diff --git a/core/engine/src/builtins/array/mod.rs b/core/engine/src/builtins/array/mod.rs index 4f0f109f12a..efc5d592e90 100644 --- a/core/engine/src/builtins/array/mod.rs +++ b/core/engine/src/builtins/array/mod.rs @@ -3199,10 +3199,12 @@ impl Array { // 2. If relativeStart is -∞, let k be 0. IntegerOrInfinity::NegativeInfinity => 0, // 3. Else if relativeStart < 0, let k be max(len + relativeStart, 0). + IntegerOrInfinity::Integer(i) if i <= (isize::MIN as i64) => 0, IntegerOrInfinity::Integer(i) if i < 0 => { len.checked_add_signed(i as isize).unwrap_or(0) } // 4. Else, let k be min(relativeStart, len). + IntegerOrInfinity::Integer(i) if i as u64 > usize::MAX as u64 => len, IntegerOrInfinity::Integer(i) => min(i as usize, len), // Special case - positive infinity. `len` is always smaller than +inf, thus from (4) @@ -3228,11 +3230,13 @@ impl Array { // 2. If relativeEnd is -∞, let final be 0. IntegerOrInfinity::NegativeInfinity => 0, // 3. Else if relativeEnd < 0, let final be max(len + relativeEnd, 0). + IntegerOrInfinity::Integer(i) if i < 0 && i <= isize::MIN as i64 => 0, IntegerOrInfinity::Integer(i) if i < 0 => { len.checked_add_signed(i as isize).unwrap_or(0) } // 4. Else, let final be min(relativeEnd, len). // Both `as` casts are safe as both variables are non-negative + IntegerOrInfinity::Integer(i) if i as u64 >= usize::MAX as u64 => len, IntegerOrInfinity::Integer(i) => min(i as usize, len), // Special case - positive infinity. `len` is always smaller than +inf, thus from (4) diff --git a/core/engine/src/builtins/regexp/mod.rs b/core/engine/src/builtins/regexp/mod.rs index ba1bd30fe85..a54ed6c784a 100644 --- a/core/engine/src/builtins/regexp/mod.rs +++ b/core/engine/src/builtins/regexp/mod.rs @@ -1537,7 +1537,7 @@ impl RegExp { .to_integer_or_infinity(context)?; // f. Set position to the result of clamping position between 0 and lengthS. - let position = position.clamp_finite(0, length_s as i64) as usize; + let position = position.clamp_finite(0, length_s); // g. Let captures be a new empty List. let mut captures = Vec::new(); diff --git a/core/engine/src/builtins/string/mod.rs b/core/engine/src/builtins/string/mod.rs index b09ebca9dd8..10c73ad70af 100644 --- a/core/engine/src/builtins/string/mod.rs +++ b/core/engine/src/builtins/string/mod.rs @@ -710,7 +710,9 @@ impl String { // 3. Let n be ? ToIntegerOrInfinity(count). match args.get_or_undefined(0).to_integer_or_infinity(context)? { IntegerOrInfinity::Integer(n) - if n > 0 && (n as usize) * len <= Self::MAX_STRING_LENGTH => + if n > 0 + && usize::try_from(n).is_ok() + && (n as usize) * len <= Self::MAX_STRING_LENGTH => { if string.is_empty() { return Ok(js_string!().into()); @@ -837,7 +839,7 @@ impl String { let search_string = search_string.to_string(context)?; // 6. Let len be the length of S. - let len = string.len() as i64; + let len = string.len(); // 7. If position is undefined, let pos be 0; else let pos be ? ToIntegerOrInfinity(position). let pos = match args.get_or_undefined(1) { @@ -846,7 +848,7 @@ impl String { }; // 8. Let start be the result of clamping pos between 0 and len. - let start = pos.clamp_finite(0, len) as usize; + let start = pos.clamp_finite(0, len); // 9. Let searchLength be the length of searchStr. let search_length = search_string.len(); @@ -857,10 +859,10 @@ impl String { } // 11. Let end be start + searchLength. - let end = start + search_length; + let end = start.saturating_add(search_length); // 12. If end > len, return false. - if end > len as usize { + if end > len { Ok(JsValue::new(false)) } else { // 13. Let substring be the substring of S from start to end. @@ -905,16 +907,16 @@ impl String { }; // 6. Let len be the length of S. - let len = string.len() as i64; + let len = string.len(); // 7. If endPosition is undefined, let pos be len; else let pos be ? ToIntegerOrInfinity(endPosition). let end = match args.get_or_undefined(1) { - end_position if end_position.is_undefined() => IntegerOrInfinity::Integer(len), + end_position if end_position.is_undefined() => IntegerOrInfinity::Integer(len as i64), end_position => end_position.to_integer_or_infinity(context)?, }; // 8. Let end be the result of clamping pos between 0 and len. - let end = end.clamp_finite(0, len) as usize; + let end = end.clamp_finite(0, len); // 9. Let searchLength be the length of searchStr. let search_length = search_str.len(); diff --git a/core/engine/src/value/integer.rs b/core/engine/src/value/integer.rs index 9c2d84e5bf5..6bbccfe2978 100644 --- a/core/engine/src/value/integer.rs +++ b/core/engine/src/value/integer.rs @@ -1,3 +1,4 @@ +use num_traits::{AsPrimitive, FromPrimitive}; use std::cmp::Ordering; /// Represents the result of the `ToIntegerOrInfinity` operation @@ -21,10 +22,11 @@ impl IntegerOrInfinity { /// /// Panics if `min > max`. #[must_use] - pub fn clamp_finite(self, min: i64, max: i64) -> i64 { - assert!(min <= max); + pub fn clamp_finite + FromPrimitive>(self, min: T, max: T) -> T { match self { - Self::Integer(i) => i.clamp(min, max), + Self::Integer(i) => { + T::from_i64(i.clamp(min.as_(), max.as_())).expect("`i` should already be clamped") + } Self::PositiveInfinity => max, Self::NegativeInfinity => min, } diff --git a/core/engine/src/value/tests.rs b/core/engine/src/value/tests.rs index 06375deb620..0a84f7cf00b 100644 --- a/core/engine/src/value/tests.rs +++ b/core/engine/src/value/tests.rs @@ -560,8 +560,8 @@ fn to_length() { assert_eq!(JsValue::new(20.9).to_length(ctx).unwrap(), 20); assert_eq!(JsValue::new(-20.9).to_length(ctx).unwrap(), 0); assert_eq!( - JsValue::new(100_000_000_000.0).to_length(ctx).unwrap(), - 100_000_000_000 + JsValue::new(100_000_000.0).to_length(ctx).unwrap(), + 100_000_000 ); assert_eq!( JsValue::new(4_010_101_101.0).to_length(ctx).unwrap(),