mirror of
https://github.com/oxc-project/oxc.git
synced 2026-11-04 10:29:58 +00:00
refactor(ecmascript): use value_type in to_primitive (#9108)
so that it supports more cases automatically.
This commit is contained in:
2 files changed
+77
-70
No files matched your search
@@ -117,10 +117,12 @@ impl MayHaveSideEffects for BinaryExpression<'_> {
|
||||
true
|
||||
}
|
||||
BinaryOperator::Addition => {
|
||||
if self.left.to_primitive_returns_string() == Some(true)
|
||||
|| self.right.to_primitive_returns_string() == Some(true)
|
||||
if self.left.to_primitive_returns_string(is_global_reference) == Some(true)
|
||||
|| self.right.to_primitive_returns_string(is_global_reference) == Some(true)
|
||||
{
|
||||
let other_side = if self.left.to_primitive_returns_string() == Some(true) {
|
||||
let other_side = if self.left.to_primitive_returns_string(is_global_reference)
|
||||
== Some(true)
|
||||
{
|
||||
&self.right
|
||||
} else {
|
||||
&self.left
|
||||
|
||||
@@ -1,12 +1,18 @@
|
||||
use oxc_ast::ast::*;
|
||||
|
||||
use crate::is_global_reference::IsGlobalReference;
|
||||
use crate::{
|
||||
constant_evaluation::{DetermineValueType, ValueType},
|
||||
is_global_reference::IsGlobalReference,
|
||||
};
|
||||
|
||||
/// `ToPrimitive`
|
||||
///
|
||||
/// <https://tc39.es/ecma262/multipage/abstract-operations.html#sec-toprimitive>
|
||||
pub trait ToPrimitive<'a> {
|
||||
fn to_primitive_returns_string(&self) -> Option<bool>;
|
||||
fn to_primitive_returns_string(
|
||||
&self,
|
||||
is_global_reference: &impl IsGlobalReference,
|
||||
) -> Option<bool>;
|
||||
fn to_primitive_returns_symbol(
|
||||
&self,
|
||||
is_global_reference: &impl IsGlobalReference,
|
||||
@@ -18,22 +24,32 @@ pub trait ToPrimitive<'a> {
|
||||
}
|
||||
|
||||
impl ToPrimitive<'_> for Expression<'_> {
|
||||
fn to_primitive_returns_string(&self) -> Option<bool> {
|
||||
match self {
|
||||
Expression::StringLiteral(_)
|
||||
| Expression::TemplateLiteral(_)
|
||||
| Expression::RegExpLiteral(_)
|
||||
| Expression::ArrayExpression(_) => Some(true),
|
||||
// unless `Symbol.toPrimitive`, `valueOf`, `toString` is overridden,
|
||||
// ToPrimitive for an object returns `"[object Object]"`
|
||||
Expression::ObjectExpression(obj) => {
|
||||
if maybe_object_with_to_primitive_related_properties_overridden(obj) {
|
||||
None
|
||||
} else {
|
||||
Some(true)
|
||||
fn to_primitive_returns_string(
|
||||
&self,
|
||||
is_global_reference: &impl IsGlobalReference,
|
||||
) -> Option<bool> {
|
||||
match self.value_type(is_global_reference) {
|
||||
ValueType::String => Some(true),
|
||||
ValueType::Number
|
||||
| ValueType::BigInt
|
||||
| ValueType::Boolean
|
||||
| ValueType::Null
|
||||
| ValueType::Undefined => Some(false),
|
||||
ValueType::Object | ValueType::Undetermined => {
|
||||
match self {
|
||||
Expression::RegExpLiteral(_) | Expression::ArrayExpression(_) => Some(true),
|
||||
// unless `Symbol.toPrimitive`, `valueOf`, `toString` is overridden,
|
||||
// ToPrimitive for an object returns `"[object Object]"`
|
||||
Expression::ObjectExpression(obj) => {
|
||||
if maybe_object_with_to_primitive_related_properties_overridden(obj) {
|
||||
None
|
||||
} else {
|
||||
Some(true)
|
||||
}
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,34 +57,28 @@ impl ToPrimitive<'_> for Expression<'_> {
|
||||
&self,
|
||||
is_global_reference: &impl IsGlobalReference,
|
||||
) -> Option<bool> {
|
||||
match self {
|
||||
Expression::Identifier(ident) => {
|
||||
if matches!(ident.name.as_str(), "Infinity" | "NaN" | "undefined")
|
||||
&& is_global_reference.is_global_reference(ident) == Some(true)
|
||||
{
|
||||
Some(false)
|
||||
} else {
|
||||
None
|
||||
match self.value_type(is_global_reference) {
|
||||
ValueType::String
|
||||
| ValueType::Number
|
||||
| ValueType::BigInt
|
||||
| ValueType::Boolean
|
||||
| ValueType::Null
|
||||
| ValueType::Undefined => Some(false),
|
||||
ValueType::Object | ValueType::Undetermined => {
|
||||
match self {
|
||||
Expression::RegExpLiteral(_) | Expression::ArrayExpression(_) => Some(false),
|
||||
// unless `Symbol.toPrimitive`, `valueOf`, `toString` is overridden,
|
||||
// ToPrimitive for an object returns `"[object Object]"`
|
||||
Expression::ObjectExpression(obj) => {
|
||||
if maybe_object_with_to_primitive_related_properties_overridden(obj) {
|
||||
None
|
||||
} else {
|
||||
Some(false)
|
||||
}
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
Expression::StringLiteral(_)
|
||||
| Expression::TemplateLiteral(_)
|
||||
| Expression::NullLiteral(_)
|
||||
| Expression::NumericLiteral(_)
|
||||
| Expression::BigIntLiteral(_)
|
||||
| Expression::BooleanLiteral(_)
|
||||
| Expression::RegExpLiteral(_)
|
||||
| Expression::ArrayExpression(_) => Some(false),
|
||||
// unless `Symbol.toPrimitive`, `valueOf`, `toString` is overridden,
|
||||
// ToPrimitive for an object returns `"[object Object]"`
|
||||
Expression::ObjectExpression(obj) => {
|
||||
if maybe_object_with_to_primitive_related_properties_overridden(obj) {
|
||||
None
|
||||
} else {
|
||||
Some(false)
|
||||
}
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -76,33 +86,28 @@ impl ToPrimitive<'_> for Expression<'_> {
|
||||
&self,
|
||||
is_global_reference: &impl IsGlobalReference,
|
||||
) -> Option<bool> {
|
||||
match self {
|
||||
Expression::Identifier(ident) => {
|
||||
if matches!(ident.name.as_str(), "Infinity" | "NaN" | "undefined")
|
||||
&& is_global_reference.is_global_reference(ident) == Some(true)
|
||||
{
|
||||
Some(false)
|
||||
} else {
|
||||
None
|
||||
match self.value_type(is_global_reference) {
|
||||
ValueType::String
|
||||
| ValueType::Number
|
||||
| ValueType::Boolean
|
||||
| ValueType::Null
|
||||
| ValueType::Undefined => Some(false),
|
||||
ValueType::BigInt => Some(true),
|
||||
ValueType::Object | ValueType::Undetermined => {
|
||||
match self {
|
||||
Expression::RegExpLiteral(_) | Expression::ArrayExpression(_) => Some(false),
|
||||
// unless `Symbol.toPrimitive`, `valueOf`, `toString` is overridden,
|
||||
// ToPrimitive for an object returns `"[object Object]"`
|
||||
Expression::ObjectExpression(obj) => {
|
||||
if maybe_object_with_to_primitive_related_properties_overridden(obj) {
|
||||
None
|
||||
} else {
|
||||
Some(false)
|
||||
}
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
Expression::StringLiteral(_)
|
||||
| Expression::TemplateLiteral(_)
|
||||
| Expression::NullLiteral(_)
|
||||
| Expression::NumericLiteral(_)
|
||||
| Expression::BooleanLiteral(_)
|
||||
| Expression::RegExpLiteral(_)
|
||||
| Expression::ArrayExpression(_) => Some(false),
|
||||
// unless `Symbol.toPrimitive`, `valueOf`, `toString` is overridden,
|
||||
// ToPrimitive for an object returns `"[object Object]"`
|
||||
Expression::ObjectExpression(obj) => {
|
||||
if maybe_object_with_to_primitive_related_properties_overridden(obj) {
|
||||
None
|
||||
} else {
|
||||
Some(false)
|
||||
}
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user