Skip to content

feat(es/minifier): Remove unused args for IIFE#11536

Open
Austaras wants to merge 1 commit intoswc-project:mainfrom
Austaras:main
Open

feat(es/minifier): Remove unused args for IIFE#11536
Austaras wants to merge 1 commit intoswc-project:mainfrom
Austaras:main

Conversation

@Austaras
Copy link
Member

@Austaras Austaras commented Feb 7, 2026

Description:

BREAKING CHANGE:

Related issue (if exists):
First part of #11089

@Austaras Austaras requested a review from a team as a code owner February 7, 2026 18:38
Copilot AI review requested due to automatic review settings February 7, 2026 18:38
@changeset-bot
Copy link

changeset-bot bot commented Feb 7, 2026

⚠️ No Changeset found

Latest commit: be6228a

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR enhances the SWC ECMAScript minifier’s IIFE argument optimization to remove unused call arguments (addressing the first part of #11089), and updates large golden outputs accordingly.

Changes:

  • Update ignore_unused_args_of_iife to drop/neutralize unused IIFE call arguments, including removing trailing arguments when safe.
  • Add an eval-presence guard (contains_eval) to avoid unsafe transformations.
  • Refresh expected outputs for large fixtures/bench outputs to reflect the new minification result.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 3 comments.

File Description
crates/swc_ecma_minifier/src/compress/optimize/iife.rs Implements removal of unused/trailing IIFE call arguments and adds eval guard.
crates/swc_ecma_minifier/tests/fixture/next/react-pdf-renderer/output.js Updates expected minified output to reflect dropped unused IIFE args.
crates/swc_ecma_minifier/tests/benches-full/victory.js Updates expected benchmark output with removed unused IIFE call argument.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +405 to +417
if e.args.len() > params.len() {
for i in (params.len()..e.args.len()).rev() {
if let Some(arg) = e.args.get_mut(i) {
let new = self.ignore_return_value(&mut arg.expr);

if let Some(new) = new {
arg.expr = Box::new(new);
} else {
e.args.remove(i);
}
}
}
}
Copy link

Copilot AI Feb 7, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This change introduces new behavior (dropping trailing IIFE call arguments) with several tricky edge cases (e.g. spread args, rest params, side-effect-only rewrites). Please add a focused regression fixture/test that covers the reported pattern from #11089 and at least one spread/rest scenario, so future optimizer changes don't reintroduce incorrect argument dropping.

Copilot uses AI. Check for mistakes.
Comment on lines +405 to +409
if e.args.len() > params.len() {
for i in (params.len()..e.args.len()).rev() {
if let Some(arg) = e.args.get_mut(i) {
let new = self.ignore_return_value(&mut arg.expr);

Copy link

Copilot AI Feb 7, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The new trailing-argument removal loop ignores arg.spread. For a call like (function(){})(...xs) or (function(a){})(x, ...xs), removing a spread argument is not semantics-preserving because spreading triggers iterator evaluation (can throw / have side effects) even if arg.expr itself looks side-effect-free. Add a guard to bail out when any argument has spread, or at least skip/abort removal when arg.spread.is_some() inside this loop.

Copilot uses AI. Check for mistakes.
Comment on lines +405 to +407
if e.args.len() > params.len() {
for i in (params.len()..e.args.len()).rev() {
if let Some(arg) = e.args.get_mut(i) {
Copy link

Copilot AI Feb 7, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

params.len() is not a safe cutoff for removing “extra” args when the callee has a rest parameter (e.g. (function(a,...rest){use(rest)})(1,2,3)). Args beyond params.len() are still part of rest, so removing them changes observable behavior. Consider detecting Pat::Rest in params and skipping this optimization in that case (or only removing args starting at the rest index when you can prove the rest binding is unused).

Copilot uses AI. Check for mistakes.
@github-actions
Copy link
Contributor

github-actions bot commented Feb 7, 2026

Binary Sizes

File Size
swc.linux-x64-gnu.node 28M (28577352 bytes)

Commit: 157a9a1

@codspeed-hq
Copy link

codspeed-hq bot commented Feb 7, 2026

CodSpeed Performance Report

Merging this PR will degrade performance by 2.42%

Comparing Austaras:main (be6228a) with main (b7e87c7)

Summary

❌ 1 regressed benchmark
✅ 183 untouched benchmarks

⚠️ Please fix the performance issues or acknowledge them on CodSpeed.

Performance Changes

Benchmark BASE HEAD Efficiency
es/full/minify/libraries/terser 510.2 ms 522.9 ms -2.42%

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

1 participant