Skip to content

[Bug]: SWC compress drops function call arguments inside inner generator #13901

@erikogan

Description

@erikogan

System Info

System:
OS: Linux 6.8 Ubuntu 22.04.4 LTS 22.04.4 LTS (Jammy Jellyfish)
CPU: (4) x64 AMD EPYC 9R45
Memory: 9.60 GB / 30.74 GB
Container: Yes
Shell: 5.8.1 - /bin/zsh
Binaries:
Node: 22.13.0 - ~/.nvm/versions/node/v22.13.0/bin/node
Yarn: 1.22.22 - ~.nvm/versions/node/v22.13.0/bin/yarn
npm: 10.9.2 - ~/.nvm/versions/node/v22.13.0/bin/npm
pnpm: 8.15.9 - ~/.nvm/versions/node/v22.13.0/bin/pnpm
npmPackages:
@rspack/cli: 2.0.1 => 2.0.1
@rspack/core: 2.0.1 => 2.0.1
@rspack/dev-server: 2.0.1 => 2.0.1
@rspack/plugin-react-refresh: ^2.0.0 => 2.0.0

Details

SWC compress drops function call arguments inside inner generator

SwcJsMinimizerRspackPlugin drops call arguments from a function call inside an inner generator when the callee was destructured from an options object and conditionally reassigned.

Trigger

All three conditions are required:

  1. var { match } = options — callee destructured from an object parameter
  2. if (!match) { match = () => true; } — if-based conditional reassignment (logically equivalent expressions do not trigger it)
  3. if (!match(a, b)) continue; — called with arguments inside a for...of loop in an inner generator

Changing any one (e.g. match = match || (() => true) for condition 2, or a direct parameter instead of destructuring for condition 1) prevents the bug.

Reproduce link

https://github.com/academia-edu/rspack-dropped-arguments-repro/tree/erik/dropped-arguments-repro

Reproduce Steps

Reproduce

pnpm install
pnpm run build

Open rspack-dist/index.html → shows FAIL (red)
Open webpack-dist/index.html → shows PASS (green)

Source (src/index.js)

function outer(options) {
  return function* () {
    var { match } = options;
    if (!match) {
      match = () => true;
    }
    for (var [a, b] of [[1, 2], [3, 4]]) {
      if (!match(a, b)) continue;   // ← BUG: compiled to match() by rspack
      yield [a, b];
    }
  };
}

Output diff

rspack (rspack-dist/main.js):

function*(){var{match:e}=t;for(var[o,d]of(e||(e=()=>!0),[[1,2],[3,4]]))e()&&(yield[o,d])
//                                                                      ^^
//                                            match(a, b) compiled to match() — args DROPPED

webpack (webpack-dist/main.js):

function*(){var{match:o}=t;for(var[e,c]of(o||(o=()=>!0),[[1,2],[3,4]]))o(e,c)&&(yield[e,c])
//                                                                      ^^^^
//                                                              match(a, b) preserved — correct

Real-world impact

This is the exact pattern in slate@0.124.1 Editor.nodes. When bundled with rspack in production mode, match(node, path) compiles to match(), so the match predicate receives undefined as the node and crashes with:

TypeError: Cannot read properties of undefined (reading 'text')

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No fields configured for Bug.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions