Latest Results
feat(es/minifier): Add `unsafe_hoist_static_method_alias` option (#11493)
## Summary
This PR adds two new minifier compress options for hoisting
frequently-used built-in references to local aliases, enabling better
minification after mangling.
### New Options
#### `unsafe_hoist_static_method_alias` (default: `false`)
Hoists frequently-used static method calls to local variables:
```js
// Before
Object.assign(a, {}); Object.assign(b, {}); Object.assign(c, {});
// After
var _Object_assign = Object.assign;
_Object_assign(a, {}); _Object_assign(b, {}); _Object_assign(c, {});
```
**Supported built-ins:**
- **Object**: `assign`, `keys`, `values`, `entries`, `fromEntries`,
`freeze`, `seal`, `create`, `defineProperty`, `defineProperties`,
`getOwnPropertyDescriptor`, `getOwnPropertyDescriptors`,
`getOwnPropertyNames`, `getOwnPropertySymbols`, `getPrototypeOf`,
`setPrototypeOf`, `preventExtensions`, `isFrozen`, `isSealed`,
`isExtensible`, `hasOwn`, `is`
- **Array**: `isArray`, `from`, `of`
- **Reflect**: `apply`, `construct`, `defineProperty`, `deleteProperty`,
`get`, `getOwnPropertyDescriptor`, `getPrototypeOf`, `has`,
`isExtensible`, `ownKeys`, `preventExtensions`, `set`, `setPrototypeOf`
- **Math**: `abs`, `acos`, `acosh`, `asin`, `asinh`, `atan`, `atan2`,
`atanh`, `cbrt`, `ceil`, `clz32`, `cos`, `cosh`, `exp`, `expm1`,
`floor`, `fround`, `hypot`, `imul`, `log`, `log10`, `log1p`, `log2`,
`max`, `min`, `pow`, `random`, `round`, `sign`, `sin`, `sinh`, `sqrt`,
`tan`, `tanh`, `trunc`
- **String**: `fromCharCode`, `fromCodePoint`, `raw`
- **Number**: `isFinite`, `isInteger`, `isNaN`, `isSafeInteger`,
`parseFloat`, `parseInt`
- **JSON**: `parse`, `stringify`
- **Promise**: `all`, `allSettled`, `any`, `race`, `reject`, `resolve`,
`withResolvers`
- **Symbol**: `for`, `keyFor`
#### `unsafe_hoist_global_objects_alias` (default: `false`)
Hoists frequently-used global object constructor calls to local
variables:
```js
// Before
new Map(); new Map(); new Map();
// After
var _Map = Map;
new _Map(); new _Map(); new _Map();
```
**Supported global objects:**
- Collections: `Map`, `Set`, `WeakMap`, `WeakSet`
- Async: `Promise`, `Proxy`
- Types: `Date`, `RegExp`, `URL`, `URLSearchParams`
- Errors: `Error`, `TypeError`, `RangeError`, `SyntaxError`,
`ReferenceError`, `URIError`, `EvalError`
- Typed Arrays: `ArrayBuffer`, `SharedArrayBuffer`, `DataView`,
`Int8Array`, `Uint8Array`, `Uint8ClampedArray`, `Int16Array`,
`Uint16Array`, `Int32Array`, `Uint32Array`, `Float32Array`,
`Float64Array`, `BigInt64Array`, `BigUint64Array`
- Text: `TextEncoder`, `TextDecoder`
### Smart Thresholds
The optimizer uses a cost-benefit formula to determine when hoisting is
worthwhile:
```
min_usages = ceil((name_len + 7) / (name_len - 1))
```
- Every hoist costs `name_len + 7` bytes (e.g., `var a=Set;` = 10 bytes)
- Every usage saves `name_len - 1` bytes (e.g., `new a()` vs `new Set()`
saves 2 bytes)
Examples:
- `Object.assign` (13 chars): needs 2+ usages
- `Math.cos` (8 chars): needs 3+ usages
- `Set` (3 chars): needs 5+ usages
### Why "unsafe"?
These options are marked as unsafe because they assume built-in globals
haven't been modified. If user code overrides `Object.assign` or `Map`
after the hoisted alias is captured, the aliased calls will still use
the original built-in.
### Implementation
The static alias optimization is integrated directly into the
`Optimizer` (following the SWC way of avoiding separate visitors):
- **`StaticAliasState`**: Stored in `Compressor` and passed to
`Optimizer` by reference, persisting state across optimization passes
- **Pass 1**: Counts usages of static method calls and global object
constructors during `visit_mut_call_expr` and `visit_mut_new_expr`. At
the end of module/script processing, builds aliases for methods/objects
that exceed the threshold.
- **Pass 2+**: Replaces call/new expressions with aliases. Inserts var
declarations at the top of the module/script.
Uses `private_ident!` macro for hygiene-safe identifier generation,
avoiding name collisions.
## Test Plan
- [x] Added 7 fixture tests covering:
- Basic static method hoisting (`9741`)
- Threshold behavior (`9741_threshold`)
- Multiple methods (`9741_multiple_methods`)
- Disabled mode (`9741_disabled`)
- Variable collision handling (`9741_collision`)
- Function collision handling (`9741_collision_function`)
- Global object hoisting (`9741_global_objects`)
- [x] Added 4 execution tests for runtime correctness
- [x] All 2,116 execution tests pass
- [x] All 2,202 fixture tests pass
Closes #9741
---
🤖 Generated with [Claude Code](https://claude.ai/claude-code)
---------
Co-authored-by: claude[bot] <41898282+claude[bot]@users.noreply.github.com>
Co-authored-by: Donny/강동윤 <kdy1@users.noreply.github.com> Active Branches
#11208+4%
#114750%
#115240%
© 2026 CodSpeed Technology