-
Notifications
You must be signed in to change notification settings - Fork 46.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Hooks Refactor Update Queue by Cloning Rebased Updates #17483
Conversation
This pull request is automatically built and testable in CodeSandbox. To see build info of the built libraries, click here or the icon next to each commit SHA. Latest deployment of this branch, based on commit 89ca3cf:
|
Details of bundled changes.Comparing: 3c1efa0...89ca3cf react-reconciler
react-dom
react-art
react-test-renderer
react-native-renderer
ReactDOM: size: 🔺+0.3%, gzip: 🔺+0.2% Size changes (stable) |
Details of bundled changes.Comparing: 3c1efa0...89ca3cf react-dom
react-native-renderer
react-test-renderer
react-art
react-reconciler
Size changes (experimental) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Neat! But I don't think we should land without fixing classes too. I can pick up that part next week when I'm back from PTO, if you want.
} else { | ||
first = last !== null ? last.next : null; | ||
current.baseQueue = baseQueue = pendingQueue; | ||
queue.pending = null; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I love this trick
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe we could use this same trick for expirationTimes. By storing it temporarily on a shared stateful object and then transferring it to “current”. That way we don’t need the alternate model when we backtrack and can just backtrack along on a shared object path.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah I used a similar trick for the eager bailout optimization. Where I reset current.expirationTime to NoWork after a bailout. Also in my useTransition PR to clear a pending transition. Such a nice strategy.
We might want to add an optimization to avoid cloning the queue when something else renders at higher pri. In that case it’s unnecessary to clone it. |
f3659c5
to
f8244b2
Compare
Adds a failing test case where an update that was committed is later skipped over during a rebase. This should never happen.
f8244b2
to
cb6ccda
Compare
cb6ccda
to
89ca3cf
Compare
Fixes a bug related to rebasing updates. Once an update has committed, it should never un-commit, even if interrupted by a higher priority update. The fix includes a refactor of how update queues work. This commit is a combination of two PRs: - #17483 by @sebmarkbage refactors the hook update queue - #17510 by @acdlite refactors the class and root update queue Landing one without the other would cause state updates to sometimes be inconsistent across components, so I've combined them into a single commit in case they need to be reverted. Co-authored-by: Sebastian Markbåge <sema@fb.com> Co-authored-by: Andrew Clark <git@andrewclark.io>
I squashed this with the class refactor and landed as b617db3 so it can be atomically reverted. |
Fixes a bug related to rebasing updates. Once an update has committed, it should never un-commit, even if interrupted by a higher priority update. The fix includes a refactor of how update queues work. This commit is a combination of two PRs: - facebook#17483 by @sebmarkbage refactors the hook update queue - facebook#17510 by @acdlite refactors the class and root update queue Landing one without the other would cause state updates to sometimes be inconsistent across components, so I've combined them into a single commit in case they need to be reverted. Co-authored-by: Sebastian Markbåge <sema@fb.com> Co-authored-by: Andrew Clark <git@andrewclark.io>
* Refactor Update Queues to Fix Rebasing Bug Fixes a bug related to rebasing updates. Once an update has committed, it should never un-commit, even if interrupted by a higher priority update. The fix includes a refactor of how update queues work. This commit is a combination of two PRs: - #17483 by @sebmarkbage refactors the hook update queue - #17510 by @acdlite refactors the class and root update queue Landing one without the other would cause state updates to sometimes be inconsistent across components, so I've combined them into a single commit in case they need to be reverted. Co-authored-by: Sebastian Markbåge <sema@fb.com> Co-authored-by: Andrew Clark <git@andrewclark.io> * Initialize update queue object on mount Instead of lazily initializing update queue objects on the first update, class and host root queues are created on mount. This simplifies the logic for appending new updates and matches what we do for hooks.
Builds on top of #17480.
Alternative to #17430.
This model splits the update queue into two (cyclic) linked lists. There is one each for current/workInProgress pair for rebase purposes. There is also one shared one.
When we process a queue we merge the shared onto the "current" one, and clone it onto the work in progress.
The cloned one doesn't include the beginning of the queue that is fully processed.
The cloned nodes that were processed get Sync priority so that they don't get dropped during future renders.