mirror of
https://github.com/oxc-project/oxc.git
synced 2026-11-04 10:29:58 +00:00
refactor(ecmascript): add ToUint32 trait (#13272)
Added `ToUint32` trait that corresponds to the [`ToUint32` abstract operation](https://tc39.es/ecma262/multipage/abstract-operations.html#sec-touint32).
This commit is contained in:
5 files changed
+38
-20
No files matched your search
@@ -20,7 +20,7 @@ use oxc_ast::{AstBuilder, ast::*};
|
||||
use equality_comparison::{abstract_equality_comparison, strict_equality_comparison};
|
||||
|
||||
use crate::{
|
||||
ToBigInt, ToBoolean, ToInt32, ToJsString as ToJsStringTrait, ToNumber,
|
||||
ToBigInt, ToBoolean, ToInt32, ToJsString as ToJsStringTrait, ToNumber, ToUint32,
|
||||
is_less_than::is_less_than,
|
||||
side_effects::{MayHaveSideEffects, MayHaveSideEffectsContext},
|
||||
to_numeric::ToNumeric,
|
||||
@@ -265,29 +265,26 @@ fn binary_operation_evaluate_value_to<'a>(
|
||||
}
|
||||
Some(ConstantValue::Number(result))
|
||||
}
|
||||
#[expect(clippy::cast_sign_loss)]
|
||||
BinaryOperator::ShiftLeft => {
|
||||
let left = left.evaluate_value_to_number(ctx)?;
|
||||
let right = right.evaluate_value_to_number(ctx)?;
|
||||
let left = left.to_int_32();
|
||||
let right = (right.to_int_32() as u32) & 31;
|
||||
let right = right.to_uint_32() & 31;
|
||||
Some(ConstantValue::Number(f64::from(left << right)))
|
||||
}
|
||||
#[expect(clippy::cast_sign_loss)]
|
||||
BinaryOperator::ShiftRight => {
|
||||
let left = left.evaluate_value_to_number(ctx)?;
|
||||
let right = right.evaluate_value_to_number(ctx)?;
|
||||
let left = left.to_int_32();
|
||||
let right = (right.to_int_32() as u32) & 31;
|
||||
let right = right.to_uint_32() & 31;
|
||||
Some(ConstantValue::Number(f64::from(left >> right)))
|
||||
}
|
||||
#[expect(clippy::cast_sign_loss)]
|
||||
BinaryOperator::ShiftRightZeroFill => {
|
||||
let left = left.evaluate_value_to_number(ctx)?;
|
||||
let right = right.evaluate_value_to_number(ctx)?;
|
||||
let left = left.to_int_32();
|
||||
let right = (right.to_int_32() as u32) & 31;
|
||||
Some(ConstantValue::Number(f64::from((left as u32) >> right)))
|
||||
let left = left.to_uint_32();
|
||||
let right = right.to_uint_32() & 31;
|
||||
Some(ConstantValue::Number(f64::from(left >> right)))
|
||||
}
|
||||
BinaryOperator::LessThan => is_less_than(ctx, left, right).map(|value| match value {
|
||||
ConstantValue::Undefined => ConstantValue::Boolean(false),
|
||||
|
||||
@@ -48,7 +48,7 @@ pub use self::{
|
||||
string_to_number::StringToNumber,
|
||||
to_big_int::ToBigInt,
|
||||
to_boolean::ToBoolean,
|
||||
to_int_32::ToInt32,
|
||||
to_int_32::{ToInt32, ToUint32},
|
||||
to_integer_index::ToIntegerIndex,
|
||||
to_number::ToNumber,
|
||||
to_primitive::ToPrimitive,
|
||||
|
||||
@@ -7,6 +7,13 @@ pub trait ToInt32 {
|
||||
fn to_int_32(&self) -> i32;
|
||||
}
|
||||
|
||||
pub trait ToUint32: ToInt32 {
|
||||
fn to_uint_32(&self) -> u32 {
|
||||
self.to_int_32().cast_unsigned()
|
||||
}
|
||||
}
|
||||
impl<T> ToUint32 for T where T: ToInt32 {}
|
||||
|
||||
impl ToInt32 for f64 {
|
||||
fn to_int_32(&self) -> i32 {
|
||||
#[cfg(all(target_arch = "aarch64", target_os = "macos"))]
|
||||
@@ -191,4 +198,20 @@ mod test {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[expect(clippy::cast_precision_loss)]
|
||||
fn f64_to_uint32_conversion() {
|
||||
assert_eq!(0.0_f64.to_uint_32(), 0);
|
||||
assert_eq!((-0.0_f64).to_uint_32(), 0);
|
||||
assert_eq!(f64::NAN.to_uint_32(), 0);
|
||||
assert_eq!(f64::INFINITY.to_uint_32(), 0);
|
||||
assert_eq!(f64::NEG_INFINITY.to_uint_32(), 0);
|
||||
assert_eq!(((i64::from(u32::MAX) + 1) as f64).to_uint_32(), u32::MIN);
|
||||
assert_eq!(((i64::from(u32::MIN) - 1) as f64).to_uint_32(), u32::MAX);
|
||||
|
||||
// Test edge cases with maximum safe integers
|
||||
assert_eq!((9_007_199_254_740_992.0_f64).to_uint_32(), 0); // 2^53
|
||||
assert_eq!((-9_007_199_254_740_992.0_f64).to_uint_32(), 0); // -2^53
|
||||
}
|
||||
}
|
||||
@@ -2,7 +2,7 @@ use rustc_hash::FxHashMap;
|
||||
|
||||
use oxc_allocator::CloneIn;
|
||||
use oxc_ast::ast::*;
|
||||
use oxc_ecmascript::ToInt32;
|
||||
use oxc_ecmascript::{ToInt32, ToUint32};
|
||||
use oxc_span::{Atom, GetSpan, SPAN};
|
||||
use oxc_syntax::{
|
||||
number::{NumberBase, ToJsString},
|
||||
@@ -204,16 +204,15 @@ impl<'a> IsolatedDeclarations<'a> {
|
||||
ConstantValue::String(_) => return None,
|
||||
};
|
||||
|
||||
#[expect(clippy::cast_sign_loss)]
|
||||
match expr.operator {
|
||||
BinaryOperator::ShiftRight => Some(ConstantValue::Number(f64::from(
|
||||
left.to_int_32().wrapping_shr(right.to_int_32() as u32),
|
||||
left.to_int_32().wrapping_shr(right.to_uint_32()),
|
||||
))),
|
||||
BinaryOperator::ShiftRightZeroFill => Some(ConstantValue::Number(f64::from(
|
||||
(left.to_int_32() as u32).wrapping_shr(right.to_int_32() as u32),
|
||||
(left.to_uint_32()).wrapping_shr(right.to_uint_32()),
|
||||
))),
|
||||
BinaryOperator::ShiftLeft => Some(ConstantValue::Number(f64::from(
|
||||
left.to_int_32().wrapping_shl(right.to_int_32() as u32),
|
||||
left.to_int_32().wrapping_shl(right.to_uint_32()),
|
||||
))),
|
||||
BinaryOperator::BitwiseXOR => {
|
||||
Some(ConstantValue::Number(f64::from(left.to_int_32() ^ right.to_int_32())))
|
||||
|
||||
@@ -6,7 +6,7 @@ use oxc_allocator::{StringBuilder, TakeIn, Vec as ArenaVec};
|
||||
use oxc_ast::{NONE, ast::*};
|
||||
use oxc_ast_visit::{VisitMut, walk_mut};
|
||||
use oxc_data_structures::stack::NonEmptyStack;
|
||||
use oxc_ecmascript::ToInt32;
|
||||
use oxc_ecmascript::{ToInt32, ToUint32};
|
||||
use oxc_semantic::{ScopeFlags, ScopeId};
|
||||
use oxc_span::{Atom, SPAN, Span};
|
||||
use oxc_syntax::{
|
||||
@@ -444,7 +444,6 @@ impl<'a> TypeScriptEnum<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
#[expect(clippy::cast_sign_loss)]
|
||||
fn eval_binary_expression(
|
||||
&self,
|
||||
expr: &BinaryExpression<'a>,
|
||||
@@ -485,13 +484,13 @@ impl<'a> TypeScriptEnum<'a> {
|
||||
|
||||
match expr.operator {
|
||||
BinaryOperator::ShiftRight => Some(ConstantValue::Number(f64::from(
|
||||
left.to_int_32().wrapping_shr(right.to_int_32() as u32),
|
||||
left.to_int_32().wrapping_shr(right.to_uint_32()),
|
||||
))),
|
||||
BinaryOperator::ShiftRightZeroFill => Some(ConstantValue::Number(f64::from(
|
||||
(left.to_int_32() as u32).wrapping_shr(right.to_int_32() as u32),
|
||||
(left.to_uint_32()).wrapping_shr(right.to_uint_32()),
|
||||
))),
|
||||
BinaryOperator::ShiftLeft => Some(ConstantValue::Number(f64::from(
|
||||
left.to_int_32().wrapping_shl(right.to_int_32() as u32),
|
||||
left.to_int_32().wrapping_shl(right.to_uint_32()),
|
||||
))),
|
||||
BinaryOperator::BitwiseXOR => {
|
||||
Some(ConstantValue::Number(f64::from(left.to_int_32() ^ right.to_int_32())))
|
||||
|
||||
Reference in new issue
Block a user