Skip to content

feat: assignment literal analysis and truthy functions - #6452

Open
cyyynthia wants to merge 2 commits into
rollup:masterfrom
cyyynthia:assignment-literal-analysis
Open

feat: assignment literal analysis and truthy functions#6452
cyyynthia wants to merge 2 commits into
rollup:masterfrom
cyyynthia:assignment-literal-analysis

Conversation

@cyyynthia

@cyyynthia cyyynthia commented Jul 19, 2026

Copy link
Copy Markdown
Contributor

This PR contains:

  • bugfix
  • feature
  • refactor
  • documentation
  • other

Are tests included?

  • yes (bugfixes and features will not be merged without tests)
  • no

Breaking Changes?

  • yes (breaking changes will not be merged unless absolutely necessary)
  • no

Description

This PR addresses 2 shortcomings of Rollup currently:

  • Assignment expressions are not walked through when it's a simple =. This unlocks analysis of e.g. () => globalThis.value = true as a side-effectful function returning true.
  • Due to the TS enum bug, ObjectEntity is not considered truthy and so are functions and classes. I've made them act as truthy, which allowed Rollup to optimise core-js parts that the bundler considers always present (the optimisation gains are underwhelming due to the lack of advanced analysis of variable reassignment, which would allow Rollup to get rid of entire requireXXX blocks in core-js).

@vercel

vercel Bot commented Jul 19, 2026

Copy link
Copy Markdown

@cyyynthia is attempting to deploy a commit to the rollup-js Team on Vercel.

A member of the Team first needs to authorize it.

@cyyynthia cyyynthia changed the title Assignment literal analysis and truthy functions feat: assignment literal analysis and truthy functions Jul 19, 2026
@codecov

codecov Bot commented Jul 19, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 60.00000% with 2 lines in your changes missing coverage. Please review.
✅ Project coverage is 98.77%. Comparing base (95c2f02) to head (b6d5e37).
⚠️ Report is 40 commits behind head on master.

⚠️ Current head b6d5e37 differs from pull request most recent head 156aef8

Please upload reports for the commit 156aef8 to get more accurate results.

Files with missing lines Patch % Lines
src/ast/nodes/AssignmentExpression.ts 50.00% 0 Missing and 1 partial ⚠️
src/ast/nodes/shared/MethodTypes.ts 0.00% 0 Missing and 1 partial ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master    #6452      +/-   ##
==========================================
- Coverage   98.78%   98.77%   -0.02%     
==========================================
  Files         275      275              
  Lines       10820    10825       +5     
  Branches     2886     2891       +5     
==========================================
+ Hits        10689    10692       +3     
  Misses         89       89              
- Partials       42       44       +2     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@cyyynthia
cyyynthia force-pushed the assignment-literal-analysis branch from cd8f85b to b6d5e37 Compare July 19, 2026 13:22
@cyyynthia cyyynthia mentioned this pull request Jul 19, 2026
9 tasks
@lukastaegert

lukastaegert commented Aug 1, 2026

Copy link
Copy Markdown
Member

Hmmm, isn't getting rid of polyfills in core-js actually a bad thing? After all, it is polyfilling missing prototype methods. From the diff it looks to me like your change might actually break the copyWithin polyfill. I believe it was for those reasons we never did the last step to mark some things as truthy (though of course negligence is likely the other reason).
At the very least what you must not do is add any logic that could give the impression that any of the assumed-present global/prototype methods actually exist, exactly not to break polyfills. It is fine to assume that objects or functions that the user declares are truthy, or methods in objects that the user declares.

@cyyynthia

Copy link
Copy Markdown
Contributor Author

At the very least what you must not do is add any logic that could give the impression that any of the assumed-present global/prototype methods actually exist, exactly not to break polyfills. It is fine to assume that objects or functions that the user declares are truthy, or methods in objects that the user declares.

I think this is a fair point, though perhaps we can preserve this new behaviour as an opt-in config flag instead 🤔

@cyyynthia
cyyynthia force-pushed the assignment-literal-analysis branch from b6d5e37 to 67bda73 Compare August 3, 2026 11:02
Solution is probably to also override deoptimizeArgumentsOnInteractionAtPath and
deoptimizePath to forward to this.right for `=`.

@lukastaegert lukastaegert left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Hi! This looks good in general now, but I found a regression in the updates to AssignmentExpression. I pushed a failing test to demonstrate. Basically if we forward AssignmentExpression.getLiteralValueAtPath to this.right, then we also need to forward deoptimizations of the result to this.right. I managed to get this to produce bugs when using destructuring assignments. Similarly, we should also implement deoptimizeArgumentsOnInteractionAtPath.

@lukastaegert

lukastaegert commented Aug 27, 2026

Copy link
Copy Markdown
Member

I think this is a fair point, though perhaps we can preserve this new behaviour as an opt-in config flag instead 🤔

I thought about this long in the past and I keep coming back to the fact that the only good reason why one would want to check the truthiness of a built-in prototype method is to do feature-detection, and we must not break those flows.
So there are several ways to do feature detection:

  • Truthiness as a smoke test if there is something at a given prototype value, this we should never break
  • typeof checks. We are not doing anything here at the moment, but in the future, we should not blindly assume that a prototype function returns function for a typeof call
  • just calling it in a try-catch. While our logic assumes many builtins have no side effects, the try-catch-deoptimization will still preserve the call in those situations

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.

2 participants