Skip to content

Fix #__PURE__ annotations being ignored by Rolldown/Vite 8 (#568)#569

Open
hrithik-infinite wants to merge 1 commit into
nevware21:mainfrom
hrithik-infinite:fix/issue-568-pure-annotations
Open

Fix #__PURE__ annotations being ignored by Rolldown/Vite 8 (#568)#569
hrithik-infinite wants to merge 1 commit into
nevware21:mainfrom
hrithik-infinite:fix/issue-568-pure-annotations

Conversation

@hrithik-infinite
Copy link
Copy Markdown

@hrithik-infinite hrithik-infinite commented May 22, 2026

Summary

Fixes #568/*#__PURE__*/ annotations in the published ESM/ES5 bundles were positioned inside the wrapping parentheses (( /*#__PURE__*/foo())), which Rolldown (and therefore Vite 8) cannot interpret. The annotation was silently ignored, so tree-shaking did not kick in for the affected values and downstream Vite 8 builds emitted [INVALID_ANNOTATION] warnings.

Root cause

The source uses (/*#__PURE__*/foo()) (no space between ( and /*). When TypeScript emits the wrapped form, it inserts a single space between ( and the leading comment, producing ( /*#__PURE__*/foo()) in the published artifacts. Rolldown only recognises the annotation when it is immediately adjacent to the call expression token; the inserted space disqualifies it.

This affected all 159 ( /*#__PURE__*/ occurrences in each of dist/es5/mod/ts-utils.js and dist/es6/mod/ts-utils.js.

Fix

Remove the redundant surrounding parens from (/*#__PURE__*/foo()) patterns in source. TypeScript then emits /*#__PURE__*/ foo(), which Rolldown interprets correctly.

  • Patterns where the parens are required for a top-level as cast ((/*#__PURE__*/foo() as Type)) are left untouched — TypeScript already strips both the parens and the cast in the emit, producing a clean annotation.
  • For the !!(/*#__PURE__*/foo()) callers in hasDocument/hasWindow/hasNavigator/hasHistory, removing the parens places the comment adjacent to !!, which TypeScript then drops. The inner annotations were redundant — the parent functions are already marked /*#__NO_SIDE_EFFECTS__*/, so callers can drop the calls when the result is unused.

Verification

  • Built artifacts (dist/es5/mod/ts-utils.js, dist/es6/mod/ts-utils.js, dist/es5/main/ts-utils.js, dist/es6/main/ts-utils.js): zero ( /*#__PURE__*/ occurrences (was 159 in each mod bundle in v0.14.0). 153 valid #__PURE__ annotations are still emitted, all in positions Rolldown accepts.
  • isNode, isWebWorker, getDocument, getWindow, getNavigator, getHistory now emit as /*#__PURE__*/ _getGlobalInstFn(...) instead of ( /*#__PURE__*/_getGlobalInstFn(...)).
  • All node tests pass: 1361 (es5) + 1371 (esnext); 0 failing.

Remove the redundant surrounding parens from `(/*#__PURE__*/foo())`
patterns. TypeScript inserts a space between the opening `(` and the
leading comment when emitting, producing `( /*#__PURE__*/foo())` in the
published bundles. Rolldown (used by Vite 8) cannot associate the
annotation with the call when the comment is positioned between the
open paren and the expression, so the annotation is silently ignored
and the call is no longer tree-shaken.

Removing the wrapping parens lets TypeScript emit
`/*#__PURE__*/ foo()`, which Rolldown interprets correctly.

Patterns where the parens are required for a top-level `as` cast are
left untouched, because TypeScript already strips both the parens and
the cast from the emit, producing a clean annotation.

For the `!!(/*#__PURE__*/foo())` callers in `hasDocument`/`hasWindow`/
`hasNavigator`/`hasHistory`, removing the parens places the comment
adjacent to `!!`, which TypeScript then drops. The inner annotations
were redundant — the parent functions are already marked
`/*#__NO_SIDE_EFFECTS__*/`, so callers can drop the calls when the
result is unused.

Verified the published bundles now contain zero
`( /*#__PURE__*/` occurrences (was 159 in v0.14.0); 153
`#__PURE__` annotations are still emitted in valid positions.
All node tests pass (1361 es5 + 1371 esnext).
@hrithik-infinite hrithik-infinite requested review from a team as code owners May 22, 2026 06:34
@hrithik-infinite
Copy link
Copy Markdown
Author

@nev21 could you please take a look when you get a chance? This fixes the Rolldown/Vite 8 warnings reported in #568. Happy to adjust the approach if you'd prefer a different pattern. Thanks!

@hrithik-infinite
Copy link
Copy Markdown
Author

Heads up — I'm also seeing 13 @typescript-eslint/no-unused-vars warnings in the current build output. They're pre-existing (not introduced by this PR), but happy to clean them up if you'd like.

Let me know which you'd prefer:

  • Fold the lint fixes into this PR (keeps everything in one place)
  • Leave them out and open a separate PR (keeps this change focused on the #__PURE__ fix)

Either is fine with me.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug] /*#__PURE__*/ annotations placed inside parens cause Rolldown/Vite 8 [INVALID_ANNOTATION] warnings and disable tree-shaking

1 participant