diff --git a/.changeset/pink-gifts-applaud.md b/.changeset/pink-gifts-applaud.md new file mode 100644 index 000000000000..5e99f1319919 --- /dev/null +++ b/.changeset/pink-gifts-applaud.md @@ -0,0 +1,6 @@ +--- +swc_ecma_minifier: patch +swc_core: patch +--- + +fix(es/minifier): Prevent array destructuring optimization in assignment contexts diff --git a/crates/swc_ecma_minifier/src/compress/pure/evaluate.rs b/crates/swc_ecma_minifier/src/compress/pure/evaluate.rs index 04a70c2ae158..2a06ae8b371c 100644 --- a/crates/swc_ecma_minifier/src/compress/pure/evaluate.rs +++ b/crates/swc_ecma_minifier/src/compress/pure/evaluate.rs @@ -73,6 +73,18 @@ impl Pure<'_> { return; } + // Don't optimize arrays used as assignment targets in destructuring + // assignments, as delete operands, or as arguments to update operators + // (++/--). This prevents invalid transformations like: [obj.prop] = + // [true] => [!0] = [!0] + if self.ctx.intersects( + Ctx::IN_DELETE + .union(Ctx::IS_UPDATE_ARG) + .union(Ctx::IS_LHS_OF_ASSIGN), + ) { + return; + } + let Expr::Array(ArrayLit { elems, .. }) = e else { return; }; diff --git a/crates/swc_ecma_minifier/tests/fixture/issues/11084/config.json b/crates/swc_ecma_minifier/tests/fixture/issues/11084/config.json new file mode 100644 index 000000000000..cffa66eebd92 --- /dev/null +++ b/crates/swc_ecma_minifier/tests/fixture/issues/11084/config.json @@ -0,0 +1,5 @@ +{ + "booleans": true, + "properties": true, + "evaluate": true +} diff --git a/crates/swc_ecma_minifier/tests/fixture/issues/11084/input.js b/crates/swc_ecma_minifier/tests/fixture/issues/11084/input.js new file mode 100644 index 000000000000..db1624c2014f --- /dev/null +++ b/crates/swc_ecma_minifier/tests/fixture/issues/11084/input.js @@ -0,0 +1,19 @@ +// Test case 1: Object property destructuring assignment +const bin = { hasMore: false, hasDisorder: false }; +[bin.hasMore, bin.hasDisorder] = [true, true]; +console.log(bin.hasMore, bin.hasDisorder); + +// Test case 2: Array element destructuring assignment +const arr = [1, 2]; +[arr[0], arr[1]] = [arr[1], arr[0]]; +console.log(arr); + +// Test case 3: Nested object destructuring +const obj = { a: { x: 0 }, b: { y: 0 } }; +[obj.a.x, obj.b.y] = [10, 20]; +console.log(obj.a.x, obj.b.y); + +// Test case 4: Mixed literals and expressions +const state = { flag: false }; +[state.flag] = [true]; +console.log(state.flag); diff --git a/crates/swc_ecma_minifier/tests/fixture/issues/11084/output.js b/crates/swc_ecma_minifier/tests/fixture/issues/11084/output.js new file mode 100644 index 000000000000..47632b88c272 --- /dev/null +++ b/crates/swc_ecma_minifier/tests/fixture/issues/11084/output.js @@ -0,0 +1,42 @@ +// Test case 1: Object property destructuring assignment +const bin = { + hasMore: !1, + hasDisorder: !1 +}; +[bin.hasMore, bin.hasDisorder] = [ + !0, + !0 +]; +console.log(bin.hasMore, bin.hasDisorder); +// Test case 2: Array element destructuring assignment +const arr = [ + 1, + 2 +]; +[arr[0], arr[1]] = [ + arr[1], + arr[0] +]; +console.log(arr); +// Test case 3: Nested object destructuring +const obj = { + a: { + x: 0 + }, + b: { + y: 0 + } +}; +[obj.a.x, obj.b.y] = [ + 10, + 20 +]; +console.log(obj.a.x, obj.b.y); +// Test case 4: Mixed literals and expressions +const state = { + flag: !1 +}; +[state.flag] = [ + !0 +]; +console.log(state.flag);