Skip to content

Comments

feat(minifier): fold iife arrow functions in call expressions#16477

Merged
sapphi-red merged 13 commits intooxc-project:mainfrom
armano2:fix/remove-unused-iife-expressions
Dec 18, 2025
Merged

feat(minifier): fold iife arrow functions in call expressions#16477
sapphi-red merged 13 commits intooxc-project:mainfrom
armano2:fix/remove-unused-iife-expressions

Conversation

@armano2
Copy link
Contributor

@armano2 armano2 commented Dec 4, 2025

Improve folding of iife

details

  • check all CallExpression if they can be collapsed
    eg. passed as arguments or in assignment
  • functions without arguments and body can be collapsed to to void 0
    (() => {})() or (function () { })() to void 0
  • with one statement and without return will be collapsed to (c, void 0)
    (() => { fn() })() to (fn(), void 0)
  • FunctionExpression is not supported
    (function () { ... })()

notes

  • function with arguments could be handled by first in-lining them
  • empty function with arguments could be also if all arguments do not have defaults
  • we should consider optimizing function definitions by removing not used arguments
  • initially i added support for FunctionExpression but there is no way to track this usage, and thus we are unable to minify this

change example

code

{
  let AOT = true;
  const getAOT = /* @__NO_SIDE_EFFECTS__ */ () => AOT;
  const fn = getAOT() ? () => console.log("Hi") : () => {};
  fn();
}

currently is collapsed to

(/* @__PURE__ */ /* @__NO_SIDE_EFFECTS__ */ (() => !0)() ? () => console.log("Hi") : () => {})();

and with this change

console.log('Hi');

from what i can see @sapphi-red worked on this file

@github-actions github-actions bot added A-minifier Area - Minifier C-bug Category - Bug labels Dec 4, 2025
@armano2 armano2 marked this pull request as ready for review December 4, 2025 02:54
@codspeed-hq
Copy link

codspeed-hq bot commented Dec 4, 2025

CodSpeed Performance Report

Merging #16477 will not alter performance

Comparing armano2:fix/remove-unused-iife-expressions (2199e89) with main (f8abd56)

Summary

✅ 38 untouched
⏩ 7 skipped1

Footnotes

  1. 7 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports.

@armano2 armano2 marked this pull request as draft December 4, 2025 22:27
@armano2 armano2 marked this pull request as ready for review December 4, 2025 22:27
@sapphi-red sapphi-red changed the title fix(minifier): fold iife arrow functions in call expressions feat(minifier): fold iife arrow functions in call expressions Dec 5, 2025
@github-actions github-actions bot added the C-enhancement Category - New feature or request label Dec 5, 2025
@armano2
Copy link
Contributor Author

armano2 commented Dec 5, 2025

i noticed a bug in this implementation
this is not handled inside FunctionExpression, i was hoping to used references, but it looks like they this is not defined as such

@armano2 armano2 marked this pull request as draft December 5, 2025 21:14
@armano2 armano2 force-pushed the fix/remove-unused-iife-expressions branch from afa595c to 6d39973 Compare December 5, 2025 21:31
@armano2 armano2 marked this pull request as ready for review December 5, 2025 21:31
@armano2
Copy link
Contributor Author

armano2 commented Dec 5, 2025

@sapphi-red thank you for running tests issues reported by it should be fixed

is there any guide what tests we have to run localy?

@sapphi-red
Copy link
Member

sapphi-red commented Dec 6, 2025

Running the tests ran by the CI should be fine.

@armano2
Copy link
Contributor Author

armano2 commented Dec 6, 2025

Conformance tests should be ok, its interesting that

  • Object.getPrototypeOf(async function () {}()) = Promise
  • Object.getPrototypeOf(async function* () {}()) = AsyncGenerator
  • Object.getPrototypeOf(async function* () {}()) = Generator

i'm not sure tho if this is this is the best way to check if we can collapse pife/iife by evaluating ancesotrs and checking if they are blocks

i did some cleanup and sorry for keeping it open while it was still WIP

@armano2
Copy link
Contributor Author

armano2 commented Dec 7, 2025

if you find some time, review would be appreciated

@sapphi-red sapphi-red removed the C-bug Category - Bug label Dec 12, 2025
@sapphi-red sapphi-red self-requested a review December 12, 2025 06:24
@armano2 armano2 requested a review from sapphi-red December 13, 2025 16:50
@armano2
Copy link
Contributor Author

armano2 commented Dec 17, 2025

i was thinking abot expanding this logic to functions with arguments, but that is going to come as separate pr

Copy link
Member

@sapphi-red sapphi-red left a comment

Choose a reason for hiding this comment

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

Thank you!

@sapphi-red sapphi-red self-assigned this Dec 18, 2025
@sapphi-red
Copy link
Member

We cannot close #13651 as it requires more optimizations.
For example, I think this PR won't fix cases like: Oxc, SWC

@sapphi-red sapphi-red merged commit 3d2b492 into oxc-project:main Dec 18, 2025
27 checks passed
@armano2 armano2 deleted the fix/remove-unused-iife-expressions branch December 18, 2025 14:37
@armano2
Copy link
Contributor Author

armano2 commented Dec 18, 2025

We cannot close #13651 as it requires more optimizations

this is related to what i discovered in #16964, cross scope variables that are not static are never in-lined

overlookmotel added a commit that referenced this pull request Dec 19, 2025
### 🚀 Features

- d209c21 allocator: Add cap to FixedSizeAllocatorPool and block when
exhausted (#17023) (Cameron)
- fb2af91 allocator: Add bitset utils (#17042) (zhaoting zhou)
- c16082c tasks/compat_data: Integrate `node-compat-table` (#16831)
(Boshen)
- 5586823 span: Extract TS declaration file check to its own function
(#17037) (camchenry)
- 3d2b492 minifier: Fold iife arrow functions in call expressions
(#16477) (Armano)
- 67e9f9e codegen: Keep comments on the export specifiers (#16943)
(夕舞八弦)
- cb515fa parser: Improve error message for `yield` as identifier usage
(#16950) (sapphi-red)
- dcc856b parser: Add help for `new_dynamic_import` error (#16949)
(sapphi-red)
- c3c79f8 parser: Improve import attribute value error message (#16948)
(sapphi-red)
- 291b57b ast_tools: Generate TS declaration files for deserializer and
walk files (#16912) (camc314)
- 74eae13 minifier: Remove unused import specifiers (#16797) (camc314)

### 🐛 Bug Fixes

- fb9e193 linter: OOM problems with custom plugins (#17082)
(overlookmotel)
- e59132b parser/napi: Fix lazy deser (#17069) (overlookmotel)
- a92faf0 ast_tools: Support `u128` in `assert_layouts` generator
(#17050) (overlookmotel)
- 47b4c2f minifier/docs: Correct hyperlink path in OPTIMIZATIONS.md
(#16986) (GRK)
- 3002649 transformer/typescript: Remove unused import equals
declaration (#16776) (Dunqing)
- 5a2af88 regular_expression: Correct named capture group reference
error (#16952) (sapphi-red)

### ⚡ Performance

- b657bb6 allocator: Reduce time `Mutex` lock is held in
`FixedSizeAllocatorPool::get` (#17079) (overlookmotel)
- 1f3b19b ast: `#[ast]` macro use `#[repr(transparent)]` for
single-field structs (#17052) (overlookmotel)
- 225f229 parser: Use SmallVec for duplicate default export detection
(#16801) (camc314)

### 📚 Documentation

- a9c419f traverse: Update safety comments (#16944) (overlookmotel)

Co-authored-by: overlookmotel <557937+overlookmotel@users.noreply.github.com>
qinyuhang pushed a commit to qinyuhang/oxc that referenced this pull request Jan 22, 2026
…oject#16477)

Improve folding of iife 

## details

- check all `CallExpression` if they can be collapsed
  eg. passed as arguments or in assignment
- functions without arguments and body can be collapsed to to `void 0`
 `(() => {})()` or `(function () { })()` to `void 0`
- with one statement and without return will be collapsed to `(c, void
0)`
  `(() => { fn() })()` to `(fn(), void 0)`
- `FunctionExpression` is not supported
  `(function () { ... })()`

## notes

- function with arguments could be handled by first in-lining them
- empty function with arguments could be also if all arguments do not
have defaults
- we should consider optimizing function definitions by removing not
used arguments
- initially i added support for `FunctionExpression` but there is no way
to track `this` usage, and thus we are unable to minify this

## change example

code
```js
{
  let AOT = true;
  const getAOT = /* @__NO_SIDE_EFFECTS__ */ () => AOT;
  const fn = getAOT() ? () => console.log("Hi") : () => {};
  fn();
}
```

currently is collapsed to 

```js
(/* @__PURE__ */ /* @__NO_SIDE_EFFECTS__ */ (() => !0)() ? () => console.log("Hi") : () => {})();
```

and with this change

```js
console.log('Hi');
```

------------------

from what i can see @sapphi-red worked on this file

---------

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

A-minifier Area - Minifier C-enhancement Category - New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants