Skip to content

Commit 679f6a9

Browse files
Dunqingclaude
andauthored
refactor(treeshake): migrate SideEffectDetector to Oxc's MayHaveSideEffects trait (#8624)
## Summary Closes: #7918 - Delegate expression/statement side-effect analysis to Oxc's `MayHaveSideEffects` trait instead of reimplementing it - `SideEffectDetector` now implements `MayHaveSideEffectsContext` and `GlobalContext` directly, keeping only bundler-specific logic - Remove `utils.rs` (593 lines) and `global_reference.rs` (828 lines) — logic now lives in Oxc - Remove `BundlerSideEffectCtx` bridge type, merging its fields and trait impls into `SideEffectDetector` - Remove `phf` dependency from `rolldown_utils` - Fix pre-existing bugs: - Destructuring assignment targets (`[] = rhs`, `{} = rhs`) were incorrectly treated as side-effect-free — now delegated to Oxc which correctly identifies `GetIterator`/`RequireObjectCoercible` as observable - Compound assignment operators (`+=`, `-=`, `||=`, etc.) were missing a side-effect check — now delegated to Oxc which correctly treats them as always side-effectful Net: **-1555 lines** ### Why some checks still can't be delegated to Oxc Oxc's `MayHaveSideEffects` is a pure JS semantics analysis — it has no concept of bundler-level concerns. The remaining Rolldown-specific overrides are: | Override | Why Oxc can't handle it | |---|---| | **`SideEffectDetail` metadata flags** (`GlobalVarAccess`, `PureAnnotation`, `PureCjs`) | These are bundler metadata bits propagated through the tree for downstream decisions (e.g. cross-module optimization, CJS interop). Oxc returns a plain `bool`. | | **`import.meta.*` is side-effect-free** | Oxc treats `import.meta` as a `MetaProperty` with no special semantics. The bundler knows `import.meta.url` etc. are safe reads because it controls their resolution. | | **CJS `exports.foo = ...` pattern** | Oxc sees a property write on an unresolved global (`exports`) — side-effectful. The bundler knows this is a CJS export assignment and marks it `PureCjs`. Must be checked **before** delegating to Oxc. | | **Cross-module pure call tracking** (`side_effect_free_call_expr_addr`) | The bundler's link stage identifies calls to functions proven pure across modules. Oxc only sees a single file at a time. | | **Module declarations** (`import`/`export`) | Oxc would treat these as side-effectful statements. The bundler knows imports/re-exports are declarative and handles them in the link stage. | | **`using` declarations** | Rolldown has custom logic for `using` declarators (only `null`, `undefined`, or `void expr` initializers are side-effect-free). This is stricter than generic analysis because `using` invokes `Symbol.dispose`. | | **Variable declarations with destructuring** | Rolldown has custom rules: object destructuring depends on `property_read_side_effects`, array destructuring checks for nested patterns. These interact with bundler options that Oxc doesn't model at the statement level. | | **Pure-annotated call args** | For `/*@__PURE__*/` calls, Rolldown must re-check args through its own detector (not Oxc's) because bundler-specific overrides (e.g. `import.meta.*`) apply to args too. | ## Test plan - [x] All existing side-effect detection tests pass (33/33) Related: oxc-project/oxc#19673 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Claude Opus 4.6 (1M context) <[email protected]>
1 parent 557d377 commit 679f6a9

File tree

6 files changed

+360
-2197
lines changed

6 files changed

+360
-2197
lines changed

Cargo.lock

Lines changed: 0 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)