From 462925187a72f1dbcec73568e9421bac0d6d50fc Mon Sep 17 00:00:00 2001 From: YanWQ-monad Date: Mon, 18 Aug 2025 04:18:10 +0800 Subject: [PATCH 1/2] fix(ecmascript): skip array length evaluation if there are any spread elements Co-authored-by: GZTime --- .../src/constant_evaluation/mod.rs | 35 ++++++++++--------- 1 file changed, 19 insertions(+), 16 deletions(-) diff --git a/crates/oxc_ecmascript/src/constant_evaluation/mod.rs b/crates/oxc_ecmascript/src/constant_evaluation/mod.rs index d0868cdf86965..f06bb518b3f5f 100644 --- a/crates/oxc_ecmascript/src/constant_evaluation/mod.rs +++ b/crates/oxc_ecmascript/src/constant_evaluation/mod.rs @@ -495,15 +495,7 @@ impl<'a> ConstantEvaluation<'a> for StaticMemberExpression<'a> { _target_ty: Option, ) -> Option> { match self.property.name.as_str() { - "length" => { - if let Some(ConstantValue::String(s)) = self.object.evaluate_value(ctx) { - Some(ConstantValue::Number(s.encode_utf16().count().to_f64().unwrap())) - } else if let Expression::ArrayExpression(arr) = &self.object { - Some(ConstantValue::Number(arr.elements.len().to_f64().unwrap())) - } else { - None - } - } + "length" => evaluate_value_length(&self.object, ctx), _ => None, } } @@ -517,19 +509,30 @@ impl<'a> ConstantEvaluation<'a> for ComputedMemberExpression<'a> { ) -> Option> { match &self.expression { Expression::StringLiteral(s) if s.value == "length" => { - if let Some(ConstantValue::String(s)) = self.object.evaluate_value(ctx) { - Some(ConstantValue::Number(s.encode_utf16().count().to_f64().unwrap())) - } else if let Expression::ArrayExpression(arr) = &self.object { - Some(ConstantValue::Number(arr.elements.len().to_f64().unwrap())) - } else { - None - } + evaluate_value_length(&self.object, ctx) } _ => None, } } } +fn evaluate_value_length<'a>( + object: &Expression<'a>, + ctx: &impl ConstantEvaluationCtx<'a>, +) -> Option> { + if let Some(ConstantValue::String(s)) = object.evaluate_value(ctx) { + Some(ConstantValue::Number(s.encode_utf16().count().to_f64().unwrap())) + } else if let Expression::ArrayExpression(arr) = object { + if arr.elements.iter().any(|e| matches!(e, ArrayExpressionElement::SpreadElement(_))) { + None + } else { + Some(ConstantValue::Number(arr.elements.len().to_f64().unwrap())) + } + } else { + None + } +} + impl<'a> ConstantEvaluation<'a> for CallExpression<'a> { fn evaluate_value_to( &self, From 305cee84ec425c83982cf4ea13ad1a574289e1d2 Mon Sep 17 00:00:00 2001 From: Boshen Date: Wed, 20 Aug 2025 10:56:00 +0800 Subject: [PATCH 2/2] add test --- crates/oxc_minifier/src/peephole/fold_constants.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/crates/oxc_minifier/src/peephole/fold_constants.rs b/crates/oxc_minifier/src/peephole/fold_constants.rs index 7624745ed7eae..02f78eed2329d 100644 --- a/crates/oxc_minifier/src/peephole/fold_constants.rs +++ b/crates/oxc_minifier/src/peephole/fold_constants.rs @@ -1778,6 +1778,7 @@ mod test { // Cannot fold fold("x = [foo(), 0].length", "x = [foo(),0].length"); fold_same("x = y.length"); + fold_same("[...[1, 2, 3]].length"); } #[test]