diff --git a/crates/oxc_ecmascript/CHANGELOG.md b/crates/oxc_ecmascript/CHANGELOG.md index b848e9561b8ee..1bb19d2a99415 100644 --- a/crates/oxc_ecmascript/CHANGELOG.md +++ b/crates/oxc_ecmascript/CHANGELOG.md @@ -73,7 +73,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0). ### 🚜 Refactor -- 5a46641 ecmascript: Move `get_constant_value_for_reference_id` to `IsGlobalReference` trait (#11810) (Boshen) +- 5a46641 ecmascript: Move `get_constant_value_for_reference_id` to `GlobalContext` trait (#11810) (Boshen) @@ -204,11 +204,11 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), - b164072 ecmascript: Extract to_numeric (#9111) (sapphi-red) - fc53cdd ecmascript: Generalize ToPrimitive (#9109) (sapphi-red) - d951390 ecmascript: Use value_type in to_primitive (#9108) (sapphi-red) -- 8f79012 ecmascript: Pass IsGlobalReference to DetermineValueType instead of extending it (#9107) (sapphi-red) +- 8f79012 ecmascript: Pass GlobalContext to DetermineValueType instead of extending it (#9107) (sapphi-red) - db1744c ecmascript: Remove "constant_evaluation" / "side_effects" features (#9114) (sapphi-red) - 329de94 ecmascript: Extract ToPrimitive (#9102) (sapphi-red) -- d670ec7 ecmascript: Pass IsGlobalReference to MayHaveSideEffects instead of extending it (#9101) (sapphi-red) -- f4e2d4e ecmascript: Allow IsGlobalReference to return None (#9100) (sapphi-red) +- d670ec7 ecmascript: Pass GlobalContext to MayHaveSideEffects instead of extending it (#9101) (sapphi-red) +- f4e2d4e ecmascript: Allow GlobalContext to return None (#9100) (sapphi-red) ## [0.49.0] - 2025-02-10 diff --git a/crates/oxc_ecmascript/src/array_join.rs b/crates/oxc_ecmascript/src/array_join.rs index ebc8d77b6f507..d33c8d6155a53 100644 --- a/crates/oxc_ecmascript/src/array_join.rs +++ b/crates/oxc_ecmascript/src/array_join.rs @@ -1,28 +1,16 @@ use oxc_ast::ast::*; -use crate::{ToJsString, is_global_reference::IsGlobalReference}; +use crate::{GlobalContext, ToJsString}; pub trait ArrayJoin<'a> { /// `Array.prototype.join ( separator )` /// - fn array_join( - &self, - is_global_reference: &impl IsGlobalReference<'a>, - separator: Option<&str>, - ) -> Option; + fn array_join(&self, ctx: &impl GlobalContext<'a>, separator: Option<&str>) -> Option; } impl<'a> ArrayJoin<'a> for ArrayExpression<'a> { - fn array_join( - &self, - is_global_reference: &impl IsGlobalReference<'a>, - separator: Option<&str>, - ) -> Option { - let strings = self - .elements - .iter() - .map(|e| e.to_js_string(is_global_reference)) - .collect::>>(); + fn array_join(&self, ctx: &impl GlobalContext<'a>, separator: Option<&str>) -> Option { + let strings = self.elements.iter().map(|e| e.to_js_string(ctx)).collect::>>(); strings .map(|v| v.iter().map(AsRef::as_ref).collect::>().join(separator.unwrap_or(","))) } diff --git a/crates/oxc_ecmascript/src/constant_evaluation/is_int32_or_uint32.rs b/crates/oxc_ecmascript/src/constant_evaluation/is_int32_or_uint32.rs index 614ab7d1a190c..d8e027a0998b5 100644 --- a/crates/oxc_ecmascript/src/constant_evaluation/is_int32_or_uint32.rs +++ b/crates/oxc_ecmascript/src/constant_evaluation/is_int32_or_uint32.rs @@ -1,7 +1,7 @@ use num_traits::ToPrimitive; use oxc_ast::ast::*; -use crate::is_global_reference::IsGlobalReference; +use crate::GlobalContext; use super::DetermineValueType; @@ -13,56 +13,53 @@ pub trait IsInt32OrUint32<'a> { /// - false means it is neither int32 nor uint32, or it is unknown. /// /// Based on - fn is_int32_or_uint32(&self, is_global_reference: &impl IsGlobalReference<'a>) -> bool; + fn is_int32_or_uint32(&self, ctx: &impl GlobalContext<'a>) -> bool; } impl<'a> IsInt32OrUint32<'a> for Expression<'a> { - fn is_int32_or_uint32(&self, is_global_reference: &impl IsGlobalReference<'a>) -> bool { + fn is_int32_or_uint32(&self, ctx: &impl GlobalContext<'a>) -> bool { match self { - Expression::NumericLiteral(n) => n.is_int32_or_uint32(is_global_reference), - Expression::UnaryExpression(e) => e.is_int32_or_uint32(is_global_reference), - Expression::BinaryExpression(e) => e.is_int32_or_uint32(is_global_reference), - Expression::LogicalExpression(e) => e.is_int32_or_uint32(is_global_reference), + Expression::NumericLiteral(n) => n.is_int32_or_uint32(ctx), + Expression::UnaryExpression(e) => e.is_int32_or_uint32(ctx), + Expression::BinaryExpression(e) => e.is_int32_or_uint32(ctx), + Expression::LogicalExpression(e) => e.is_int32_or_uint32(ctx), Expression::ConditionalExpression(e) => { - e.consequent.is_int32_or_uint32(is_global_reference) - && e.alternate.is_int32_or_uint32(is_global_reference) + e.consequent.is_int32_or_uint32(ctx) && e.alternate.is_int32_or_uint32(ctx) } Expression::SequenceExpression(e) => { - e.expressions.last().is_some_and(|e| e.is_int32_or_uint32(is_global_reference)) - } - Expression::ParenthesizedExpression(e) => { - e.expression.is_int32_or_uint32(is_global_reference) + e.expressions.last().is_some_and(|e| e.is_int32_or_uint32(ctx)) } + Expression::ParenthesizedExpression(e) => e.expression.is_int32_or_uint32(ctx), _ => false, } } } impl<'a> IsInt32OrUint32<'a> for NumericLiteral<'a> { - fn is_int32_or_uint32(&self, _is_global_reference: &impl IsGlobalReference<'a>) -> bool { + fn is_int32_or_uint32(&self, _ctx: &impl GlobalContext<'a>) -> bool { self.value.fract() == 0.0 && (self.value.to_i32().is_some() || self.value.to_u32().is_some()) } } impl<'a> IsInt32OrUint32<'a> for UnaryExpression<'a> { - fn is_int32_or_uint32(&self, is_global_reference: &impl IsGlobalReference<'a>) -> bool { + fn is_int32_or_uint32(&self, ctx: &impl GlobalContext<'a>) -> bool { match self.operator { - UnaryOperator::BitwiseNot => self.value_type(is_global_reference).is_number(), - UnaryOperator::UnaryPlus => self.argument.is_int32_or_uint32(is_global_reference), + UnaryOperator::BitwiseNot => self.value_type(ctx).is_number(), + UnaryOperator::UnaryPlus => self.argument.is_int32_or_uint32(ctx), _ => false, } } } impl<'a> IsInt32OrUint32<'a> for BinaryExpression<'a> { - fn is_int32_or_uint32(&self, is_global_reference: &impl IsGlobalReference<'a>) -> bool { + fn is_int32_or_uint32(&self, ctx: &impl GlobalContext<'a>) -> bool { match self.operator { BinaryOperator::ShiftLeft | BinaryOperator::ShiftRight | BinaryOperator::BitwiseAnd | BinaryOperator::BitwiseOR - | BinaryOperator::BitwiseXOR => self.value_type(is_global_reference).is_number(), + | BinaryOperator::BitwiseXOR => self.value_type(ctx).is_number(), BinaryOperator::ShiftRightZeroFill => true, _ => false, } @@ -70,13 +67,12 @@ impl<'a> IsInt32OrUint32<'a> for BinaryExpression<'a> { } impl<'a> IsInt32OrUint32<'a> for LogicalExpression<'a> { - fn is_int32_or_uint32(&self, is_global_reference: &impl IsGlobalReference<'a>) -> bool { + fn is_int32_or_uint32(&self, ctx: &impl GlobalContext<'a>) -> bool { match self.operator { LogicalOperator::And | LogicalOperator::Or => { - self.left.is_int32_or_uint32(is_global_reference) - && self.right.is_int32_or_uint32(is_global_reference) + self.left.is_int32_or_uint32(ctx) && self.right.is_int32_or_uint32(ctx) } - LogicalOperator::Coalesce => self.left.is_int32_or_uint32(is_global_reference), + LogicalOperator::Coalesce => self.left.is_int32_or_uint32(ctx), } } } diff --git a/crates/oxc_ecmascript/src/constant_evaluation/value.rs b/crates/oxc_ecmascript/src/constant_evaluation/value.rs index 40076948a5e48..acfb64f4c7e65 100644 --- a/crates/oxc_ecmascript/src/constant_evaluation/value.rs +++ b/crates/oxc_ecmascript/src/constant_evaluation/value.rs @@ -3,7 +3,7 @@ use std::borrow::Cow; use num_bigint::BigInt; use num_traits::Zero; -use crate::{ToBoolean, ToJsString, ToNumber, is_global_reference::IsGlobalReference}; +use crate::{GlobalContext, ToBoolean, ToJsString, ToNumber}; #[derive(Debug, PartialEq, Clone)] pub enum ConstantValue<'a> { @@ -70,10 +70,7 @@ impl<'a> ConstantValue<'a> { } impl<'a> ToJsString<'a> for ConstantValue<'a> { - fn to_js_string( - &self, - _is_global_reference: &impl IsGlobalReference<'a>, - ) -> Option> { + fn to_js_string(&self, _ctx: &impl GlobalContext<'a>) -> Option> { match self { Self::Number(n) => { use oxc_syntax::number::ToJsString; @@ -90,7 +87,7 @@ impl<'a> ToJsString<'a> for ConstantValue<'a> { } impl<'a> ToNumber<'a> for ConstantValue<'a> { - fn to_number(&self, _is_global_reference: &impl IsGlobalReference<'a>) -> Option { + fn to_number(&self, _ctx: &impl GlobalContext<'a>) -> Option { use crate::StringToNumber; match self { Self::Number(n) => Some(*n), @@ -104,7 +101,7 @@ impl<'a> ToNumber<'a> for ConstantValue<'a> { } impl<'a> ToBoolean<'a> for ConstantValue<'a> { - fn to_boolean(&self, _is_global_reference: &impl IsGlobalReference<'a>) -> Option { + fn to_boolean(&self, _ctx: &impl GlobalContext<'a>) -> Option { match self { Self::Number(n) => Some(!n.is_nan() && *n != 0.0), Self::BigInt(n) => Some(*n != BigInt::zero()), diff --git a/crates/oxc_ecmascript/src/constant_evaluation/value_type.rs b/crates/oxc_ecmascript/src/constant_evaluation/value_type.rs index 99604821bbc8a..c8cb58a4db0ea 100644 --- a/crates/oxc_ecmascript/src/constant_evaluation/value_type.rs +++ b/crates/oxc_ecmascript/src/constant_evaluation/value_type.rs @@ -1,9 +1,7 @@ use oxc_ast::ast::*; use oxc_syntax::operator::{BinaryOperator, UnaryOperator}; -use crate::{ - is_global_reference::IsGlobalReference, to_numeric::ToNumeric, to_primitive::ToPrimitive, -}; +use crate::{GlobalContext, to_numeric::ToNumeric, to_primitive::ToPrimitive}; /// JavaScript Language Type /// @@ -61,11 +59,11 @@ impl ValueType { /// This function ignores the cases that throws an error, e.g. `foo * 0` can throw an error when `foo` is a bigint. /// To detect those cases, use [`crate::side_effects::MayHaveSideEffects`]. pub trait DetermineValueType<'a> { - fn value_type(&self, is_global_reference: &impl IsGlobalReference<'a>) -> ValueType; + fn value_type(&self, ctx: &impl GlobalContext<'a>) -> ValueType; } impl<'a> DetermineValueType<'a> for Expression<'a> { - fn value_type(&self, is_global_reference: &impl IsGlobalReference<'a>) -> ValueType { + fn value_type(&self, ctx: &impl GlobalContext<'a>) -> ValueType { match self { Expression::BigIntLiteral(_) => ValueType::BigInt, Expression::BooleanLiteral(_) | Expression::PrivateInExpression(_) => { @@ -87,7 +85,7 @@ impl<'a> DetermineValueType<'a> for Expression<'a> { } } Expression::Identifier(ident) => { - if is_global_reference.is_global_reference(ident) == Some(true) { + if ctx.is_global_reference(ident) == Some(true) { match ident.name.as_str() { "undefined" => ValueType::Undefined, "NaN" | "Infinity" => ValueType::Number, @@ -97,34 +95,33 @@ impl<'a> DetermineValueType<'a> for Expression<'a> { ValueType::Undetermined } } - Expression::UnaryExpression(e) => e.value_type(is_global_reference), - Expression::BinaryExpression(e) => e.value_type(is_global_reference), - Expression::SequenceExpression(e) => e - .expressions - .last() - .map_or(ValueType::Undetermined, |e| e.value_type(is_global_reference)), - Expression::AssignmentExpression(e) => e.value_type(is_global_reference), - Expression::ConditionalExpression(e) => e.value_type(is_global_reference), - Expression::LogicalExpression(e) => e.value_type(is_global_reference), - Expression::ParenthesizedExpression(e) => e.expression.value_type(is_global_reference), - Expression::StaticMemberExpression(e) => e.value_type(is_global_reference), - Expression::NewExpression(e) => e.value_type(is_global_reference), + Expression::UnaryExpression(e) => e.value_type(ctx), + Expression::BinaryExpression(e) => e.value_type(ctx), + Expression::SequenceExpression(e) => { + e.expressions.last().map_or(ValueType::Undetermined, |e| e.value_type(ctx)) + } + Expression::AssignmentExpression(e) => e.value_type(ctx), + Expression::ConditionalExpression(e) => e.value_type(ctx), + Expression::LogicalExpression(e) => e.value_type(ctx), + Expression::ParenthesizedExpression(e) => e.expression.value_type(ctx), + Expression::StaticMemberExpression(e) => e.value_type(ctx), + Expression::NewExpression(e) => e.value_type(ctx), _ => ValueType::Undetermined, } } } impl<'a> DetermineValueType<'a> for BinaryExpression<'a> { - fn value_type(&self, is_global_reference: &impl IsGlobalReference<'a>) -> ValueType { + fn value_type(&self, ctx: &impl GlobalContext<'a>) -> ValueType { match self.operator { BinaryOperator::Addition => { - let left = self.left.to_primitive(is_global_reference); - let right = self.right.to_primitive(is_global_reference); + let left = self.left.to_primitive(ctx); + let right = self.right.to_primitive(ctx); if left.is_string() == Some(true) || right.is_string() == Some(true) { return ValueType::String; } - let left_to_numeric_type = left.to_numeric(is_global_reference); - let right_to_numeric_type = right.to_numeric(is_global_reference); + let left_to_numeric_type = left.to_numeric(ctx); + let right_to_numeric_type = right.to_numeric(ctx); // we need to check both operands because the other operand might be undetermined and maybe a string if left_to_numeric_type.is_number() && right_to_numeric_type.is_number() { return ValueType::Number; @@ -144,8 +141,8 @@ impl<'a> DetermineValueType<'a> for BinaryExpression<'a> { | BinaryOperator::BitwiseXOR | BinaryOperator::BitwiseAnd | BinaryOperator::Exponential => { - let left_to_numeric_type = self.left.to_numeric(is_global_reference); - let right_to_numeric_type = self.right.to_numeric(is_global_reference); + let left_to_numeric_type = self.left.to_numeric(ctx); + let right_to_numeric_type = self.right.to_numeric(ctx); // if either operand is a number, the result is always a number // because if the other operand is a bigint, an error is thrown if left_to_numeric_type.is_number() || right_to_numeric_type.is_number() { @@ -172,11 +169,11 @@ impl<'a> DetermineValueType<'a> for BinaryExpression<'a> { } impl<'a> DetermineValueType<'a> for UnaryExpression<'a> { - fn value_type(&self, is_global_reference: &impl IsGlobalReference<'a>) -> ValueType { + fn value_type(&self, ctx: &impl GlobalContext<'a>) -> ValueType { match self.operator { UnaryOperator::Void => ValueType::Undefined, UnaryOperator::UnaryNegation | UnaryOperator::BitwiseNot => { - let argument_ty = self.argument.value_type(is_global_reference); + let argument_ty = self.argument.value_type(ctx); match argument_ty { ValueType::BigInt => ValueType::BigInt, // non-object values other than BigInt are converted to number by `ToNumber` @@ -196,11 +193,11 @@ impl<'a> DetermineValueType<'a> for UnaryExpression<'a> { } impl<'a> DetermineValueType<'a> for AssignmentExpression<'a> { - fn value_type(&self, is_global_reference: &impl IsGlobalReference<'a>) -> ValueType { + fn value_type(&self, ctx: &impl GlobalContext<'a>) -> ValueType { match self.operator { - AssignmentOperator::Assign => self.right.value_type(is_global_reference), + AssignmentOperator::Assign => self.right.value_type(ctx), AssignmentOperator::Addition => { - let right = self.right.value_type(is_global_reference); + let right = self.right.value_type(ctx); if right.is_string() { ValueType::String } else { ValueType::Undetermined } } AssignmentOperator::Subtraction @@ -213,7 +210,7 @@ impl<'a> DetermineValueType<'a> for AssignmentExpression<'a> { | AssignmentOperator::BitwiseXOR | AssignmentOperator::BitwiseAnd | AssignmentOperator::Exponential => { - let right = self.right.value_type(is_global_reference); + let right = self.right.value_type(ctx); if right.is_bigint() { ValueType::BigInt } else if !(right.is_object() || right.is_undetermined()) { @@ -231,12 +228,12 @@ impl<'a> DetermineValueType<'a> for AssignmentExpression<'a> { } impl<'a> DetermineValueType<'a> for ConditionalExpression<'a> { - fn value_type(&self, is_global_reference: &impl IsGlobalReference<'a>) -> ValueType { - let left = self.consequent.value_type(is_global_reference); + fn value_type(&self, ctx: &impl GlobalContext<'a>) -> ValueType { + let left = self.consequent.value_type(ctx); if left.is_undetermined() { return ValueType::Undetermined; } - let right = self.alternate.value_type(is_global_reference); + let right = self.alternate.value_type(ctx); if left == right { return left; } @@ -245,25 +242,23 @@ impl<'a> DetermineValueType<'a> for ConditionalExpression<'a> { } impl<'a> DetermineValueType<'a> for LogicalExpression<'a> { - fn value_type(&self, is_global_reference: &impl IsGlobalReference<'a>) -> ValueType { + fn value_type(&self, ctx: &impl GlobalContext<'a>) -> ValueType { match self.operator { LogicalOperator::And | LogicalOperator::Or => { - let left = self.left.value_type(is_global_reference); + let left = self.left.value_type(ctx); if left.is_undetermined() { return ValueType::Undetermined; } - let right = self.right.value_type(is_global_reference); + let right = self.right.value_type(ctx); if left == right { return left; } ValueType::Undetermined } LogicalOperator::Coalesce => { - let left = self.left.value_type(is_global_reference); + let left = self.left.value_type(ctx); match left { - ValueType::Undefined | ValueType::Null => { - self.right.value_type(is_global_reference) - } + ValueType::Undefined | ValueType::Null => self.right.value_type(ctx), ValueType::Undetermined => ValueType::Undetermined, _ => left, } @@ -273,12 +268,10 @@ impl<'a> DetermineValueType<'a> for LogicalExpression<'a> { } impl<'a> DetermineValueType<'a> for StaticMemberExpression<'a> { - fn value_type(&self, is_global_reference: &impl IsGlobalReference<'a>) -> ValueType { + fn value_type(&self, ctx: &impl GlobalContext<'a>) -> ValueType { if matches!(self.property.name.as_str(), "POSITIVE_INFINITY" | "NEGATIVE_INFINITY") { if let Some(ident) = self.object.get_identifier_reference() { - if ident.name.as_str() == "Number" - && is_global_reference.is_global_reference(ident) == Some(true) - { + if ident.name.as_str() == "Number" && ctx.is_global_reference(ident) == Some(true) { return ValueType::Number; } } @@ -288,11 +281,9 @@ impl<'a> DetermineValueType<'a> for StaticMemberExpression<'a> { } impl<'a> DetermineValueType<'a> for NewExpression<'a> { - fn value_type(&self, is_global_reference: &impl IsGlobalReference<'a>) -> ValueType { + fn value_type(&self, ctx: &impl GlobalContext<'a>) -> ValueType { if let Some(ident) = self.callee.get_identifier_reference() { - if ident.name.as_str() == "Date" - && is_global_reference.is_global_reference(ident) == Some(true) - { + if ident.name.as_str() == "Date" && ctx.is_global_reference(ident) == Some(true) { return ValueType::Object; } } diff --git a/crates/oxc_ecmascript/src/is_global_reference.rs b/crates/oxc_ecmascript/src/global_context.rs similarity index 86% rename from crates/oxc_ecmascript/src/is_global_reference.rs rename to crates/oxc_ecmascript/src/global_context.rs index 73501b9f15f44..53a51989a081c 100644 --- a/crates/oxc_ecmascript/src/is_global_reference.rs +++ b/crates/oxc_ecmascript/src/global_context.rs @@ -3,7 +3,7 @@ use oxc_syntax::reference::ReferenceId; use crate::constant_evaluation::ConstantValue; -pub trait IsGlobalReference<'a>: Sized { +pub trait GlobalContext<'a>: Sized { /// Whether the reference is a global reference. /// /// - None means it is unknown. @@ -21,7 +21,7 @@ pub trait IsGlobalReference<'a>: Sized { pub struct WithoutGlobalReferenceInformation; -impl<'a> IsGlobalReference<'a> for WithoutGlobalReferenceInformation { +impl<'a> GlobalContext<'a> for WithoutGlobalReferenceInformation { fn is_global_reference(&self, _reference: &IdentifierReference<'a>) -> Option { None } diff --git a/crates/oxc_ecmascript/src/lib.rs b/crates/oxc_ecmascript/src/lib.rs index 5e68bb4731e91..0b0a1adc4001f 100644 --- a/crates/oxc_ecmascript/src/lib.rs +++ b/crates/oxc_ecmascript/src/lib.rs @@ -29,12 +29,13 @@ mod to_string; mod to_integer_index; pub mod constant_evaluation; -pub mod is_global_reference; +mod global_context; pub mod side_effects; pub use self::{ array_join::ArrayJoin, bound_names::BoundNames, + global_context::{GlobalContext, WithoutGlobalReferenceInformation}, is_simple_parameter_list::IsSimpleParameterList, private_bound_identifiers::PrivateBoundIdentifiers, prop_name::PropName, diff --git a/crates/oxc_ecmascript/src/side_effects/context.rs b/crates/oxc_ecmascript/src/side_effects/context.rs index 446c287c294f9..7cd44575ca8a1 100644 --- a/crates/oxc_ecmascript/src/side_effects/context.rs +++ b/crates/oxc_ecmascript/src/side_effects/context.rs @@ -1,6 +1,6 @@ use oxc_ast::ast::Expression; -use crate::is_global_reference::IsGlobalReference; +use crate::GlobalContext; #[derive(Default, Clone, Copy, Debug, PartialEq, Eq)] pub enum PropertyReadSideEffects { @@ -14,7 +14,7 @@ pub enum PropertyReadSideEffects { All, } -pub trait MayHaveSideEffectsContext<'a>: IsGlobalReference<'a> { +pub trait MayHaveSideEffectsContext<'a>: GlobalContext<'a> { /// Whether to respect the pure annotations. /// /// Pure annotations are the comments that marks that a expression is pure. diff --git a/crates/oxc_ecmascript/src/to_big_int.rs b/crates/oxc_ecmascript/src/to_big_int.rs index 91b60c709d768..073a866e01292 100644 --- a/crates/oxc_ecmascript/src/to_big_int.rs +++ b/crates/oxc_ecmascript/src/to_big_int.rs @@ -4,18 +4,18 @@ use num_traits::{Num, One, Zero}; use oxc_ast::ast::{BigIntLiteral, Expression}; use oxc_syntax::operator::UnaryOperator; -use crate::{StringToBigInt, ToBoolean, ToJsString, is_global_reference::IsGlobalReference}; +use crate::{GlobalContext, StringToBigInt, ToBoolean, ToJsString}; /// `ToBigInt` /// /// pub trait ToBigInt<'a> { - fn to_big_int(&self, is_global_reference: &impl IsGlobalReference<'a>) -> Option; + fn to_big_int(&self, ctx: &impl GlobalContext<'a>) -> Option; } impl<'a> ToBigInt<'a> for Expression<'a> { #[expect(clippy::cast_possible_truncation)] - fn to_big_int(&self, is_global_reference: &impl IsGlobalReference<'a>) -> Option { + fn to_big_int(&self, ctx: &impl GlobalContext<'a>) -> Option { match self { Expression::NumericLiteral(number_literal) => { let value = number_literal.value; @@ -25,7 +25,7 @@ impl<'a> ToBigInt<'a> for Expression<'a> { None } } - Expression::BigIntLiteral(lit) => lit.to_big_int(is_global_reference), + Expression::BigIntLiteral(lit) => lit.to_big_int(ctx), Expression::BooleanLiteral(bool_literal) => { if bool_literal.value { Some(BigInt::one()) @@ -35,30 +35,30 @@ impl<'a> ToBigInt<'a> for Expression<'a> { } Expression::UnaryExpression(unary_expr) => match unary_expr.operator { UnaryOperator::LogicalNot => self - .to_boolean(is_global_reference) + .to_boolean(ctx) .map(|boolean| if boolean { BigInt::one() } else { BigInt::zero() }), UnaryOperator::UnaryNegation => { - unary_expr.argument.to_big_int(is_global_reference).map(std::ops::Neg::neg) + unary_expr.argument.to_big_int(ctx).map(std::ops::Neg::neg) } UnaryOperator::BitwiseNot => { - unary_expr.argument.to_big_int(is_global_reference).map(std::ops::Not::not) + unary_expr.argument.to_big_int(ctx).map(std::ops::Not::not) } - UnaryOperator::UnaryPlus => unary_expr.argument.to_big_int(is_global_reference), + UnaryOperator::UnaryPlus => unary_expr.argument.to_big_int(ctx), _ => None, }, Expression::StringLiteral(string_literal) => { string_literal.value.as_str().string_to_big_int() } - Expression::TemplateLiteral(_) => self - .to_js_string(is_global_reference) - .and_then(|value| value.as_ref().string_to_big_int()), + Expression::TemplateLiteral(_) => { + self.to_js_string(ctx).and_then(|value| value.as_ref().string_to_big_int()) + } _ => None, } } } impl<'a> ToBigInt<'a> for BigIntLiteral<'a> { - fn to_big_int(&self, _is_global_reference: &impl IsGlobalReference<'a>) -> Option { + fn to_big_int(&self, _ctx: &impl GlobalContext<'a>) -> Option { // No need to use `StringToBigInt::string_to_big_int`, because `value` is always base 10 let value = BigInt::from_str_radix(&self.value, 10).ok(); debug_assert!(value.is_some(), "Failed to parse {}n", self.value); diff --git a/crates/oxc_ecmascript/src/to_boolean.rs b/crates/oxc_ecmascript/src/to_boolean.rs index 011e7075a383f..21d56a670d54c 100644 --- a/crates/oxc_ecmascript/src/to_boolean.rs +++ b/crates/oxc_ecmascript/src/to_boolean.rs @@ -1,30 +1,24 @@ use oxc_ast::ast::Expression; -use crate::is_global_reference::IsGlobalReference; +use crate::GlobalContext; /// `ToBoolean` /// /// pub trait ToBoolean<'a> { - fn to_boolean(&self, is_global_reference: &impl IsGlobalReference<'a>) -> Option; + fn to_boolean(&self, ctx: &impl GlobalContext<'a>) -> Option; } impl<'a> ToBoolean<'a> for Expression<'a> { - fn to_boolean(&self, is_global_reference: &impl IsGlobalReference<'a>) -> Option { + fn to_boolean(&self, ctx: &impl GlobalContext<'a>) -> Option { // 1. If argument is a Boolean, return argument. // 2. If argument is one of undefined, null, +0𝔽, -0𝔽, NaN, 0ℤ, or the empty String, return false. // 3. NOTE: This step is replaced in section B.3.6.1. // 4. Return true. match self { Expression::Identifier(ident) => match ident.name.as_str() { - "NaN" | "undefined" - if is_global_reference.is_global_reference(ident) == Some(true) => - { - Some(false) - } - "Infinity" if is_global_reference.is_global_reference(ident) == Some(true) => { - Some(true) - } + "NaN" | "undefined" if ctx.is_global_reference(ident) == Some(true) => Some(false), + "Infinity" if ctx.is_global_reference(ident) == Some(true) => Some(true), _ => None, }, Expression::RegExpLiteral(_) @@ -51,7 +45,7 @@ impl<'a> ToBoolean<'a> for Expression<'a> { .map(|cooked| !cooked.is_empty()) } Expression::SequenceExpression(e) => { - e.expressions.last().and_then(|expr| expr.to_boolean(is_global_reference)) + e.expressions.last().and_then(|expr| expr.to_boolean(ctx)) } _ => None, } diff --git a/crates/oxc_ecmascript/src/to_number.rs b/crates/oxc_ecmascript/src/to_number.rs index e710ce5bfa6de..09d6f6737c837 100644 --- a/crates/oxc_ecmascript/src/to_number.rs +++ b/crates/oxc_ecmascript/src/to_number.rs @@ -1,19 +1,18 @@ use oxc_ast::ast::*; use crate::{ - is_global_reference::IsGlobalReference, - to_primitive::maybe_object_with_to_primitive_related_properties_overridden, + GlobalContext, to_primitive::maybe_object_with_to_primitive_related_properties_overridden, }; /// `ToNumber` /// /// pub trait ToNumber<'a> { - fn to_number(&self, is_global_reference: &impl IsGlobalReference<'a>) -> Option; + fn to_number(&self, ctx: &impl GlobalContext<'a>) -> Option; } impl<'a> ToNumber<'a> for Expression<'a> { - fn to_number(&self, is_global_reference: &impl IsGlobalReference<'a>) -> Option { + fn to_number(&self, ctx: &impl GlobalContext<'a>) -> Option { match self { Expression::NumericLiteral(number_literal) => Some(number_literal.value), Expression::BooleanLiteral(bool_literal) => { @@ -25,12 +24,8 @@ impl<'a> ToNumber<'a> for Expression<'a> { } Expression::NullLiteral(_) => Some(0.0), Expression::Identifier(ident) => match ident.name.as_str() { - "Infinity" if is_global_reference.is_global_reference(ident) == Some(true) => { - Some(f64::INFINITY) - } - "NaN" | "undefined" - if is_global_reference.is_global_reference(ident) == Some(true) => - { + "Infinity" if ctx.is_global_reference(ident) == Some(true) => Some(f64::INFINITY), + "NaN" | "undefined" if ctx.is_global_reference(ident) == Some(true) => { Some(f64::NAN) } _ => None, @@ -40,7 +35,7 @@ impl<'a> ToNumber<'a> for Expression<'a> { Some(lit.value.as_str().string_to_number()) } Expression::UnaryExpression(unary) if unary.operator.is_not() => { - let number = unary.argument.to_number(is_global_reference)?; + let number = unary.argument.to_number(ctx)?; Some(if number == 0.0 { 1.0 } else { 0.0 }) } Expression::ObjectExpression(obj) => { @@ -67,7 +62,7 @@ impl<'a> ToNumber<'a> for Expression<'a> { // `ToPrimitive` returns `""` for `[,]` ArrayExpressionElement::Elision(_) => Some(0.0), match_expression!(ArrayExpressionElement) => { - first_element.to_expression().to_number(is_global_reference) + first_element.to_expression().to_number(ctx) } }; } diff --git a/crates/oxc_ecmascript/src/to_numeric.rs b/crates/oxc_ecmascript/src/to_numeric.rs index 818b1e438d5e9..9558651b659d7 100644 --- a/crates/oxc_ecmascript/src/to_numeric.rs +++ b/crates/oxc_ecmascript/src/to_numeric.rs @@ -1,7 +1,7 @@ use oxc_ast::ast::Expression; use crate::{ - is_global_reference::IsGlobalReference, + GlobalContext, to_primitive::{ToPrimitive, ToPrimitiveResult}, }; @@ -26,17 +26,17 @@ impl ToNumericResult { /// /// pub trait ToNumeric<'a> { - fn to_numeric(&self, is_global_reference: &impl IsGlobalReference<'a>) -> ToNumericResult; + fn to_numeric(&self, ctx: &impl GlobalContext<'a>) -> ToNumericResult; } impl<'a> ToNumeric<'a> for Expression<'a> { - fn to_numeric(&self, is_global_reference: &impl IsGlobalReference<'a>) -> ToNumericResult { - self.to_primitive(is_global_reference).to_numeric(is_global_reference) + fn to_numeric(&self, ctx: &impl GlobalContext<'a>) -> ToNumericResult { + self.to_primitive(ctx).to_numeric(ctx) } } impl<'a> ToNumeric<'a> for ToPrimitiveResult { - fn to_numeric(&self, _is_global_reference: &impl IsGlobalReference<'a>) -> ToNumericResult { + fn to_numeric(&self, _ctx: &impl GlobalContext<'a>) -> ToNumericResult { match self { // Symbol throws an error when passed to ToNumber in step 3 ToPrimitiveResult::Symbol | ToPrimitiveResult::Undetermined => { diff --git a/crates/oxc_ecmascript/src/to_primitive.rs b/crates/oxc_ecmascript/src/to_primitive.rs index d88f31dc56c69..b1df0e9642048 100644 --- a/crates/oxc_ecmascript/src/to_primitive.rs +++ b/crates/oxc_ecmascript/src/to_primitive.rs @@ -1,8 +1,8 @@ use oxc_ast::ast::*; use crate::{ + GlobalContext, constant_evaluation::{DetermineValueType, ValueType}, - is_global_reference::IsGlobalReference, }; #[derive(Debug, Clone, Copy, PartialEq, Eq)] @@ -47,12 +47,12 @@ impl ToPrimitiveResult { /// /// pub trait ToPrimitive<'a> { - fn to_primitive(&self, is_global_reference: &impl IsGlobalReference<'a>) -> ToPrimitiveResult; + fn to_primitive(&self, ctx: &impl GlobalContext<'a>) -> ToPrimitiveResult; } impl<'a> ToPrimitive<'a> for Expression<'a> { - fn to_primitive(&self, is_global_reference: &impl IsGlobalReference<'a>) -> ToPrimitiveResult { - match self.value_type(is_global_reference) { + fn to_primitive(&self, ctx: &impl GlobalContext<'a>) -> ToPrimitiveResult { + match self.value_type(ctx) { ValueType::Undefined => ToPrimitiveResult::Undefined, ValueType::Null => ToPrimitiveResult::Null, ValueType::Number => ToPrimitiveResult::Number, diff --git a/crates/oxc_ecmascript/src/to_string.rs b/crates/oxc_ecmascript/src/to_string.rs index 268735e3ffb75..1a7970d5f519e 100644 --- a/crates/oxc_ecmascript/src/to_string.rs +++ b/crates/oxc_ecmascript/src/to_string.rs @@ -4,10 +4,9 @@ use oxc_ast::ast::*; use oxc_syntax::operator::UnaryOperator; use crate::{ - ToBoolean, + GlobalContext, ToBoolean, array_join::ArrayJoin, constant_evaluation::{DetermineValueType, ValueType}, - is_global_reference::IsGlobalReference, to_primitive::maybe_object_with_to_primitive_related_properties_overridden, }; @@ -15,48 +14,39 @@ use crate::{ /// /// pub trait ToJsString<'a> { - fn to_js_string( - &self, - is_global_reference: &impl IsGlobalReference<'a>, - ) -> Option>; + fn to_js_string(&self, ctx: &impl GlobalContext<'a>) -> Option>; } impl<'a> ToJsString<'a> for Expression<'a> { - fn to_js_string( - &self, - is_global_reference: &impl IsGlobalReference<'a>, - ) -> Option> { + fn to_js_string(&self, ctx: &impl GlobalContext<'a>) -> Option> { match self { - Expression::StringLiteral(lit) => lit.to_js_string(is_global_reference), - Expression::TemplateLiteral(lit) => lit.to_js_string(is_global_reference), - Expression::Identifier(ident) => ident.to_js_string(is_global_reference), - Expression::NumericLiteral(lit) => lit.to_js_string(is_global_reference), - Expression::BigIntLiteral(lit) => lit.to_js_string(is_global_reference), - Expression::NullLiteral(lit) => lit.to_js_string(is_global_reference), - Expression::BooleanLiteral(lit) => lit.to_js_string(is_global_reference), - Expression::UnaryExpression(e) => e.to_js_string(is_global_reference), - Expression::ArrayExpression(e) => e.to_js_string(is_global_reference), - Expression::ObjectExpression(e) => e.to_js_string(is_global_reference), - Expression::RegExpLiteral(e) => e.to_js_string(is_global_reference), + Expression::StringLiteral(lit) => lit.to_js_string(ctx), + Expression::TemplateLiteral(lit) => lit.to_js_string(ctx), + Expression::Identifier(ident) => ident.to_js_string(ctx), + Expression::NumericLiteral(lit) => lit.to_js_string(ctx), + Expression::BigIntLiteral(lit) => lit.to_js_string(ctx), + Expression::NullLiteral(lit) => lit.to_js_string(ctx), + Expression::BooleanLiteral(lit) => lit.to_js_string(ctx), + Expression::UnaryExpression(e) => e.to_js_string(ctx), + Expression::ArrayExpression(e) => e.to_js_string(ctx), + Expression::ObjectExpression(e) => e.to_js_string(ctx), + Expression::RegExpLiteral(e) => e.to_js_string(ctx), _ => None, } } } impl<'a> ToJsString<'a> for ArrayExpressionElement<'a> { - fn to_js_string( - &self, - is_global_reference: &impl IsGlobalReference<'a>, - ) -> Option> { + fn to_js_string(&self, ctx: &impl GlobalContext<'a>) -> Option> { match self { ArrayExpressionElement::SpreadElement(_) => None, ArrayExpressionElement::Elision(_) => Some(Cow::Borrowed("")), expr @ match_expression!(ArrayExpressionElement) => { let expr = expr.as_expression()?; - match expr.value_type(is_global_reference) { + match expr.value_type(ctx) { ValueType::Undefined | ValueType::Null => Some(Cow::Borrowed("")), ValueType::Undetermined => None, - _ => expr.to_js_string(is_global_reference), + _ => expr.to_js_string(ctx), } } } @@ -64,26 +54,20 @@ impl<'a> ToJsString<'a> for ArrayExpressionElement<'a> { } impl<'a> ToJsString<'a> for StringLiteral<'a> { - fn to_js_string( - &self, - _is_global_reference: &impl IsGlobalReference<'a>, - ) -> Option> { + fn to_js_string(&self, _ctx: &impl GlobalContext<'a>) -> Option> { Some(Cow::Borrowed(self.value.as_str())) } } impl<'a> ToJsString<'a> for TemplateLiteral<'a> { - fn to_js_string( - &self, - is_global_reference: &impl IsGlobalReference<'a>, - ) -> Option> { + fn to_js_string(&self, ctx: &impl GlobalContext<'a>) -> Option> { let mut str = String::new(); for (i, quasi) in self.quasis.iter().enumerate() { str.push_str(quasi.value.cooked.as_ref()?); if i < self.expressions.len() { let expr = &self.expressions[i]; - let value = expr.to_js_string(is_global_reference)?; + let value = expr.to_js_string(ctx)?; str.push_str(&value); } } @@ -92,22 +76,16 @@ impl<'a> ToJsString<'a> for TemplateLiteral<'a> { } impl<'a> ToJsString<'a> for IdentifierReference<'a> { - fn to_js_string( - &self, - is_global_reference: &impl IsGlobalReference<'a>, - ) -> Option> { + fn to_js_string(&self, ctx: &impl GlobalContext<'a>) -> Option> { let name = self.name.as_str(); (matches!(name, "undefined" | "Infinity" | "NaN") - && is_global_reference.is_global_reference(self) == Some(true)) + && ctx.is_global_reference(self) == Some(true)) .then_some(Cow::Borrowed(name)) } } impl<'a> ToJsString<'a> for NumericLiteral<'a> { - fn to_js_string( - &self, - _is_global_reference: &impl IsGlobalReference<'a>, - ) -> Option> { + fn to_js_string(&self, _ctx: &impl GlobalContext<'a>) -> Option> { use oxc_syntax::number::ToJsString; let value = self.value; Some(if value == 0.0 { Cow::Borrowed("0") } else { Cow::Owned(value.to_js_string()) }) @@ -116,42 +94,30 @@ impl<'a> ToJsString<'a> for NumericLiteral<'a> { /// impl<'a> ToJsString<'a> for BigIntLiteral<'a> { - fn to_js_string( - &self, - _is_global_reference: &impl IsGlobalReference<'a>, - ) -> Option> { + fn to_js_string(&self, _ctx: &impl GlobalContext<'a>) -> Option> { Some(Cow::Borrowed(self.value.as_str())) } } impl<'a> ToJsString<'a> for BooleanLiteral { - fn to_js_string( - &self, - _is_global_reference: &impl IsGlobalReference<'a>, - ) -> Option> { + fn to_js_string(&self, _ctx: &impl GlobalContext<'a>) -> Option> { Some(Cow::Borrowed(if self.value { "true" } else { "false" })) } } impl<'a> ToJsString<'a> for NullLiteral { - fn to_js_string( - &self, - _is_global_reference: &impl IsGlobalReference<'a>, - ) -> Option> { + fn to_js_string(&self, _ctx: &impl GlobalContext<'a>) -> Option> { Some(Cow::Borrowed("null")) } } impl<'a> ToJsString<'a> for UnaryExpression<'a> { - fn to_js_string( - &self, - is_global_reference: &impl IsGlobalReference<'a>, - ) -> Option> { + fn to_js_string(&self, ctx: &impl GlobalContext<'a>) -> Option> { match self.operator { UnaryOperator::Void => Some(Cow::Borrowed("undefined")), UnaryOperator::LogicalNot => self .argument - .to_boolean(is_global_reference) + .to_boolean(ctx) .map(|boolean| Cow::Borrowed(if boolean { "false" } else { "true" })), _ => None, } @@ -159,19 +125,13 @@ impl<'a> ToJsString<'a> for UnaryExpression<'a> { } impl<'a> ToJsString<'a> for ArrayExpression<'a> { - fn to_js_string( - &self, - is_global_reference: &impl IsGlobalReference<'a>, - ) -> Option> { - self.array_join(is_global_reference, Some(",")).map(Cow::Owned) + fn to_js_string(&self, ctx: &impl GlobalContext<'a>) -> Option> { + self.array_join(ctx, Some(",")).map(Cow::Owned) } } impl<'a> ToJsString<'a> for ObjectExpression<'a> { - fn to_js_string( - &self, - _is_global_reference: &impl IsGlobalReference<'a>, - ) -> Option> { + fn to_js_string(&self, _ctx: &impl GlobalContext<'a>) -> Option> { if maybe_object_with_to_primitive_related_properties_overridden(self) { None } else { @@ -181,10 +141,7 @@ impl<'a> ToJsString<'a> for ObjectExpression<'a> { } impl<'a> ToJsString<'a> for RegExpLiteral<'a> { - fn to_js_string( - &self, - _is_global_reference: &impl IsGlobalReference<'a>, - ) -> Option> { + fn to_js_string(&self, _ctx: &impl GlobalContext<'a>) -> Option> { if let Some(raw) = self.raw.as_ref() { Some(Cow::Borrowed(raw.as_str())) } else { diff --git a/crates/oxc_linter/src/ast_util.rs b/crates/oxc_linter/src/ast_util.rs index 37c1579e28208..4b04747861c79 100644 --- a/crates/oxc_linter/src/ast_util.rs +++ b/crates/oxc_linter/src/ast_util.rs @@ -6,7 +6,7 @@ use oxc_ast::{ AstKind, ast::{BindingIdentifier, *}, }; -use oxc_ecmascript::{ToBoolean, is_global_reference::WithoutGlobalReferenceInformation}; +use oxc_ecmascript::{ToBoolean, WithoutGlobalReferenceInformation}; use oxc_semantic::{AstNode, AstNodes, IsGlobalReference, NodeId, ReferenceId, Semantic, SymbolId}; use oxc_span::{GetSpan, Span}; use oxc_syntax::operator::{AssignmentOperator, BinaryOperator, LogicalOperator, UnaryOperator}; diff --git a/crates/oxc_linter/src/rules/eslint/array_callback_return/return_checker.rs b/crates/oxc_linter/src/rules/eslint/array_callback_return/return_checker.rs index 4cb66d004b068..c98c4f00b1ac9 100644 --- a/crates/oxc_linter/src/rules/eslint/array_callback_return/return_checker.rs +++ b/crates/oxc_linter/src/rules/eslint/array_callback_return/return_checker.rs @@ -1,5 +1,5 @@ use oxc_ast::ast::{BlockStatement, FunctionBody, Statement, SwitchCase}; -use oxc_ecmascript::{ToBoolean, is_global_reference::WithoutGlobalReferenceInformation}; +use oxc_ecmascript::{ToBoolean, WithoutGlobalReferenceInformation}; /// `StatementReturnStatus` describes whether the CFG corresponding to /// the statement is termitated by return statement in all/some/nome of diff --git a/crates/oxc_linter/src/rules/eslint/yoda.rs b/crates/oxc_linter/src/rules/eslint/yoda.rs index 6f7022c862cd0..62cddd9048952 100644 --- a/crates/oxc_linter/src/rules/eslint/yoda.rs +++ b/crates/oxc_linter/src/rules/eslint/yoda.rs @@ -6,7 +6,7 @@ use oxc_ast::{ }, }; use oxc_diagnostics::OxcDiagnostic; -use oxc_ecmascript::{ToBigInt, is_global_reference::WithoutGlobalReferenceInformation}; +use oxc_ecmascript::{ToBigInt, WithoutGlobalReferenceInformation}; use oxc_macros::declare_oxc_lint; use oxc_span::{GetSpan, Span}; diff --git a/crates/oxc_linter/src/utils/react.rs b/crates/oxc_linter/src/utils/react.rs index 32a3e0ed1f3ac..0d78eaac4174c 100644 --- a/crates/oxc_linter/src/utils/react.rs +++ b/crates/oxc_linter/src/utils/react.rs @@ -9,7 +9,7 @@ use oxc_ast::{ }, match_member_expression, }; -use oxc_ecmascript::{ToBoolean, is_global_reference::WithoutGlobalReferenceInformation}; +use oxc_ecmascript::{ToBoolean, WithoutGlobalReferenceInformation}; use oxc_semantic::AstNode; use crate::{LintContext, OxlintSettings}; diff --git a/crates/oxc_minifier/CHANGELOG.md b/crates/oxc_minifier/CHANGELOG.md index f1ebafe55a606..77b6dd841c5e5 100644 --- a/crates/oxc_minifier/CHANGELOG.md +++ b/crates/oxc_minifier/CHANGELOG.md @@ -159,7 +159,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0). ### 🚜 Refactor -- 5a46641 ecmascript: Move `get_constant_value_for_reference_id` to `IsGlobalReference` trait (#11810) (Boshen) +- 5a46641 ecmascript: Move `get_constant_value_for_reference_id` to `GlobalContext` trait (#11810) (Boshen) - d5a8f18 minifier: Make `Ctx` take `&mut TraverseCtx` (#11771) (Boshen) @@ -525,10 +525,10 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), - 8bd6eef ecmascript: Merge constant evaluation logics (#9120) (sapphi-red) - b164072 ecmascript: Extract to_numeric (#9111) (sapphi-red) -- 8f79012 ecmascript: Pass IsGlobalReference to DetermineValueType instead of extending it (#9107) (sapphi-red) +- 8f79012 ecmascript: Pass GlobalContext to DetermineValueType instead of extending it (#9107) (sapphi-red) - db1744c ecmascript: Remove "constant_evaluation" / "side_effects" features (#9114) (sapphi-red) -- d670ec7 ecmascript: Pass IsGlobalReference to MayHaveSideEffects instead of extending it (#9101) (sapphi-red) -- f4e2d4e ecmascript: Allow IsGlobalReference to return None (#9100) (sapphi-red) +- d670ec7 ecmascript: Pass GlobalContext to MayHaveSideEffects instead of extending it (#9101) (sapphi-red) +- f4e2d4e ecmascript: Allow GlobalContext to return None (#9100) (sapphi-red) - 29be94d minifier: Inline more minification methods (#9088) (Boshen) - 80f719e minifier: Clean up minimize_statements.rs (#9076) (Boshen) - d5edde0 minifier: Minimize `if (!foo) foo = bar;` -> `foo ||= bar` in the same AST pass (#9075) (Boshen) @@ -1259,7 +1259,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), ### Refactor -- 067f9b5 semantic: Introduce `IsGlobalReference` trait (#5672) (Boshen) +- 067f9b5 semantic: Introduce `GlobalContext` trait (#5672) (Boshen) ## [0.27.0] - 2024-09-06 diff --git a/crates/oxc_minifier/src/ctx.rs b/crates/oxc_minifier/src/ctx.rs index ea0aa370a9fcf..a5da4db759da1 100644 --- a/crates/oxc_minifier/src/ctx.rs +++ b/crates/oxc_minifier/src/ctx.rs @@ -41,7 +41,7 @@ impl<'a, 'b> DerefMut for Ctx<'a, 'b> { } } -impl<'a> oxc_ecmascript::is_global_reference::IsGlobalReference<'a> for Ctx<'a, '_> { +impl<'a> oxc_ecmascript::GlobalContext<'a> for Ctx<'a, '_> { fn is_global_reference(&self, ident: &IdentifierReference<'_>) -> Option { Some(ident.is_global_reference(self.0.scoping())) } diff --git a/crates/oxc_minifier/tests/ecmascript/array_join.rs b/crates/oxc_minifier/tests/ecmascript/array_join.rs index e2ad8411560ad..be4a8d311ba6c 100644 --- a/crates/oxc_minifier/tests/ecmascript/array_join.rs +++ b/crates/oxc_minifier/tests/ecmascript/array_join.rs @@ -1,6 +1,6 @@ use oxc_allocator::{Allocator, CloneIn}; use oxc_ast::{AstBuilder, ast::*}; -use oxc_ecmascript::{ArrayJoin, is_global_reference::WithoutGlobalReferenceInformation}; +use oxc_ecmascript::{ArrayJoin, WithoutGlobalReferenceInformation}; use oxc_span::SPAN; #[test] diff --git a/crates/oxc_minifier/tests/ecmascript/is_int32_or_uint32.rs b/crates/oxc_minifier/tests/ecmascript/is_int32_or_uint32.rs index 59b1fb9e3d456..ae2331eeed5af 100644 --- a/crates/oxc_minifier/tests/ecmascript/is_int32_or_uint32.rs +++ b/crates/oxc_minifier/tests/ecmascript/is_int32_or_uint32.rs @@ -1,8 +1,6 @@ use oxc_allocator::Allocator; use oxc_ast::ast::Statement; -use oxc_ecmascript::{ - constant_evaluation::IsInt32OrUint32, is_global_reference::WithoutGlobalReferenceInformation, -}; +use oxc_ecmascript::{WithoutGlobalReferenceInformation, constant_evaluation::IsInt32OrUint32}; use oxc_parser::Parser; use oxc_span::SourceType; diff --git a/crates/oxc_minifier/tests/ecmascript/may_have_side_effects.rs b/crates/oxc_minifier/tests/ecmascript/may_have_side_effects.rs index 15e479bec9510..dda5d91420180 100644 --- a/crates/oxc_minifier/tests/ecmascript/may_have_side_effects.rs +++ b/crates/oxc_minifier/tests/ecmascript/may_have_side_effects.rs @@ -1,7 +1,7 @@ use oxc_allocator::Allocator; use oxc_ast::ast::{Expression, IdentifierReference, Statement}; use oxc_ecmascript::{ - is_global_reference::IsGlobalReference, + GlobalContext, side_effects::{MayHaveSideEffects, MayHaveSideEffectsContext, PropertyReadSideEffects}, }; use oxc_parser::Parser; @@ -25,7 +25,7 @@ impl Default for Ctx { } } } -impl<'a> IsGlobalReference<'a> for Ctx { +impl<'a> GlobalContext<'a> for Ctx { fn is_global_reference(&self, ident: &IdentifierReference<'a>) -> Option { Some(self.global_variable_names.iter().any(|name| name == ident.name.as_str())) } diff --git a/crates/oxc_minifier/tests/ecmascript/to_boolean.rs b/crates/oxc_minifier/tests/ecmascript/to_boolean.rs index 6fdc996a64049..0f30f30225458 100644 --- a/crates/oxc_minifier/tests/ecmascript/to_boolean.rs +++ b/crates/oxc_minifier/tests/ecmascript/to_boolean.rs @@ -1,13 +1,13 @@ use oxc_allocator::Allocator; use oxc_ast::{AstBuilder, ast::*}; -use oxc_ecmascript::{ToBoolean, is_global_reference::IsGlobalReference}; +use oxc_ecmascript::{GlobalContext, ToBoolean}; use oxc_span::SPAN; struct GlobalReferenceInformation { is_undefined_shadowed: bool, } -impl<'a> IsGlobalReference<'a> for GlobalReferenceInformation { +impl<'a> GlobalContext<'a> for GlobalReferenceInformation { fn is_global_reference(&self, ident: &IdentifierReference<'a>) -> Option { if ident.name == "undefined" { Some(!self.is_undefined_shadowed) } else { None } } diff --git a/crates/oxc_minifier/tests/ecmascript/to_number.rs b/crates/oxc_minifier/tests/ecmascript/to_number.rs index 24ac1034c60be..7c60ac331affb 100644 --- a/crates/oxc_minifier/tests/ecmascript/to_number.rs +++ b/crates/oxc_minifier/tests/ecmascript/to_number.rs @@ -1,16 +1,13 @@ use oxc_allocator::Allocator; use oxc_ast::{AstBuilder, ast::*}; -use oxc_ecmascript::{ - ToNumber, - is_global_reference::{IsGlobalReference, WithoutGlobalReferenceInformation}, -}; +use oxc_ecmascript::{GlobalContext, ToNumber, WithoutGlobalReferenceInformation}; use oxc_span::SPAN; struct GlobalReferenceInformation { is_undefined_shadowed: bool, } -impl<'a> IsGlobalReference<'a> for GlobalReferenceInformation { +impl<'a> GlobalContext<'a> for GlobalReferenceInformation { fn is_global_reference(&self, ident: &IdentifierReference<'a>) -> Option { if ident.name == "undefined" { Some(!self.is_undefined_shadowed) } else { None } } diff --git a/crates/oxc_minifier/tests/ecmascript/to_string.rs b/crates/oxc_minifier/tests/ecmascript/to_string.rs index 54fdcfda0e22f..c5e5f345effc3 100644 --- a/crates/oxc_minifier/tests/ecmascript/to_string.rs +++ b/crates/oxc_minifier/tests/ecmascript/to_string.rs @@ -1,16 +1,13 @@ use oxc_allocator::Allocator; use oxc_ast::{AstBuilder, ast::*}; -use oxc_ecmascript::{ - ToJsString, - is_global_reference::{IsGlobalReference, WithoutGlobalReferenceInformation}, -}; +use oxc_ecmascript::{GlobalContext, ToJsString, WithoutGlobalReferenceInformation}; use oxc_span::SPAN; struct GlobalReferenceInformation { is_undefined_shadowed: bool, } -impl<'a> IsGlobalReference<'a> for GlobalReferenceInformation { +impl<'a> GlobalContext<'a> for GlobalReferenceInformation { fn is_global_reference(&self, ident: &IdentifierReference<'a>) -> Option { if ident.name == "undefined" { Some(!self.is_undefined_shadowed) } else { None } } diff --git a/crates/oxc_minifier/tests/ecmascript/value_type.rs b/crates/oxc_minifier/tests/ecmascript/value_type.rs index 43922fdb0adb1..5ba813ff93529 100644 --- a/crates/oxc_minifier/tests/ecmascript/value_type.rs +++ b/crates/oxc_minifier/tests/ecmascript/value_type.rs @@ -1,8 +1,8 @@ use oxc_allocator::Allocator; use oxc_ast::ast::{IdentifierReference, Statement}; use oxc_ecmascript::{ + GlobalContext, constant_evaluation::{DetermineValueType, ValueType}, - is_global_reference::IsGlobalReference, }; use oxc_parser::Parser; use oxc_span::SourceType; @@ -11,7 +11,7 @@ struct GlobalReferenceChecker { global_variable_names: Vec, } -impl<'a> IsGlobalReference<'a> for GlobalReferenceChecker { +impl<'a> GlobalContext<'a> for GlobalReferenceChecker { fn is_global_reference(&self, ident: &IdentifierReference<'a>) -> Option { Some(self.global_variable_names.iter().any(|name| name == ident.name.as_str())) } diff --git a/crates/oxc_transformer/src/es2018/object_rest_spread.rs b/crates/oxc_transformer/src/es2018/object_rest_spread.rs index 9db1a6305e53f..0aab31f8ef58f 100644 --- a/crates/oxc_transformer/src/es2018/object_rest_spread.rs +++ b/crates/oxc_transformer/src/es2018/object_rest_spread.rs @@ -34,9 +34,7 @@ use serde::Deserialize; use oxc_allocator::{Box as ArenaBox, GetAddress, TakeIn, Vec as ArenaVec}; use oxc_ast::{NONE, ast::*}; use oxc_diagnostics::OxcDiagnostic; -use oxc_ecmascript::{ - BoundNames, ToJsString, is_global_reference::WithoutGlobalReferenceInformation, -}; +use oxc_ecmascript::{BoundNames, ToJsString, WithoutGlobalReferenceInformation}; use oxc_semantic::{ScopeFlags, ScopeId, SymbolFlags}; use oxc_span::{GetSpan, SPAN}; use oxc_traverse::{Ancestor, MaybeBoundIdentifier, Traverse};