diff --git a/.changeset/empty-steaks-dream.md b/.changeset/empty-steaks-dream.md new file mode 100644 index 000000000000..fc00c6afceaa --- /dev/null +++ b/.changeset/empty-steaks-dream.md @@ -0,0 +1,6 @@ +--- +swc_ecma_ast: minor +swc_ecma_utils: major +--- + +perf(es/utils): Restrict recursion of `get_type` diff --git a/crates/swc_ecma_minifier/src/compress/optimize/bools.rs b/crates/swc_ecma_minifier/src/compress/optimize/bools.rs index cbd015c374e2..c541ee8c34ca 100644 --- a/crates/swc_ecma_minifier/src/compress/optimize/bools.rs +++ b/crates/swc_ecma_minifier/src/compress/optimize/bools.rs @@ -42,13 +42,13 @@ impl Optimizer<'_> { } if !is_ret_val_ignored { - if let Known(Type::Bool) = e.left.get_type() { + if let Known(Type::Bool) = e.left.get_type(self.ctx.expr_ctx) { } else { // Don't change type. return false; } - if let Known(Type::Bool) = e.right.get_type() { + if let Known(Type::Bool) = e.right.get_type(self.ctx.expr_ctx) { } else { // Don't change type. return false; @@ -277,8 +277,8 @@ impl Optimizer<'_> { _ => return None, }; - let lt = left.get_type(); - let rt = right.get_type(); + let lt = left.get_type(self.ctx.expr_ctx); + let rt = right.get_type(self.ctx.expr_ctx); if let Value::Known(lt) = lt { if let Value::Known(rt) = rt { match (lt, rt) { diff --git a/crates/swc_ecma_minifier/src/compress/optimize/mod.rs b/crates/swc_ecma_minifier/src/compress/optimize/mod.rs index 138a1efd6f6f..3679b542ccec 100644 --- a/crates/swc_ecma_minifier/src/compress/optimize/mod.rs +++ b/crates/swc_ecma_minifier/src/compress/optimize/mod.rs @@ -1630,11 +1630,11 @@ impl VisitMut for Optimizer<'_> { self.optimize_bin_and_or(n); if n.op == op!(bin, "+") { - if let Known(Type::Str) = n.left.get_type() { + if let Known(Type::Str) = n.left.get_type(self.ctx.expr_ctx) { self.optimize_expr_in_str_ctx(&mut n.right); } - if let Known(Type::Str) = n.right.get_type() { + if let Known(Type::Str) = n.right.get_type(self.ctx.expr_ctx) { self.optimize_expr_in_str_ctx(&mut n.left); } } diff --git a/crates/swc_ecma_minifier/src/compress/optimize/ops.rs b/crates/swc_ecma_minifier/src/compress/optimize/ops.rs index 5025e0dfd404..b4bc8e4e70bb 100644 --- a/crates/swc_ecma_minifier/src/compress/optimize/ops.rs +++ b/crates/swc_ecma_minifier/src/compress/optimize/ops.rs @@ -58,8 +58,8 @@ impl Optimizer<'_> { } } - let lt = e.left.get_type(); - let rt = e.right.get_type(); + let lt = e.left.get_type(self.ctx.expr_ctx); + let rt = e.right.get_type(self.ctx.expr_ctx); if e.op == op!("===") { if let Known(lt) = lt { @@ -127,7 +127,10 @@ impl Optimizer<'_> { .into(), ) }; - match (n.left.get_type().opt()?, n.right.get_type().opt()?) { + match ( + n.left.get_type(self.ctx.expr_ctx).opt()?, + n.right.get_type(self.ctx.expr_ctx).opt()?, + ) { // Abort if types differ, or one of them is unknown. (lt, rt) if lt != rt => {} (Type::Obj, Type::Obj) => {} @@ -181,7 +184,7 @@ impl Optimizer<'_> { | Expr::Bin(BinExpr { op: op!("<"), .. }) | Expr::Bin(BinExpr { op: op!(">="), .. }) | Expr::Bin(BinExpr { op: op!(">"), .. }) => { - if let Known(Type::Bool) = arg.get_type() { + if let Known(Type::Bool) = arg.get_type(self.ctx.expr_ctx) { self.changed = true; report_change!("Optimizing: `!!expr` => `expr`"); *e = *arg.take(); @@ -299,14 +302,14 @@ impl Optimizer<'_> { _ => {} } - let lt = bin.left.get_type(); + let lt = bin.left.get_type(self.ctx.expr_ctx); match lt { // Don't change type Known(Type::Bool) => {} _ => return, } - let rt = bin.right.get_type(); + let rt = bin.right.get_type(self.ctx.expr_ctx); match rt { Known(Type::Bool) => {} _ => return, diff --git a/crates/swc_ecma_minifier/src/compress/optimize/sequences.rs b/crates/swc_ecma_minifier/src/compress/optimize/sequences.rs index 3924f631322d..a91aea93ac34 100644 --- a/crates/swc_ecma_minifier/src/compress/optimize/sequences.rs +++ b/crates/swc_ecma_minifier/src/compress/optimize/sequences.rs @@ -2371,7 +2371,7 @@ impl Optimizer<'_> { Mergable::Drop => return Ok(false), }; - let a_type = a_right.as_deref().map(|a| a.get_type()); + let a_type = a_right.as_deref().map(|a| a.get_type(self.ctx.expr_ctx)); if let Some(a_right) = a_right { if a_right.is_this() || a_right.is_ident_ref_to("arguments") { @@ -2484,7 +2484,7 @@ impl Optimizer<'_> { let Some(a_type) = a_type else { return Ok(false); }; - let b_type = b.right.get_type(); + let b_type = b.right.get_type(self.ctx.expr_ctx); if let Some(a_op) = a_op { if can_drop_op_for(a_op, b.op, var_type, a_type, b_type) { diff --git a/crates/swc_ecma_minifier/src/compress/pure/bools.rs b/crates/swc_ecma_minifier/src/compress/pure/bools.rs index b8b775d7a070..fda1b06c3bff 100644 --- a/crates/swc_ecma_minifier/src/compress/pure/bools.rs +++ b/crates/swc_ecma_minifier/src/compress/pure/bools.rs @@ -85,7 +85,7 @@ impl Pure<'_> { matches!(op, op!("==") | op!("===") | op!("!=") | op!("!==")) } - fn can_absorb_negate(e: &Expr) -> bool { + fn can_absorb_negate(e: &Expr, ctx: ExprCtx) -> bool { match e { Expr::Lit(_) => true, Expr::Bin(BinExpr { @@ -93,11 +93,11 @@ impl Pure<'_> { left, right, .. - }) => can_absorb_negate(left) && can_absorb_negate(right), + }) => can_absorb_negate(left, ctx) && can_absorb_negate(right, ctx), Expr::Bin(BinExpr { op, .. }) if is_eq(*op) => true, Expr::Unary(UnaryExpr { op: op!("!"), arg, .. - }) => arg.get_type() == Value::Known(Type::Bool), + }) => arg.get_type(ctx) == Value::Known(Type::Bool), _ => false, } } @@ -123,7 +123,7 @@ impl Pure<'_> { return; }; - let arg_can_negate = can_absorb_negate(arg); + let arg_can_negate = can_absorb_negate(arg, self.expr_ctx); match &mut **arg { Expr::Bin(BinExpr { op, .. }) if is_eq(*op) => { @@ -158,7 +158,7 @@ impl Pure<'_> { } pub(super) fn compress_cmp_with_long_op(&mut self, e: &mut BinExpr) { - fn should_optimize(l: &Expr, r: &Expr, opts: &CompressOptions) -> bool { + fn should_optimize(l: &Expr, r: &Expr, ctx: ExprCtx, opts: &CompressOptions) -> bool { match (l, r) { ( Expr::Unary(UnaryExpr { @@ -168,7 +168,7 @@ impl Pure<'_> { ) => true, _ => { if opts.comparisons { - match (l.get_type(), r.get_type()) { + match (l.get_type(ctx), r.get_type(ctx)) { (Value::Known(lt), Value::Known(rt)) => lt == rt, _ => false, @@ -185,8 +185,8 @@ impl Pure<'_> { _ => return, } - if should_optimize(&e.left, &e.right, self.options) - || should_optimize(&e.right, &e.left, self.options) + if should_optimize(&e.left, &e.right, self.expr_ctx, self.options) + || should_optimize(&e.right, &e.left, self.expr_ctx, self.options) { report_change!("bools: Compressing comparison of `typeof` with literal"); self.changed = true; @@ -226,8 +226,8 @@ impl Pure<'_> { right, .. }) => { - let lt = left.get_type(); - let rt = right.get_type(); + let lt = left.get_type(self.expr_ctx); + let rt = right.get_type(self.expr_ctx); if let (Value::Known(Type::Bool), Value::Known(Type::Bool)) = (lt, rt) { let rb = right.as_pure_bool(self.expr_ctx); diff --git a/crates/swc_ecma_minifier/src/compress/pure/conds.rs b/crates/swc_ecma_minifier/src/compress/pure/conds.rs index c48f8321b4d0..06545c93ecaa 100644 --- a/crates/swc_ecma_minifier/src/compress/pure/conds.rs +++ b/crates/swc_ecma_minifier/src/compress/pure/conds.rs @@ -21,7 +21,7 @@ impl Pure<'_> { let Expr::Cond(cond) = e else { return }; - let lt = cond.cons.get_type(); + let lt = cond.cons.get_type(self.expr_ctx); if let Value::Known(Type::Bool) = lt { let lb = cond.cons.as_pure_bool(self.expr_ctx); if let Value::Known(true) = lb { @@ -59,7 +59,7 @@ impl Pure<'_> { } } - let rt = cond.alt.get_type(); + let rt = cond.alt.get_type(self.expr_ctx); if let Value::Known(Type::Bool) = rt { let rb = cond.alt.as_pure_bool(self.expr_ctx); if let Value::Known(false) = rb { @@ -220,8 +220,8 @@ impl Pure<'_> { return; } - let lt = bin.left.get_type(); - let rt = bin.right.get_type(); + let lt = bin.left.get_type(self.expr_ctx); + let rt = bin.right.get_type(self.expr_ctx); let _lb = bin.left.as_pure_bool(self.expr_ctx); let rb = bin.right.as_pure_bool(self.expr_ctx); diff --git a/crates/swc_ecma_minifier/src/compress/pure/misc.rs b/crates/swc_ecma_minifier/src/compress/pure/misc.rs index 308b1fc0d2f7..98747637c9d1 100644 --- a/crates/swc_ecma_minifier/src/compress/pure/misc.rs +++ b/crates/swc_ecma_minifier/src/compress/pure/misc.rs @@ -1675,8 +1675,8 @@ impl Pure<'_> { _ => return, }; - let lt = cond.cons.get_type(); - let rt = cond.alt.get_type(); + let lt = cond.cons.get_type(self.expr_ctx); + let rt = cond.alt.get_type(self.expr_ctx); match (lt, rt) { (Known(Type::Bool), Known(Type::Bool)) => {} _ => return, diff --git a/crates/swc_ecma_minifier/src/compress/pure/strings.rs b/crates/swc_ecma_minifier/src/compress/pure/strings.rs index 07fd1c96135b..9d41f323b367 100644 --- a/crates/swc_ecma_minifier/src/compress/pure/strings.rs +++ b/crates/swc_ecma_minifier/src/compress/pure/strings.rs @@ -28,11 +28,11 @@ impl Pure<'_> { _ => return, }; - match l_l.get_type() { + match l_l.get_type(self.expr_ctx) { Known(Type::Str) => {} _ => return, } - match r_l.get_type() { + match r_l.get_type(self.expr_ctx) { Known(Type::Str) => {} _ => return, } @@ -487,8 +487,8 @@ impl Pure<'_> { }, ) = &mut *bin.left { - let type_of_second = left.right.get_type(); - let type_of_third = bin.right.get_type(); + let type_of_second = left.right.get_type(self.expr_ctx); + let type_of_third = bin.right.get_type(self.expr_ctx); if let Value::Known(Type::Str) = type_of_second { if let Value::Known(Type::Str) = type_of_third { @@ -534,8 +534,8 @@ impl Pure<'_> { .. }) = e { - let lt = left.get_type(); - let rt = right.get_type(); + let lt = left.get_type(self.expr_ctx); + let rt = right.get_type(self.expr_ctx); if let Value::Known(Type::Str) = lt { if let Value::Known(Type::Str) = rt { match &**left { diff --git a/crates/swc_ecma_minifier/tests/benches-full/react.js b/crates/swc_ecma_minifier/tests/benches-full/react.js index 0db6b584af04..a7bd2916ceda 100644 --- a/crates/swc_ecma_minifier/tests/benches-full/react.js +++ b/crates/swc_ecma_minifier/tests/benches-full/react.js @@ -512,7 +512,8 @@ throw payload._result; } function isValidElementType(type) { - return 'string' == typeof type || 'function' == typeof type || type === exports.Fragment || type === exports.Profiler || type === REACT_DEBUG_TRACING_MODE_TYPE || type === exports.StrictMode || type === exports.Suspense || type === REACT_SUSPENSE_LIST_TYPE || type === REACT_LEGACY_HIDDEN_TYPE || 'object' == typeof type && null !== type && (type.$$typeof === REACT_LAZY_TYPE || type.$$typeof === REACT_MEMO_TYPE || type.$$typeof === REACT_PROVIDER_TYPE || type.$$typeof === REACT_CONTEXT_TYPE || type.$$typeof === REACT_FORWARD_REF_TYPE || type.$$typeof === REACT_FUNDAMENTAL_TYPE || type.$$typeof === REACT_BLOCK_TYPE || type[0] === REACT_SERVER_BLOCK_TYPE); + return 'string' == typeof type || 'function' == typeof type || type === exports.Fragment || type === exports.Profiler || type === REACT_DEBUG_TRACING_MODE_TYPE || type === exports.StrictMode || type === exports.Suspense || type === REACT_SUSPENSE_LIST_TYPE || type === REACT_LEGACY_HIDDEN_TYPE || 'object' == typeof type && null !== type && (type.$$typeof === REACT_LAZY_TYPE || type.$$typeof === REACT_MEMO_TYPE || type.$$typeof === REACT_PROVIDER_TYPE || type.$$typeof === REACT_CONTEXT_TYPE || type.$$typeof === REACT_FORWARD_REF_TYPE || type.$$typeof === REACT_FUNDAMENTAL_TYPE || type.$$typeof === REACT_BLOCK_TYPE || type[0] === REACT_SERVER_BLOCK_TYPE) || !1 // Note: typeof might be other than 'symbol' or 'number' (e.g. if it's a polyfill). + ; } function resolveDispatcher() { var dispatcher = ReactCurrentDispatcher.current; diff --git a/crates/swc_ecma_minifier/tests/fixture/next/styled-components/1/output.js b/crates/swc_ecma_minifier/tests/fixture/next/styled-components/1/output.js index f23d5b19c071..d808cc0ec162 100644 --- a/crates/swc_ecma_minifier/tests/fixture/next/styled-components/1/output.js +++ b/crates/swc_ecma_minifier/tests/fixture/next/styled-components/1/output.js @@ -6701,7 +6701,7 @@ * LICENSE file in the root directory of this source tree. */ var u, b = Symbol.for("react.element"), c = Symbol.for("react.portal"), d = Symbol.for("react.fragment"), e = Symbol.for("react.strict_mode"), f = Symbol.for("react.profiler"), g = Symbol.for("react.provider"), h = Symbol.for("react.context"), k = Symbol.for("react.server_context"), l = Symbol.for("react.forward_ref"), m = Symbol.for("react.suspense"), n = Symbol.for("react.suspense_list"), p = Symbol.for("react.memo"), q = Symbol.for("react.lazy"), t = Symbol.for("react.offscreen"); u = Symbol.for("react.module.reference"), exports.isValidElementType = function(a) { - return "string" == typeof a || "function" == typeof a || a === d || a === f || a === e || a === m || a === n || a === t || "object" == typeof a && null !== a && (a.$$typeof === q || a.$$typeof === p || a.$$typeof === g || a.$$typeof === h || a.$$typeof === l || a.$$typeof === u || void 0 !== a.getModuleId); + return "string" == typeof a || "function" == typeof a || a === d || a === f || a === e || a === m || a === n || a === t || "object" == typeof a && null !== a && (a.$$typeof === q || a.$$typeof === p || a.$$typeof === g || a.$$typeof === h || a.$$typeof === l || a.$$typeof === u || void 0 !== a.getModuleId) || !1; }, exports.typeOf = function(a) { if ("object" == typeof a && null !== a) { var r = a.$$typeof; diff --git a/crates/swc_ecma_minifier/tests/fixture/next/syncfusion/933-e9f9a6bf671b96fc/output.js b/crates/swc_ecma_minifier/tests/fixture/next/syncfusion/933-e9f9a6bf671b96fc/output.js index 2f8f825a6329..21ca64cf8622 100644 --- a/crates/swc_ecma_minifier/tests/fixture/next/syncfusion/933-e9f9a6bf671b96fc/output.js +++ b/crates/swc_ecma_minifier/tests/fixture/next/syncfusion/933-e9f9a6bf671b96fc/output.js @@ -27994,7 +27994,7 @@ */ ToolbarRenderer.prototype.renderColorPickerDropDown = function(args, item, colorPicker, defaultColor) { var range, _this = this, proxy = this, css = classes /* CLS_RTE_ELEMENTS */ .i7 + ' ' + classes /* CLS_TB_BTN */ .Fs + (this.parent.inlineMode ? ' ' + classes /* CLS_INLINE_DROPDOWN */ .ZV : ''); - css += ' ' + ('backgroundcolor' === item ? classes /* CLS_BACKGROUND_COLOR_DROPDOWN */ .Z8 : classes /* CLS_FONT_COLOR_DROPDOWN */ .UQ) + ' ' + this.parent.cssClass; + css += ' ' + ('backgroundcolor' === item ? classes /* CLS_BACKGROUND_COLOR_DROPDOWN */ .Z8 : classes /* CLS_FONT_COLOR_DROPDOWN */ .UQ), css += ' ' + this.parent.cssClass; var content = proxy.parent.createElement('span', { className: classes /* CLS_COLOR_CONTENT */ .uN }), inlineEle = proxy.parent.createElement('span', { @@ -30011,7 +30011,7 @@ * @returns {boolean} - returns the boolean value * @hidden */ function isEditableValueEmpty(value) { - return '


' === value || '<p><br></p>' === value || '

' === value || '<div><br></div>' === value || '
' === value || '<br>' === value || '' === value; + return '


' === value || '<p><br></p>' === value || '

' === value || '<div><br></div>' === value || '
' === value || '<br>' === value || '' === value || !1; } /** * @param {string} value - specifies the string value diff --git a/crates/swc_ecma_minifier/tests/projects/output/react-17.0.1.js b/crates/swc_ecma_minifier/tests/projects/output/react-17.0.1.js index f0b3f33e8589..580b4009b5bc 100644 --- a/crates/swc_ecma_minifier/tests/projects/output/react-17.0.1.js +++ b/crates/swc_ecma_minifier/tests/projects/output/react-17.0.1.js @@ -514,7 +514,8 @@ throw payload._result; } function isValidElementType(type) { - return "string" == typeof type || "function" == typeof type || type === exports.Fragment || type === exports.Profiler || type === REACT_DEBUG_TRACING_MODE_TYPE || type === exports.StrictMode || type === exports.Suspense || type === REACT_SUSPENSE_LIST_TYPE || type === REACT_LEGACY_HIDDEN_TYPE || "object" == typeof type && null !== type && (type.$$typeof === REACT_LAZY_TYPE || type.$$typeof === REACT_MEMO_TYPE || type.$$typeof === REACT_PROVIDER_TYPE || type.$$typeof === REACT_CONTEXT_TYPE || type.$$typeof === REACT_FORWARD_REF_TYPE || type.$$typeof === REACT_FUNDAMENTAL_TYPE || type.$$typeof === REACT_BLOCK_TYPE || type[0] === REACT_SERVER_BLOCK_TYPE); + return "string" == typeof type || "function" == typeof type || type === exports.Fragment || type === exports.Profiler || type === REACT_DEBUG_TRACING_MODE_TYPE || type === exports.StrictMode || type === exports.Suspense || type === REACT_SUSPENSE_LIST_TYPE || type === REACT_LEGACY_HIDDEN_TYPE || "object" == typeof type && null !== type && (type.$$typeof === REACT_LAZY_TYPE || type.$$typeof === REACT_MEMO_TYPE || type.$$typeof === REACT_PROVIDER_TYPE || type.$$typeof === REACT_CONTEXT_TYPE || type.$$typeof === REACT_FORWARD_REF_TYPE || type.$$typeof === REACT_FUNDAMENTAL_TYPE || type.$$typeof === REACT_BLOCK_TYPE || type[0] === REACT_SERVER_BLOCK_TYPE) || !1 // Note: typeof might be other than 'symbol' or 'number' (e.g. if it's a polyfill). + ; } function resolveDispatcher() { var dispatcher = ReactCurrentDispatcher.current; diff --git a/crates/swc_ecma_transforms_optimization/src/simplify/expr/mod.rs b/crates/swc_ecma_transforms_optimization/src/simplify/expr/mod.rs index d61252bf2dc1..d2112068ff3c 100644 --- a/crates/swc_ecma_transforms_optimization/src/simplify/expr/mod.rs +++ b/crates/swc_ecma_transforms_optimization/src/simplify/expr/mod.rs @@ -445,7 +445,7 @@ impl SimplifyExpr { } } - match expr.get_type() { + match expr.get_type(self.expr_ctx) { // String concatenation Known(StringType) => match expr { Expr::Bin(BinExpr { @@ -911,8 +911,8 @@ impl SimplifyExpr { if (lv.is_unknown() && rv.is_unknown()) || op == op!(bin, "+") - && (!left.get_type().casted_to_number_on_add() - || !right.get_type().casted_to_number_on_add()) + && (!left.get_type(self.expr_ctx).casted_to_number_on_add() + || !right.get_type(self.expr_ctx).casted_to_number_on_add()) { return Unknown; } @@ -1067,7 +1067,7 @@ impl SimplifyExpr { } // Try to evaluate based on the general type. - let (lt, rt) = (left.get_type(), right.get_type()); + let (lt, rt) = (left.get_type(self.expr_ctx), right.get_type(self.expr_ctx)); if let (Known(StringType), Known(StringType)) = (lt, rt) { if let (Known(lv), Known(rv)) = ( @@ -1099,7 +1099,10 @@ impl SimplifyExpr { /// https://tc39.github.io/ecma262/#sec-abstract-equality-comparison fn perform_abstract_eq_cmp(&mut self, span: Span, left: &Expr, right: &Expr) -> Value { - let (lt, rt) = (try_val!(left.get_type()), try_val!(right.get_type())); + let (lt, rt) = ( + try_val!(left.get_type(self.expr_ctx)), + try_val!(right.get_type(self.expr_ctx)), + ); if lt == rt { return self.perform_strict_eq_cmp(left, right); @@ -1171,7 +1174,10 @@ impl SimplifyExpr { _ => {} } - let (lt, rt) = (try_val!(left.get_type()), try_val!(right.get_type())); + let (lt, rt) = ( + try_val!(left.get_type(self.expr_ctx)), + try_val!(right.get_type(self.expr_ctx)), + ); // Strict equality can only be true for values of the same type. if lt != rt { return Known(false); diff --git a/crates/swc_ecma_usage_analyzer/src/analyzer/mod.rs b/crates/swc_ecma_usage_analyzer/src/analyzer/mod.rs index bae4d9443de6..9e62aece3afc 100644 --- a/crates/swc_ecma_usage_analyzer/src/analyzer/mod.rs +++ b/crates/swc_ecma_usage_analyzer/src/analyzer/mod.rs @@ -276,15 +276,19 @@ where match &n.left { AssignTarget::Pat(p) => { for id in find_pat_ids(p) { - self.data - .report_assign(self.ctx, id, is_op_assign, n.right.get_type()) + self.data.report_assign( + self.ctx, + id, + is_op_assign, + n.right.get_type(self.expr_ctx), + ) } } AssignTarget::Simple(e) => { self.report_assign_expr_if_ident( e.as_ident().map(Ident::from).as_ref(), is_op_assign, - n.right.get_type(), + n.right.get_type(self.expr_ctx), ); self.mark_mutation_if_member(e.as_member()) } @@ -1304,7 +1308,10 @@ where let ctx = Ctx { inline_prevented: self.ctx.inline_prevented || prevent_inline, in_pat_of_var_decl: true, - in_pat_of_var_decl_with_init: e.init.as_ref().map(|init| init.get_type()), + in_pat_of_var_decl_with_init: e + .init + .as_ref() + .map(|init| init.get_type(self.expr_ctx)), in_decl_with_no_side_effect_for_member_access: e .init .as_deref() diff --git a/crates/swc_ecma_utils/src/lib.rs b/crates/swc_ecma_utils/src/lib.rs index 14d4558f2305..18dd69b7bd98 100644 --- a/crates/swc_ecma_utils/src/lib.rs +++ b/crates/swc_ecma_utils/src/lib.rs @@ -708,8 +708,8 @@ pub trait ExprExt { /// Apply the supplied predicate against all possible result Nodes of the /// expression. #[inline(always)] - fn get_type(&self) -> Value { - get_type(self.as_expr()) + fn get_type(&self, ctx: ExprCtx) -> Value { + get_type(self.as_expr(), ctx) } #[inline(always)] @@ -2704,7 +2704,7 @@ fn cast_to_bool(expr: &Expr, ctx: ExprCtx) -> (Purity, BoolValue) { ref right, .. }) => { - if left.get_type() != Known(BoolType) || right.get_type() != Known(BoolType) { + if left.get_type(ctx) != Known(BoolType) || right.get_type(ctx) != Known(BoolType) { return (MayBeImpure, Unknown); } @@ -3013,13 +3013,17 @@ fn as_pure_string(expr: &Expr, ctx: ExprCtx) -> Value> { } } -fn get_type(expr: &Expr) -> Value { +fn get_type(expr: &Expr, ctx: ExprCtx) -> Value { + let Some(ctx) = ctx.consume_depth() else { + return Unknown; + }; + match expr { Expr::Assign(AssignExpr { ref right, op: op!("="), .. - }) => right.get_type(), + }) => right.get_type(ctx), Expr::Member(MemberExpr { obj, @@ -3036,7 +3040,7 @@ fn get_type(expr: &Expr) -> Value { Expr::Seq(SeqExpr { ref exprs, .. }) => exprs .last() .expect("sequence expression should not be empty") - .get_type(), + .get_type(ctx), Expr::Bin(BinExpr { ref left, @@ -3054,7 +3058,7 @@ fn get_type(expr: &Expr) -> Value { cons: ref left, alt: ref right, .. - }) => and(left.get_type(), right.get_type()), + }) => and(left.get_type(ctx), right.get_type(ctx)), Expr::Bin(BinExpr { ref left, @@ -3062,12 +3066,12 @@ fn get_type(expr: &Expr) -> Value { ref right, .. }) => { - let rt = right.get_type(); + let rt = right.get_type(ctx); if rt == Known(StringType) { return Known(StringType); } - let lt = left.get_type(); + let lt = left.get_type(ctx); if lt == Known(StringType) { return Known(StringType); } @@ -3096,7 +3100,7 @@ fn get_type(expr: &Expr) -> Value { ref right, .. }) => { - if right.get_type() == Known(StringType) { + if right.get_type(ctx) == Known(StringType) { return Known(StringType); } Unknown