Track entangled lanes separately from update lane - #27505

Merged
acdlite merged 2 commits into
react:mainfrom
acdlite:track-entangled-lanes-separately
Oct 15, 2023
Merged

Track entangled lanes separately from update lane#27505
acdlite merged 2 commits into
react:mainfrom
acdlite:track-entangled-lanes-separately

Conversation

@acdlite

Copy link
Copy Markdown
Collaborator

A small refactor to how the lane entanglement mechanism works. We can now distinguish between the lane that "spawned" a render task (i.e. a new update) versus the lanes that it's entangled with. Both the update lane and the entangled lanes will be included while rendering, but by keeping them separate, we don't lose the original priority.

In practical terms, this means we can now entangle a low priority update with a higher priority lane while rendering at the lower priority.

To do this, lanes that are entangled at the root are now tracked using the same variable that we use to track the "base lanes" when revealing a previously hidden tree — conceptually, they are the same thing. I also renamed this variable (from subtreeLanes to entangledRenderLanes) to better reflect how it's used.

My primary motivation is related to useDeferredValue, which I'll address in a later PR.

I updated one of the tests related to synchronous popstate transitions
to clarify what the desired behavior is. It's really about what happens
if a popstate transition suspends. It should not cause an error, and
the transition should be allowed to finish once the promise resolves.
Ideally, if the transition suspends, it should completely revert back
to the default behavior for transitions — i.e. it should no longer be
treated as synchronous. Currently we don't do that, and when the promise
resolve the transition will still be rendered synchronously, but we can
improve this later.
@facebook-github-botfacebook-github-bot added CLA Signed React Core Team Opened by a member of the React Core Team labels Oct 12, 2023
@react-sizebot

react-sizebot commented Oct 12, 2023

Copy link
Copy Markdown

Comparing: e61a60f...717595f

Critical size changes

Includes critical production bundles, as well as any change greater than 2%:

Name+/-BaseCurrent+/- gzipBase gzipCurrent gzip
oss-stable/react-dom/cjs/react-dom.production.min.js+0.09%174.53 kB174.68 kB+0.04%54.29 kB54.32 kB
oss-experimental/react-dom/cjs/react-dom.production.min.js+0.09%176.61 kB176.77 kB+0.09%54.94 kB54.99 kB
facebook-www/ReactDOM-prod.classic.js+0.08%565.12 kB565.55 kB+0.11%99.42 kB99.53 kB
facebook-www/ReactDOM-prod.modern.js+0.08%548.98 kB549.40 kB+0.11%96.50 kB96.60 kB

Significant size changes

Includes any change greater than 0.2%:

Expand to show
Name+/-BaseCurrent+/- gzipBase gzipCurrent gzip
oss-stable-semver/react-reconciler/cjs/react-reconciler.development.js+0.22%931.93 kB933.98 kB+0.22%200.11 kB200.55 kB
oss-stable/react-reconciler/cjs/react-reconciler.development.js+0.22%931.95 kB934.01 kB+0.22%200.14 kB200.58 kB
oss-experimental/react-reconciler/cjs/react-reconciler.development.js+0.22%942.04 kB944.09 kB+0.22%202.00 kB202.46 kB
oss-stable-semver/react-test-renderer/cjs/react-test-renderer.development.js+0.20%813.99 kB815.64 kB+0.25%178.18 kB178.62 kB
oss-stable/react-test-renderer/cjs/react-test-renderer.development.js+0.20%814.02 kB815.67 kB+0.25%178.21 kB178.66 kB
oss-experimental/react-test-renderer/cjs/react-test-renderer.development.js+0.20%815.38 kB817.03 kB+0.25%178.45 kB178.89 kB
facebook-react-native/react-test-renderer/cjs/ReactTestRenderer-dev.js+0.20%826.50 kB828.16 kB+0.23%179.67 kB180.09 kB

Generated by 🚫 dangerJS against 717595f

A small refactor to how the lane entanglement mechanism works. We can
now distinguish between the lane that "spawned" a render task (i.e. a
new update) versus the lanes that it's entangled with. Both the update
lane and the entangled lanes will be included while rendering, but
by keeping them separate, we don't lose the original priority.
In practical terms, this means we can now entangle a low priority update
with a higher priority lane while rendering at the lower priority.
To do this, lanes that are entangled at the root are now tracked using
the same variable that we use to track the "base lanes" when revealing
a previously hidden tree — conceptually, they are the same thing. I
also renamed this variable (from subtreeLanes to entangledRenderLanes)
to better reflect how it's used.
My primary motivation is related to useDeferredValue, which I'll address
in a later PR.
@acdlite
acdlite merged commit 309c8ad into react:mainOct 15, 2023
github-actionsBot pushed a commit that referenced this pull request Oct 15, 2023
A small refactor to how the lane entanglement mechanism works. We can
now distinguish between the lane that "spawned" a render task (i.e. a
new update) versus the lanes that it's entangled with. Both the update
lane and the entangled lanes will be included while rendering, but by
keeping them separate, we don't lose the original priority.
In practical terms, this means we can now entangle a low priority update
with a higher priority lane while rendering at the lower priority.
To do this, lanes that are entangled at the root are now tracked using
the same variable that we use to track the "base lanes" when revealing a
previously hidden tree — conceptually, they are the same thing. I also
renamed this variable (from subtreeLanes to entangledRenderLanes) to
better reflect how it's used.
My primary motivation is related to useDeferredValue, which I'll address
in a later PR.
DiffTrain build for [309c8ad](309c8ad)
acdlite added a commit that referenced this pull request Oct 17, 2023
### Based on #27505
If a parent render spawns a deferred task with useDeferredValue, but the
parent render suspends, we should not wait for the parent render to
complete before attempting to render the final value.
The reason is that the initialValue argument to useDeferredValue is
meant to represent an immediate preview of the final UI. If we can't
render it "immediately", we might as well skip it and go straight to the
"real" value.
This is an improvement over how a userspace implementation of
useDeferredValue would work, because a userspace implementation would
have to wait for the parent task to commit (useEffect) before spawning
the deferred task, creating a waterfall.
github-actionsBot pushed a commit that referenced this pull request Oct 17, 2023
### Based on #27505
If a parent render spawns a deferred task with useDeferredValue, but the
parent render suspends, we should not wait for the parent render to
complete before attempting to render the final value.
The reason is that the initialValue argument to useDeferredValue is
meant to represent an immediate preview of the final UI. If we can't
render it "immediately", we might as well skip it and go straight to the
"real" value.
This is an improvement over how a userspace implementation of
useDeferredValue would work, because a userspace implementation would
have to wait for the parent task to commit (useEffect) before spawning
the deferred task, creating a waterfall.
DiffTrain build for [b2a68a6](b2a68a6)
kodiakhqBot pushed a commit to vercel/next.js that referenced this pull request Oct 18, 2023
jerrydev0927 added a commit to jerrydev0927/react that referenced this pull request Jan 5, 2024
### Based on react/react#27505
If a parent render spawns a deferred task with useDeferredValue, but the
parent render suspends, we should not wait for the parent render to
complete before attempting to render the final value.
The reason is that the initialValue argument to useDeferredValue is
meant to represent an immediate preview of the final UI. If we can't
render it "immediately", we might as well skip it and go straight to the
"real" value.
This is an improvement over how a userspace implementation of
useDeferredValue would work, because a userspace implementation would
have to wait for the parent task to commit (useEffect) before spawning
the deferred task, creating a waterfall.
DiffTrain build for [b2a68a65c84b63ac86930d88ae5c84380cbbdeb6](react/react@b2a68a6)
EdisonVan pushed a commit to EdisonVan/react that referenced this pull request Apr 15, 2024
A small refactor to how the lane entanglement mechanism works. We can
now distinguish between the lane that "spawned" a render task (i.e. a
new update) versus the lanes that it's entangled with. Both the update
lane and the entangled lanes will be included while rendering, but by
keeping them separate, we don't lose the original priority.
In practical terms, this means we can now entangle a low priority update
with a higher priority lane while rendering at the lower priority.
To do this, lanes that are entangled at the root are now tracked using
the same variable that we use to track the "base lanes" when revealing a
previously hidden tree — conceptually, they are the same thing. I also
renamed this variable (from subtreeLanes to entangledRenderLanes) to
better reflect how it's used.
My primary motivation is related to useDeferredValue, which I'll address
in a later PR.
EdisonVan pushed a commit to EdisonVan/react that referenced this pull request Apr 15, 2024
### Based on react#27505
If a parent render spawns a deferred task with useDeferredValue, but the
parent render suspends, we should not wait for the parent render to
complete before attempting to render the final value.
The reason is that the initialValue argument to useDeferredValue is
meant to represent an immediate preview of the final UI. If we can't
render it "immediately", we might as well skip it and go straight to the
"real" value.
This is an improvement over how a userspace implementation of
useDeferredValue would work, because a userspace implementation would
have to wait for the parent task to commit (useEffect) before spawning
the deferred task, creating a waterfall.
bigfootjon pushed a commit that referenced this pull request Apr 18, 2024
A small refactor to how the lane entanglement mechanism works. We can
now distinguish between the lane that "spawned" a render task (i.e. a
new update) versus the lanes that it's entangled with. Both the update
lane and the entangled lanes will be included while rendering, but by
keeping them separate, we don't lose the original priority.
In practical terms, this means we can now entangle a low priority update
with a higher priority lane while rendering at the lower priority.
To do this, lanes that are entangled at the root are now tracked using
the same variable that we use to track the "base lanes" when revealing a
previously hidden tree — conceptually, they are the same thing. I also
renamed this variable (from subtreeLanes to entangledRenderLanes) to
better reflect how it's used.
My primary motivation is related to useDeferredValue, which I'll address
in a later PR.
DiffTrain build for commit 309c8ad.
acdlite added a commit that referenced this pull request Aug 23, 2024
This is a refactor of the fix in #27505.
When a transition update is scheduled by a popstate event, (i.e. a back/
forward navigation) we attempt to render it synchronously even though
it's a transition, since it's likely the previous page's data is cached.
In #27505, I changed the implementation so that it only "upgrades" the
priority of the transition for a single attempt. If the attempt
suspends, say because the data is not cached after all, from then on it
should be treated as a normal transition.
But it turns out #27505 did not work as intended, because it relied on
marking the root with pending synchronous work (root.pendingLanes),
which was never cleared until the popstate update completed.
The test scenarios I wrote accidentally worked for a different reason
related to suspending the work loop, which I'm currently in the middle
of refactoring.
github-actionsBot pushed a commit that referenced this pull request Aug 23, 2024
This is a refactor of the fix in #27505.
When a transition update is scheduled by a popstate event, (i.e. a back/
forward navigation) we attempt to render it synchronously even though
it's a transition, since it's likely the previous page's data is cached.
In #27505, I changed the implementation so that it only "upgrades" the
priority of the transition for a single attempt. If the attempt
suspends, say because the data is not cached after all, from then on it
should be treated as a normal transition.
But it turns out #27505 did not work as intended, because it relied on
marking the root with pending synchronous work (root.pendingLanes),
which was never cleared until the popstate update completed.
The test scenarios I wrote accidentally worked for a different reason
related to suspending the work loop, which I'm currently in the middle
of refactoring.
DiffTrain build for commit ee7f675.
github-actionsBot pushed a commit that referenced this pull request Aug 23, 2024
This is a refactor of the fix in #27505.
When a transition update is scheduled by a popstate event, (i.e. a back/
forward navigation) we attempt to render it synchronously even though
it's a transition, since it's likely the previous page's data is cached.
In #27505, I changed the implementation so that it only "upgrades" the
priority of the transition for a single attempt. If the attempt
suspends, say because the data is not cached after all, from then on it
should be treated as a normal transition.
But it turns out #27505 did not work as intended, because it relied on
marking the root with pending synchronous work (root.pendingLanes),
which was never cleared until the popstate update completed.
The test scenarios I wrote accidentally worked for a different reason
related to suspending the work loop, which I'm currently in the middle
of refactoring.
DiffTrain build for [ee7f675](ee7f675)
Akshato07 pushed a commit to Akshato07/-Luffy that referenced this pull request Feb 20, 2025
### Based on react/react#27505
If a parent render spawns a deferred task with useDeferredValue, but the
parent render suspends, we should not wait for the parent render to
complete before attempting to render the final value.
The reason is that the initialValue argument to useDeferredValue is
meant to represent an immediate preview of the final UI. If we can't
render it "immediately", we might as well skip it and go straight to the
"real" value.
This is an improvement over how a userspace implementation of
useDeferredValue would work, because a userspace implementation would
have to wait for the parent task to commit (useEffect) before spawning
the deferred task, creating a waterfall.
DiffTrain build for commit react/react@b2a68a6.
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CLA SignedReact Core TeamOpened by a member of the React Core Team

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@acdlite@react-sizebot@sebmarkbage@facebook-github-bot
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

Track entangled lanes separately from update lane - #27505

Merged
acdlite merged 2 commits into
react:mainfrom
acdlite:track-entangled-lanes-separately
Oct 15, 2023
Merged

Track entangled lanes separately from update lane#27505
acdlite merged 2 commits into
react:mainfrom
acdlite:track-entangled-lanes-separately

Conversation

@acdlite

Copy link
Copy Markdown
Collaborator

A small refactor to how the lane entanglement mechanism works. We can now distinguish between the lane that "spawned" a render task (i.e. a new update) versus the lanes that it's entangled with. Both the update lane and the entangled lanes will be included while rendering, but by keeping them separate, we don't lose the original priority.

In practical terms, this means we can now entangle a low priority update with a higher priority lane while rendering at the lower priority.

To do this, lanes that are entangled at the root are now tracked using the same variable that we use to track the "base lanes" when revealing a previously hidden tree — conceptually, they are the same thing. I also renamed this variable (from subtreeLanes to entangledRenderLanes) to better reflect how it's used.

My primary motivation is related to useDeferredValue, which I'll address in a later PR.

I updated one of the tests related to synchronous popstate transitions
to clarify what the desired behavior is. It's really about what happens
if a popstate transition suspends. It should not cause an error, and
the transition should be allowed to finish once the promise resolves.
Ideally, if the transition suspends, it should completely revert back
to the default behavior for transitions — i.e. it should no longer be
treated as synchronous. Currently we don't do that, and when the promise
resolve the transition will still be rendered synchronously, but we can
improve this later.
@facebook-github-botfacebook-github-bot added CLA Signed React Core Team Opened by a member of the React Core Team labels Oct 12, 2023
@react-sizebot

react-sizebot commented Oct 12, 2023

Copy link
Copy Markdown

Comparing: e61a60f...717595f

Critical size changes

Includes critical production bundles, as well as any change greater than 2%:

Name+/-BaseCurrent+/- gzipBase gzipCurrent gzip
oss-stable/react-dom/cjs/react-dom.production.min.js+0.09%174.53 kB174.68 kB+0.04%54.29 kB54.32 kB
oss-experimental/react-dom/cjs/react-dom.production.min.js+0.09%176.61 kB176.77 kB+0.09%54.94 kB54.99 kB
facebook-www/ReactDOM-prod.classic.js+0.08%565.12 kB565.55 kB+0.11%99.42 kB99.53 kB
facebook-www/ReactDOM-prod.modern.js+0.08%548.98 kB549.40 kB+0.11%96.50 kB96.60 kB

Significant size changes

Includes any change greater than 0.2%:

Expand to show
Name+/-BaseCurrent+/- gzipBase gzipCurrent gzip
oss-stable-semver/react-reconciler/cjs/react-reconciler.development.js+0.22%931.93 kB933.98 kB+0.22%200.11 kB200.55 kB
oss-stable/react-reconciler/cjs/react-reconciler.development.js+0.22%931.95 kB934.01 kB+0.22%200.14 kB200.58 kB
oss-experimental/react-reconciler/cjs/react-reconciler.development.js+0.22%942.04 kB944.09 kB+0.22%202.00 kB202.46 kB
oss-stable-semver/react-test-renderer/cjs/react-test-renderer.development.js+0.20%813.99 kB815.64 kB+0.25%178.18 kB178.62 kB
oss-stable/react-test-renderer/cjs/react-test-renderer.development.js+0.20%814.02 kB815.67 kB+0.25%178.21 kB178.66 kB
oss-experimental/react-test-renderer/cjs/react-test-renderer.development.js+0.20%815.38 kB817.03 kB+0.25%178.45 kB178.89 kB
facebook-react-native/react-test-renderer/cjs/ReactTestRenderer-dev.js+0.20%826.50 kB828.16 kB+0.23%179.67 kB180.09 kB

Generated by 🚫 dangerJS against 717595f

A small refactor to how the lane entanglement mechanism works. We can
now distinguish between the lane that "spawned" a render task (i.e. a
new update) versus the lanes that it's entangled with. Both the update
lane and the entangled lanes will be included while rendering, but
by keeping them separate, we don't lose the original priority.
In practical terms, this means we can now entangle a low priority update
with a higher priority lane while rendering at the lower priority.
To do this, lanes that are entangled at the root are now tracked using
the same variable that we use to track the "base lanes" when revealing
a previously hidden tree — conceptually, they are the same thing. I
also renamed this variable (from subtreeLanes to entangledRenderLanes)
to better reflect how it's used.
My primary motivation is related to useDeferredValue, which I'll address
in a later PR.
@acdlite
acdlite merged commit 309c8ad into react:mainOct 15, 2023
github-actionsBot pushed a commit that referenced this pull request Oct 15, 2023
A small refactor to how the lane entanglement mechanism works. We can
now distinguish between the lane that "spawned" a render task (i.e. a
new update) versus the lanes that it's entangled with. Both the update
lane and the entangled lanes will be included while rendering, but by
keeping them separate, we don't lose the original priority.
In practical terms, this means we can now entangle a low priority update
with a higher priority lane while rendering at the lower priority.
To do this, lanes that are entangled at the root are now tracked using
the same variable that we use to track the "base lanes" when revealing a
previously hidden tree — conceptually, they are the same thing. I also
renamed this variable (from subtreeLanes to entangledRenderLanes) to
better reflect how it's used.
My primary motivation is related to useDeferredValue, which I'll address
in a later PR.
DiffTrain build for [309c8ad](309c8ad)
acdlite added a commit that referenced this pull request Oct 17, 2023
### Based on #27505
If a parent render spawns a deferred task with useDeferredValue, but the
parent render suspends, we should not wait for the parent render to
complete before attempting to render the final value.
The reason is that the initialValue argument to useDeferredValue is
meant to represent an immediate preview of the final UI. If we can't
render it "immediately", we might as well skip it and go straight to the
"real" value.
This is an improvement over how a userspace implementation of
useDeferredValue would work, because a userspace implementation would
have to wait for the parent task to commit (useEffect) before spawning
the deferred task, creating a waterfall.
github-actionsBot pushed a commit that referenced this pull request Oct 17, 2023
### Based on #27505
If a parent render spawns a deferred task with useDeferredValue, but the
parent render suspends, we should not wait for the parent render to
complete before attempting to render the final value.
The reason is that the initialValue argument to useDeferredValue is
meant to represent an immediate preview of the final UI. If we can't
render it "immediately", we might as well skip it and go straight to the
"real" value.
This is an improvement over how a userspace implementation of
useDeferredValue would work, because a userspace implementation would
have to wait for the parent task to commit (useEffect) before spawning
the deferred task, creating a waterfall.
DiffTrain build for [b2a68a6](b2a68a6)
kodiakhqBot pushed a commit to vercel/next.js that referenced this pull request Oct 18, 2023
jerrydev0927 added a commit to jerrydev0927/react that referenced this pull request Jan 5, 2024
### Based on react/react#27505
If a parent render spawns a deferred task with useDeferredValue, but the
parent render suspends, we should not wait for the parent render to
complete before attempting to render the final value.
The reason is that the initialValue argument to useDeferredValue is
meant to represent an immediate preview of the final UI. If we can't
render it "immediately", we might as well skip it and go straight to the
"real" value.
This is an improvement over how a userspace implementation of
useDeferredValue would work, because a userspace implementation would
have to wait for the parent task to commit (useEffect) before spawning
the deferred task, creating a waterfall.
DiffTrain build for [b2a68a65c84b63ac86930d88ae5c84380cbbdeb6](react/react@b2a68a6)
EdisonVan pushed a commit to EdisonVan/react that referenced this pull request Apr 15, 2024
A small refactor to how the lane entanglement mechanism works. We can
now distinguish between the lane that "spawned" a render task (i.e. a
new update) versus the lanes that it's entangled with. Both the update
lane and the entangled lanes will be included while rendering, but by
keeping them separate, we don't lose the original priority.
In practical terms, this means we can now entangle a low priority update
with a higher priority lane while rendering at the lower priority.
To do this, lanes that are entangled at the root are now tracked using
the same variable that we use to track the "base lanes" when revealing a
previously hidden tree — conceptually, they are the same thing. I also
renamed this variable (from subtreeLanes to entangledRenderLanes) to
better reflect how it's used.
My primary motivation is related to useDeferredValue, which I'll address
in a later PR.
EdisonVan pushed a commit to EdisonVan/react that referenced this pull request Apr 15, 2024
### Based on react#27505
If a parent render spawns a deferred task with useDeferredValue, but the
parent render suspends, we should not wait for the parent render to
complete before attempting to render the final value.
The reason is that the initialValue argument to useDeferredValue is
meant to represent an immediate preview of the final UI. If we can't
render it "immediately", we might as well skip it and go straight to the
"real" value.
This is an improvement over how a userspace implementation of
useDeferredValue would work, because a userspace implementation would
have to wait for the parent task to commit (useEffect) before spawning
the deferred task, creating a waterfall.
bigfootjon pushed a commit that referenced this pull request Apr 18, 2024
A small refactor to how the lane entanglement mechanism works. We can
now distinguish between the lane that "spawned" a render task (i.e. a
new update) versus the lanes that it's entangled with. Both the update
lane and the entangled lanes will be included while rendering, but by
keeping them separate, we don't lose the original priority.
In practical terms, this means we can now entangle a low priority update
with a higher priority lane while rendering at the lower priority.
To do this, lanes that are entangled at the root are now tracked using
the same variable that we use to track the "base lanes" when revealing a
previously hidden tree — conceptually, they are the same thing. I also
renamed this variable (from subtreeLanes to entangledRenderLanes) to
better reflect how it's used.
My primary motivation is related to useDeferredValue, which I'll address
in a later PR.
DiffTrain build for commit 309c8ad.
acdlite added a commit that referenced this pull request Aug 23, 2024
This is a refactor of the fix in #27505.
When a transition update is scheduled by a popstate event, (i.e. a back/
forward navigation) we attempt to render it synchronously even though
it's a transition, since it's likely the previous page's data is cached.
In #27505, I changed the implementation so that it only "upgrades" the
priority of the transition for a single attempt. If the attempt
suspends, say because the data is not cached after all, from then on it
should be treated as a normal transition.
But it turns out #27505 did not work as intended, because it relied on
marking the root with pending synchronous work (root.pendingLanes),
which was never cleared until the popstate update completed.
The test scenarios I wrote accidentally worked for a different reason
related to suspending the work loop, which I'm currently in the middle
of refactoring.
github-actionsBot pushed a commit that referenced this pull request Aug 23, 2024
This is a refactor of the fix in #27505.
When a transition update is scheduled by a popstate event, (i.e. a back/
forward navigation) we attempt to render it synchronously even though
it's a transition, since it's likely the previous page's data is cached.
In #27505, I changed the implementation so that it only "upgrades" the
priority of the transition for a single attempt. If the attempt
suspends, say because the data is not cached after all, from then on it
should be treated as a normal transition.
But it turns out #27505 did not work as intended, because it relied on
marking the root with pending synchronous work (root.pendingLanes),
which was never cleared until the popstate update completed.
The test scenarios I wrote accidentally worked for a different reason
related to suspending the work loop, which I'm currently in the middle
of refactoring.
DiffTrain build for commit ee7f675.
github-actionsBot pushed a commit that referenced this pull request Aug 23, 2024
This is a refactor of the fix in #27505.
When a transition update is scheduled by a popstate event, (i.e. a back/
forward navigation) we attempt to render it synchronously even though
it's a transition, since it's likely the previous page's data is cached.
In #27505, I changed the implementation so that it only "upgrades" the
priority of the transition for a single attempt. If the attempt
suspends, say because the data is not cached after all, from then on it
should be treated as a normal transition.
But it turns out #27505 did not work as intended, because it relied on
marking the root with pending synchronous work (root.pendingLanes),
which was never cleared until the popstate update completed.
The test scenarios I wrote accidentally worked for a different reason
related to suspending the work loop, which I'm currently in the middle
of refactoring.
DiffTrain build for [ee7f675](ee7f675)
Akshato07 pushed a commit to Akshato07/-Luffy that referenced this pull request Feb 20, 2025
### Based on react/react#27505
If a parent render spawns a deferred task with useDeferredValue, but the
parent render suspends, we should not wait for the parent render to
complete before attempting to render the final value.
The reason is that the initialValue argument to useDeferredValue is
meant to represent an immediate preview of the final UI. If we can't
render it "immediately", we might as well skip it and go straight to the
"real" value.
This is an improvement over how a userspace implementation of
useDeferredValue would work, because a userspace implementation would
have to wait for the parent task to commit (useEffect) before spawning
the deferred task, creating a waterfall.
DiffTrain build for commit react/react@b2a68a6.
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CLA SignedReact Core TeamOpened by a member of the React Core Team

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@acdlite@react-sizebot@sebmarkbage@facebook-github-bot
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Track entangled lanes separately from update lane - #27505

Merged
acdlite merged 2 commits into
react:mainfrom
acdlite:track-entangled-lanes-separately
Oct 15, 2023
Merged

Track entangled lanes separately from update lane#27505
acdlite merged 2 commits into
react:mainfrom
acdlite:track-entangled-lanes-separately

Conversation

@acdlite

Copy link
Copy Markdown
Collaborator

A small refactor to how the lane entanglement mechanism works. We can now distinguish between the lane that "spawned" a render task (i.e. a new update) versus the lanes that it's entangled with. Both the update lane and the entangled lanes will be included while rendering, but by keeping them separate, we don't lose the original priority.

In practical terms, this means we can now entangle a low priority update with a higher priority lane while rendering at the lower priority.

To do this, lanes that are entangled at the root are now tracked using the same variable that we use to track the "base lanes" when revealing a previously hidden tree — conceptually, they are the same thing. I also renamed this variable (from subtreeLanes to entangledRenderLanes) to better reflect how it's used.

My primary motivation is related to useDeferredValue, which I'll address in a later PR.

I updated one of the tests related to synchronous popstate transitions
to clarify what the desired behavior is. It's really about what happens
if a popstate transition suspends. It should not cause an error, and
the transition should be allowed to finish once the promise resolves.
Ideally, if the transition suspends, it should completely revert back
to the default behavior for transitions — i.e. it should no longer be
treated as synchronous. Currently we don't do that, and when the promise
resolve the transition will still be rendered synchronously, but we can
improve this later.
@facebook-github-botfacebook-github-bot added CLA Signed React Core Team Opened by a member of the React Core Team labels Oct 12, 2023
@react-sizebot

react-sizebot commented Oct 12, 2023

Copy link
Copy Markdown

Comparing: e61a60f...717595f

Critical size changes

Includes critical production bundles, as well as any change greater than 2%:

Name+/-BaseCurrent+/- gzipBase gzipCurrent gzip
oss-stable/react-dom/cjs/react-dom.production.min.js+0.09%174.53 kB174.68 kB+0.04%54.29 kB54.32 kB
oss-experimental/react-dom/cjs/react-dom.production.min.js+0.09%176.61 kB176.77 kB+0.09%54.94 kB54.99 kB
facebook-www/ReactDOM-prod.classic.js+0.08%565.12 kB565.55 kB+0.11%99.42 kB99.53 kB
facebook-www/ReactDOM-prod.modern.js+0.08%548.98 kB549.40 kB+0.11%96.50 kB96.60 kB

Significant size changes

Includes any change greater than 0.2%:

Expand to show
Name+/-BaseCurrent+/- gzipBase gzipCurrent gzip
oss-stable-semver/react-reconciler/cjs/react-reconciler.development.js+0.22%931.93 kB933.98 kB+0.22%200.11 kB200.55 kB
oss-stable/react-reconciler/cjs/react-reconciler.development.js+0.22%931.95 kB934.01 kB+0.22%200.14 kB200.58 kB
oss-experimental/react-reconciler/cjs/react-reconciler.development.js+0.22%942.04 kB944.09 kB+0.22%202.00 kB202.46 kB
oss-stable-semver/react-test-renderer/cjs/react-test-renderer.development.js+0.20%813.99 kB815.64 kB+0.25%178.18 kB178.62 kB
oss-stable/react-test-renderer/cjs/react-test-renderer.development.js+0.20%814.02 kB815.67 kB+0.25%178.21 kB178.66 kB
oss-experimental/react-test-renderer/cjs/react-test-renderer.development.js+0.20%815.38 kB817.03 kB+0.25%178.45 kB178.89 kB
facebook-react-native/react-test-renderer/cjs/ReactTestRenderer-dev.js+0.20%826.50 kB828.16 kB+0.23%179.67 kB180.09 kB

Generated by 🚫 dangerJS against 717595f

A small refactor to how the lane entanglement mechanism works. We can
now distinguish between the lane that "spawned" a render task (i.e. a
new update) versus the lanes that it's entangled with. Both the update
lane and the entangled lanes will be included while rendering, but
by keeping them separate, we don't lose the original priority.
In practical terms, this means we can now entangle a low priority update
with a higher priority lane while rendering at the lower priority.
To do this, lanes that are entangled at the root are now tracked using
the same variable that we use to track the "base lanes" when revealing
a previously hidden tree — conceptually, they are the same thing. I
also renamed this variable (from subtreeLanes to entangledRenderLanes)
to better reflect how it's used.
My primary motivation is related to useDeferredValue, which I'll address
in a later PR.
@acdlite
acdlite merged commit 309c8ad into react:mainOct 15, 2023
github-actionsBot pushed a commit that referenced this pull request Oct 15, 2023
A small refactor to how the lane entanglement mechanism works. We can
now distinguish between the lane that "spawned" a render task (i.e. a
new update) versus the lanes that it's entangled with. Both the update
lane and the entangled lanes will be included while rendering, but by
keeping them separate, we don't lose the original priority.
In practical terms, this means we can now entangle a low priority update
with a higher priority lane while rendering at the lower priority.
To do this, lanes that are entangled at the root are now tracked using
the same variable that we use to track the "base lanes" when revealing a
previously hidden tree — conceptually, they are the same thing. I also
renamed this variable (from subtreeLanes to entangledRenderLanes) to
better reflect how it's used.
My primary motivation is related to useDeferredValue, which I'll address
in a later PR.
DiffTrain build for [309c8ad](309c8ad)
acdlite added a commit that referenced this pull request Oct 17, 2023
### Based on #27505
If a parent render spawns a deferred task with useDeferredValue, but the
parent render suspends, we should not wait for the parent render to
complete before attempting to render the final value.
The reason is that the initialValue argument to useDeferredValue is
meant to represent an immediate preview of the final UI. If we can't
render it "immediately", we might as well skip it and go straight to the
"real" value.
This is an improvement over how a userspace implementation of
useDeferredValue would work, because a userspace implementation would
have to wait for the parent task to commit (useEffect) before spawning
the deferred task, creating a waterfall.
github-actionsBot pushed a commit that referenced this pull request Oct 17, 2023
### Based on #27505
If a parent render spawns a deferred task with useDeferredValue, but the
parent render suspends, we should not wait for the parent render to
complete before attempting to render the final value.
The reason is that the initialValue argument to useDeferredValue is
meant to represent an immediate preview of the final UI. If we can't
render it "immediately", we might as well skip it and go straight to the
"real" value.
This is an improvement over how a userspace implementation of
useDeferredValue would work, because a userspace implementation would
have to wait for the parent task to commit (useEffect) before spawning
the deferred task, creating a waterfall.
DiffTrain build for [b2a68a6](b2a68a6)
kodiakhqBot pushed a commit to vercel/next.js that referenced this pull request Oct 18, 2023
jerrydev0927 added a commit to jerrydev0927/react that referenced this pull request Jan 5, 2024
### Based on react/react#27505
If a parent render spawns a deferred task with useDeferredValue, but the
parent render suspends, we should not wait for the parent render to
complete before attempting to render the final value.
The reason is that the initialValue argument to useDeferredValue is
meant to represent an immediate preview of the final UI. If we can't
render it "immediately", we might as well skip it and go straight to the
"real" value.
This is an improvement over how a userspace implementation of
useDeferredValue would work, because a userspace implementation would
have to wait for the parent task to commit (useEffect) before spawning
the deferred task, creating a waterfall.
DiffTrain build for [b2a68a65c84b63ac86930d88ae5c84380cbbdeb6](react/react@b2a68a6)
EdisonVan pushed a commit to EdisonVan/react that referenced this pull request Apr 15, 2024
A small refactor to how the lane entanglement mechanism works. We can
now distinguish between the lane that "spawned" a render task (i.e. a
new update) versus the lanes that it's entangled with. Both the update
lane and the entangled lanes will be included while rendering, but by
keeping them separate, we don't lose the original priority.
In practical terms, this means we can now entangle a low priority update
with a higher priority lane while rendering at the lower priority.
To do this, lanes that are entangled at the root are now tracked using
the same variable that we use to track the "base lanes" when revealing a
previously hidden tree — conceptually, they are the same thing. I also
renamed this variable (from subtreeLanes to entangledRenderLanes) to
better reflect how it's used.
My primary motivation is related to useDeferredValue, which I'll address
in a later PR.
EdisonVan pushed a commit to EdisonVan/react that referenced this pull request Apr 15, 2024
### Based on react#27505
If a parent render spawns a deferred task with useDeferredValue, but the
parent render suspends, we should not wait for the parent render to
complete before attempting to render the final value.
The reason is that the initialValue argument to useDeferredValue is
meant to represent an immediate preview of the final UI. If we can't
render it "immediately", we might as well skip it and go straight to the
"real" value.
This is an improvement over how a userspace implementation of
useDeferredValue would work, because a userspace implementation would
have to wait for the parent task to commit (useEffect) before spawning
the deferred task, creating a waterfall.
bigfootjon pushed a commit that referenced this pull request Apr 18, 2024
A small refactor to how the lane entanglement mechanism works. We can
now distinguish between the lane that "spawned" a render task (i.e. a
new update) versus the lanes that it's entangled with. Both the update
lane and the entangled lanes will be included while rendering, but by
keeping them separate, we don't lose the original priority.
In practical terms, this means we can now entangle a low priority update
with a higher priority lane while rendering at the lower priority.
To do this, lanes that are entangled at the root are now tracked using
the same variable that we use to track the "base lanes" when revealing a
previously hidden tree — conceptually, they are the same thing. I also
renamed this variable (from subtreeLanes to entangledRenderLanes) to
better reflect how it's used.
My primary motivation is related to useDeferredValue, which I'll address
in a later PR.
DiffTrain build for commit 309c8ad.
acdlite added a commit that referenced this pull request Aug 23, 2024
This is a refactor of the fix in #27505.
When a transition update is scheduled by a popstate event, (i.e. a back/
forward navigation) we attempt to render it synchronously even though
it's a transition, since it's likely the previous page's data is cached.
In #27505, I changed the implementation so that it only "upgrades" the
priority of the transition for a single attempt. If the attempt
suspends, say because the data is not cached after all, from then on it
should be treated as a normal transition.
But it turns out #27505 did not work as intended, because it relied on
marking the root with pending synchronous work (root.pendingLanes),
which was never cleared until the popstate update completed.
The test scenarios I wrote accidentally worked for a different reason
related to suspending the work loop, which I'm currently in the middle
of refactoring.
github-actionsBot pushed a commit that referenced this pull request Aug 23, 2024
This is a refactor of the fix in #27505.
When a transition update is scheduled by a popstate event, (i.e. a back/
forward navigation) we attempt to render it synchronously even though
it's a transition, since it's likely the previous page's data is cached.
In #27505, I changed the implementation so that it only "upgrades" the
priority of the transition for a single attempt. If the attempt
suspends, say because the data is not cached after all, from then on it
should be treated as a normal transition.
But it turns out #27505 did not work as intended, because it relied on
marking the root with pending synchronous work (root.pendingLanes),
which was never cleared until the popstate update completed.
The test scenarios I wrote accidentally worked for a different reason
related to suspending the work loop, which I'm currently in the middle
of refactoring.
DiffTrain build for commit ee7f675.
github-actionsBot pushed a commit that referenced this pull request Aug 23, 2024
This is a refactor of the fix in #27505.
When a transition update is scheduled by a popstate event, (i.e. a back/
forward navigation) we attempt to render it synchronously even though
it's a transition, since it's likely the previous page's data is cached.
In #27505, I changed the implementation so that it only "upgrades" the
priority of the transition for a single attempt. If the attempt
suspends, say because the data is not cached after all, from then on it
should be treated as a normal transition.
But it turns out #27505 did not work as intended, because it relied on
marking the root with pending synchronous work (root.pendingLanes),
which was never cleared until the popstate update completed.
The test scenarios I wrote accidentally worked for a different reason
related to suspending the work loop, which I'm currently in the middle
of refactoring.
DiffTrain build for [ee7f675](ee7f675)
Akshato07 pushed a commit to Akshato07/-Luffy that referenced this pull request Feb 20, 2025
### Based on react/react#27505
If a parent render spawns a deferred task with useDeferredValue, but the
parent render suspends, we should not wait for the parent render to
complete before attempting to render the final value.
The reason is that the initialValue argument to useDeferredValue is
meant to represent an immediate preview of the final UI. If we can't
render it "immediately", we might as well skip it and go straight to the
"real" value.
This is an improvement over how a userspace implementation of
useDeferredValue would work, because a userspace implementation would
have to wait for the parent task to commit (useEffect) before spawning
the deferred task, creating a waterfall.
DiffTrain build for commit react/react@b2a68a6.
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CLA SignedReact Core TeamOpened by a member of the React Core Team

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@acdlite@react-sizebot@sebmarkbage@facebook-github-bot
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Track entangled lanes separately from update lane - #27505

Merged
acdlite merged 2 commits into
react:mainfrom
acdlite:track-entangled-lanes-separately
Oct 15, 2023
Merged

Track entangled lanes separately from update lane#27505
acdlite merged 2 commits into
react:mainfrom
acdlite:track-entangled-lanes-separately

Conversation

@acdlite

Copy link
Copy Markdown
Collaborator

A small refactor to how the lane entanglement mechanism works. We can now distinguish between the lane that "spawned" a render task (i.e. a new update) versus the lanes that it's entangled with. Both the update lane and the entangled lanes will be included while rendering, but by keeping them separate, we don't lose the original priority.

In practical terms, this means we can now entangle a low priority update with a higher priority lane while rendering at the lower priority.

To do this, lanes that are entangled at the root are now tracked using the same variable that we use to track the "base lanes" when revealing a previously hidden tree — conceptually, they are the same thing. I also renamed this variable (from subtreeLanes to entangledRenderLanes) to better reflect how it's used.

My primary motivation is related to useDeferredValue, which I'll address in a later PR.

I updated one of the tests related to synchronous popstate transitions
to clarify what the desired behavior is. It's really about what happens
if a popstate transition suspends. It should not cause an error, and
the transition should be allowed to finish once the promise resolves.
Ideally, if the transition suspends, it should completely revert back
to the default behavior for transitions — i.e. it should no longer be
treated as synchronous. Currently we don't do that, and when the promise
resolve the transition will still be rendered synchronously, but we can
improve this later.
@facebook-github-botfacebook-github-bot added CLA Signed React Core Team Opened by a member of the React Core Team labels Oct 12, 2023
@react-sizebot

react-sizebot commented Oct 12, 2023

Copy link
Copy Markdown

Comparing: e61a60f...717595f

Critical size changes

Includes critical production bundles, as well as any change greater than 2%:

Name+/-BaseCurrent+/- gzipBase gzipCurrent gzip
oss-stable/react-dom/cjs/react-dom.production.min.js+0.09%174.53 kB174.68 kB+0.04%54.29 kB54.32 kB
oss-experimental/react-dom/cjs/react-dom.production.min.js+0.09%176.61 kB176.77 kB+0.09%54.94 kB54.99 kB
facebook-www/ReactDOM-prod.classic.js+0.08%565.12 kB565.55 kB+0.11%99.42 kB99.53 kB
facebook-www/ReactDOM-prod.modern.js+0.08%548.98 kB549.40 kB+0.11%96.50 kB96.60 kB

Significant size changes

Includes any change greater than 0.2%:

Expand to show
Name+/-BaseCurrent+/- gzipBase gzipCurrent gzip
oss-stable-semver/react-reconciler/cjs/react-reconciler.development.js+0.22%931.93 kB933.98 kB+0.22%200.11 kB200.55 kB
oss-stable/react-reconciler/cjs/react-reconciler.development.js+0.22%931.95 kB934.01 kB+0.22%200.14 kB200.58 kB
oss-experimental/react-reconciler/cjs/react-reconciler.development.js+0.22%942.04 kB944.09 kB+0.22%202.00 kB202.46 kB
oss-stable-semver/react-test-renderer/cjs/react-test-renderer.development.js+0.20%813.99 kB815.64 kB+0.25%178.18 kB178.62 kB
oss-stable/react-test-renderer/cjs/react-test-renderer.development.js+0.20%814.02 kB815.67 kB+0.25%178.21 kB178.66 kB
oss-experimental/react-test-renderer/cjs/react-test-renderer.development.js+0.20%815.38 kB817.03 kB+0.25%178.45 kB178.89 kB
facebook-react-native/react-test-renderer/cjs/ReactTestRenderer-dev.js+0.20%826.50 kB828.16 kB+0.23%179.67 kB180.09 kB

Generated by 🚫 dangerJS against 717595f

A small refactor to how the lane entanglement mechanism works. We can
now distinguish between the lane that "spawned" a render task (i.e. a
new update) versus the lanes that it's entangled with. Both the update
lane and the entangled lanes will be included while rendering, but
by keeping them separate, we don't lose the original priority.
In practical terms, this means we can now entangle a low priority update
with a higher priority lane while rendering at the lower priority.
To do this, lanes that are entangled at the root are now tracked using
the same variable that we use to track the "base lanes" when revealing
a previously hidden tree — conceptually, they are the same thing. I
also renamed this variable (from subtreeLanes to entangledRenderLanes)
to better reflect how it's used.
My primary motivation is related to useDeferredValue, which I'll address
in a later PR.
@acdlite
acdlite merged commit 309c8ad into react:mainOct 15, 2023
github-actionsBot pushed a commit that referenced this pull request Oct 15, 2023
A small refactor to how the lane entanglement mechanism works. We can
now distinguish between the lane that "spawned" a render task (i.e. a
new update) versus the lanes that it's entangled with. Both the update
lane and the entangled lanes will be included while rendering, but by
keeping them separate, we don't lose the original priority.
In practical terms, this means we can now entangle a low priority update
with a higher priority lane while rendering at the lower priority.
To do this, lanes that are entangled at the root are now tracked using
the same variable that we use to track the "base lanes" when revealing a
previously hidden tree — conceptually, they are the same thing. I also
renamed this variable (from subtreeLanes to entangledRenderLanes) to
better reflect how it's used.
My primary motivation is related to useDeferredValue, which I'll address
in a later PR.
DiffTrain build for [309c8ad](309c8ad)
acdlite added a commit that referenced this pull request Oct 17, 2023
### Based on #27505
If a parent render spawns a deferred task with useDeferredValue, but the
parent render suspends, we should not wait for the parent render to
complete before attempting to render the final value.
The reason is that the initialValue argument to useDeferredValue is
meant to represent an immediate preview of the final UI. If we can't
render it "immediately", we might as well skip it and go straight to the
"real" value.
This is an improvement over how a userspace implementation of
useDeferredValue would work, because a userspace implementation would
have to wait for the parent task to commit (useEffect) before spawning
the deferred task, creating a waterfall.
github-actionsBot pushed a commit that referenced this pull request Oct 17, 2023
### Based on #27505
If a parent render spawns a deferred task with useDeferredValue, but the
parent render suspends, we should not wait for the parent render to
complete before attempting to render the final value.
The reason is that the initialValue argument to useDeferredValue is
meant to represent an immediate preview of the final UI. If we can't
render it "immediately", we might as well skip it and go straight to the
"real" value.
This is an improvement over how a userspace implementation of
useDeferredValue would work, because a userspace implementation would
have to wait for the parent task to commit (useEffect) before spawning
the deferred task, creating a waterfall.
DiffTrain build for [b2a68a6](b2a68a6)
kodiakhqBot pushed a commit to vercel/next.js that referenced this pull request Oct 18, 2023
jerrydev0927 added a commit to jerrydev0927/react that referenced this pull request Jan 5, 2024
### Based on react/react#27505
If a parent render spawns a deferred task with useDeferredValue, but the
parent render suspends, we should not wait for the parent render to
complete before attempting to render the final value.
The reason is that the initialValue argument to useDeferredValue is
meant to represent an immediate preview of the final UI. If we can't
render it "immediately", we might as well skip it and go straight to the
"real" value.
This is an improvement over how a userspace implementation of
useDeferredValue would work, because a userspace implementation would
have to wait for the parent task to commit (useEffect) before spawning
the deferred task, creating a waterfall.
DiffTrain build for [b2a68a65c84b63ac86930d88ae5c84380cbbdeb6](react/react@b2a68a6)
EdisonVan pushed a commit to EdisonVan/react that referenced this pull request Apr 15, 2024
A small refactor to how the lane entanglement mechanism works. We can
now distinguish between the lane that "spawned" a render task (i.e. a
new update) versus the lanes that it's entangled with. Both the update
lane and the entangled lanes will be included while rendering, but by
keeping them separate, we don't lose the original priority.
In practical terms, this means we can now entangle a low priority update
with a higher priority lane while rendering at the lower priority.
To do this, lanes that are entangled at the root are now tracked using
the same variable that we use to track the "base lanes" when revealing a
previously hidden tree — conceptually, they are the same thing. I also
renamed this variable (from subtreeLanes to entangledRenderLanes) to
better reflect how it's used.
My primary motivation is related to useDeferredValue, which I'll address
in a later PR.
EdisonVan pushed a commit to EdisonVan/react that referenced this pull request Apr 15, 2024
### Based on react#27505
If a parent render spawns a deferred task with useDeferredValue, but the
parent render suspends, we should not wait for the parent render to
complete before attempting to render the final value.
The reason is that the initialValue argument to useDeferredValue is
meant to represent an immediate preview of the final UI. If we can't
render it "immediately", we might as well skip it and go straight to the
"real" value.
This is an improvement over how a userspace implementation of
useDeferredValue would work, because a userspace implementation would
have to wait for the parent task to commit (useEffect) before spawning
the deferred task, creating a waterfall.
bigfootjon pushed a commit that referenced this pull request Apr 18, 2024
A small refactor to how the lane entanglement mechanism works. We can
now distinguish between the lane that "spawned" a render task (i.e. a
new update) versus the lanes that it's entangled with. Both the update
lane and the entangled lanes will be included while rendering, but by
keeping them separate, we don't lose the original priority.
In practical terms, this means we can now entangle a low priority update
with a higher priority lane while rendering at the lower priority.
To do this, lanes that are entangled at the root are now tracked using
the same variable that we use to track the "base lanes" when revealing a
previously hidden tree — conceptually, they are the same thing. I also
renamed this variable (from subtreeLanes to entangledRenderLanes) to
better reflect how it's used.
My primary motivation is related to useDeferredValue, which I'll address
in a later PR.
DiffTrain build for commit 309c8ad.
acdlite added a commit that referenced this pull request Aug 23, 2024
This is a refactor of the fix in #27505.
When a transition update is scheduled by a popstate event, (i.e. a back/
forward navigation) we attempt to render it synchronously even though
it's a transition, since it's likely the previous page's data is cached.
In #27505, I changed the implementation so that it only "upgrades" the
priority of the transition for a single attempt. If the attempt
suspends, say because the data is not cached after all, from then on it
should be treated as a normal transition.
But it turns out #27505 did not work as intended, because it relied on
marking the root with pending synchronous work (root.pendingLanes),
which was never cleared until the popstate update completed.
The test scenarios I wrote accidentally worked for a different reason
related to suspending the work loop, which I'm currently in the middle
of refactoring.
github-actionsBot pushed a commit that referenced this pull request Aug 23, 2024
This is a refactor of the fix in #27505.
When a transition update is scheduled by a popstate event, (i.e. a back/
forward navigation) we attempt to render it synchronously even though
it's a transition, since it's likely the previous page's data is cached.
In #27505, I changed the implementation so that it only "upgrades" the
priority of the transition for a single attempt. If the attempt
suspends, say because the data is not cached after all, from then on it
should be treated as a normal transition.
But it turns out #27505 did not work as intended, because it relied on
marking the root with pending synchronous work (root.pendingLanes),
which was never cleared until the popstate update completed.
The test scenarios I wrote accidentally worked for a different reason
related to suspending the work loop, which I'm currently in the middle
of refactoring.
DiffTrain build for commit ee7f675.
github-actionsBot pushed a commit that referenced this pull request Aug 23, 2024
This is a refactor of the fix in #27505.
When a transition update is scheduled by a popstate event, (i.e. a back/
forward navigation) we attempt to render it synchronously even though
it's a transition, since it's likely the previous page's data is cached.
In #27505, I changed the implementation so that it only "upgrades" the
priority of the transition for a single attempt. If the attempt
suspends, say because the data is not cached after all, from then on it
should be treated as a normal transition.
But it turns out #27505 did not work as intended, because it relied on
marking the root with pending synchronous work (root.pendingLanes),
which was never cleared until the popstate update completed.
The test scenarios I wrote accidentally worked for a different reason
related to suspending the work loop, which I'm currently in the middle
of refactoring.
DiffTrain build for [ee7f675](ee7f675)
Akshato07 pushed a commit to Akshato07/-Luffy that referenced this pull request Feb 20, 2025
### Based on react/react#27505
If a parent render spawns a deferred task with useDeferredValue, but the
parent render suspends, we should not wait for the parent render to
complete before attempting to render the final value.
The reason is that the initialValue argument to useDeferredValue is
meant to represent an immediate preview of the final UI. If we can't
render it "immediately", we might as well skip it and go straight to the
"real" value.
This is an improvement over how a userspace implementation of
useDeferredValue would work, because a userspace implementation would
have to wait for the parent task to commit (useEffect) before spawning
the deferred task, creating a waterfall.
DiffTrain build for commit react/react@b2a68a6.
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CLA SignedReact Core TeamOpened by a member of the React Core Team

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@acdlite@react-sizebot@sebmarkbage@facebook-github-bot
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

Track entangled lanes separately from update lane - #27505

Merged
acdlite merged 2 commits into
react:mainfrom
acdlite:track-entangled-lanes-separately
Oct 15, 2023
Merged

Track entangled lanes separately from update lane#27505
acdlite merged 2 commits into
react:mainfrom
acdlite:track-entangled-lanes-separately

Conversation

@acdlite

Copy link
Copy Markdown
Collaborator

A small refactor to how the lane entanglement mechanism works. We can now distinguish between the lane that "spawned" a render task (i.e. a new update) versus the lanes that it's entangled with. Both the update lane and the entangled lanes will be included while rendering, but by keeping them separate, we don't lose the original priority.

In practical terms, this means we can now entangle a low priority update with a higher priority lane while rendering at the lower priority.

To do this, lanes that are entangled at the root are now tracked using the same variable that we use to track the "base lanes" when revealing a previously hidden tree — conceptually, they are the same thing. I also renamed this variable (from subtreeLanes to entangledRenderLanes) to better reflect how it's used.

My primary motivation is related to useDeferredValue, which I'll address in a later PR.

I updated one of the tests related to synchronous popstate transitions
to clarify what the desired behavior is. It's really about what happens
if a popstate transition suspends. It should not cause an error, and
the transition should be allowed to finish once the promise resolves.
Ideally, if the transition suspends, it should completely revert back
to the default behavior for transitions — i.e. it should no longer be
treated as synchronous. Currently we don't do that, and when the promise
resolve the transition will still be rendered synchronously, but we can
improve this later.
@facebook-github-botfacebook-github-bot added CLA Signed React Core Team Opened by a member of the React Core Team labels Oct 12, 2023
@react-sizebot

react-sizebot commented Oct 12, 2023

Copy link
Copy Markdown

Comparing: e61a60f...717595f

Critical size changes

Includes critical production bundles, as well as any change greater than 2%:

Name+/-BaseCurrent+/- gzipBase gzipCurrent gzip
oss-stable/react-dom/cjs/react-dom.production.min.js+0.09%174.53 kB174.68 kB+0.04%54.29 kB54.32 kB
oss-experimental/react-dom/cjs/react-dom.production.min.js+0.09%176.61 kB176.77 kB+0.09%54.94 kB54.99 kB
facebook-www/ReactDOM-prod.classic.js+0.08%565.12 kB565.55 kB+0.11%99.42 kB99.53 kB
facebook-www/ReactDOM-prod.modern.js+0.08%548.98 kB549.40 kB+0.11%96.50 kB96.60 kB

Significant size changes

Includes any change greater than 0.2%:

Expand to show
Name+/-BaseCurrent+/- gzipBase gzipCurrent gzip
oss-stable-semver/react-reconciler/cjs/react-reconciler.development.js+0.22%931.93 kB933.98 kB+0.22%200.11 kB200.55 kB
oss-stable/react-reconciler/cjs/react-reconciler.development.js+0.22%931.95 kB934.01 kB+0.22%200.14 kB200.58 kB
oss-experimental/react-reconciler/cjs/react-reconciler.development.js+0.22%942.04 kB944.09 kB+0.22%202.00 kB202.46 kB
oss-stable-semver/react-test-renderer/cjs/react-test-renderer.development.js+0.20%813.99 kB815.64 kB+0.25%178.18 kB178.62 kB
oss-stable/react-test-renderer/cjs/react-test-renderer.development.js+0.20%814.02 kB815.67 kB+0.25%178.21 kB178.66 kB
oss-experimental/react-test-renderer/cjs/react-test-renderer.development.js+0.20%815.38 kB817.03 kB+0.25%178.45 kB178.89 kB
facebook-react-native/react-test-renderer/cjs/ReactTestRenderer-dev.js+0.20%826.50 kB828.16 kB+0.23%179.67 kB180.09 kB

Generated by 🚫 dangerJS against 717595f

A small refactor to how the lane entanglement mechanism works. We can
now distinguish between the lane that "spawned" a render task (i.e. a
new update) versus the lanes that it's entangled with. Both the update
lane and the entangled lanes will be included while rendering, but
by keeping them separate, we don't lose the original priority.
In practical terms, this means we can now entangle a low priority update
with a higher priority lane while rendering at the lower priority.
To do this, lanes that are entangled at the root are now tracked using
the same variable that we use to track the "base lanes" when revealing
a previously hidden tree — conceptually, they are the same thing. I
also renamed this variable (from subtreeLanes to entangledRenderLanes)
to better reflect how it's used.
My primary motivation is related to useDeferredValue, which I'll address
in a later PR.
@acdlite
acdlite merged commit 309c8ad into react:mainOct 15, 2023
github-actionsBot pushed a commit that referenced this pull request Oct 15, 2023
A small refactor to how the lane entanglement mechanism works. We can
now distinguish between the lane that "spawned" a render task (i.e. a
new update) versus the lanes that it's entangled with. Both the update
lane and the entangled lanes will be included while rendering, but by
keeping them separate, we don't lose the original priority.
In practical terms, this means we can now entangle a low priority update
with a higher priority lane while rendering at the lower priority.
To do this, lanes that are entangled at the root are now tracked using
the same variable that we use to track the "base lanes" when revealing a
previously hidden tree — conceptually, they are the same thing. I also
renamed this variable (from subtreeLanes to entangledRenderLanes) to
better reflect how it's used.
My primary motivation is related to useDeferredValue, which I'll address
in a later PR.
DiffTrain build for [309c8ad](309c8ad)
acdlite added a commit that referenced this pull request Oct 17, 2023
### Based on #27505
If a parent render spawns a deferred task with useDeferredValue, but the
parent render suspends, we should not wait for the parent render to
complete before attempting to render the final value.
The reason is that the initialValue argument to useDeferredValue is
meant to represent an immediate preview of the final UI. If we can't
render it "immediately", we might as well skip it and go straight to the
"real" value.
This is an improvement over how a userspace implementation of
useDeferredValue would work, because a userspace implementation would
have to wait for the parent task to commit (useEffect) before spawning
the deferred task, creating a waterfall.
github-actionsBot pushed a commit that referenced this pull request Oct 17, 2023
### Based on #27505
If a parent render spawns a deferred task with useDeferredValue, but the
parent render suspends, we should not wait for the parent render to
complete before attempting to render the final value.
The reason is that the initialValue argument to useDeferredValue is
meant to represent an immediate preview of the final UI. If we can't
render it "immediately", we might as well skip it and go straight to the
"real" value.
This is an improvement over how a userspace implementation of
useDeferredValue would work, because a userspace implementation would
have to wait for the parent task to commit (useEffect) before spawning
the deferred task, creating a waterfall.
DiffTrain build for [b2a68a6](b2a68a6)
kodiakhqBot pushed a commit to vercel/next.js that referenced this pull request Oct 18, 2023
jerrydev0927 added a commit to jerrydev0927/react that referenced this pull request Jan 5, 2024
### Based on react/react#27505
If a parent render spawns a deferred task with useDeferredValue, but the
parent render suspends, we should not wait for the parent render to
complete before attempting to render the final value.
The reason is that the initialValue argument to useDeferredValue is
meant to represent an immediate preview of the final UI. If we can't
render it "immediately", we might as well skip it and go straight to the
"real" value.
This is an improvement over how a userspace implementation of
useDeferredValue would work, because a userspace implementation would
have to wait for the parent task to commit (useEffect) before spawning
the deferred task, creating a waterfall.
DiffTrain build for [b2a68a65c84b63ac86930d88ae5c84380cbbdeb6](react/react@b2a68a6)
EdisonVan pushed a commit to EdisonVan/react that referenced this pull request Apr 15, 2024
A small refactor to how the lane entanglement mechanism works. We can
now distinguish between the lane that "spawned" a render task (i.e. a
new update) versus the lanes that it's entangled with. Both the update
lane and the entangled lanes will be included while rendering, but by
keeping them separate, we don't lose the original priority.
In practical terms, this means we can now entangle a low priority update
with a higher priority lane while rendering at the lower priority.
To do this, lanes that are entangled at the root are now tracked using
the same variable that we use to track the "base lanes" when revealing a
previously hidden tree — conceptually, they are the same thing. I also
renamed this variable (from subtreeLanes to entangledRenderLanes) to
better reflect how it's used.
My primary motivation is related to useDeferredValue, which I'll address
in a later PR.
EdisonVan pushed a commit to EdisonVan/react that referenced this pull request Apr 15, 2024
### Based on react#27505
If a parent render spawns a deferred task with useDeferredValue, but the
parent render suspends, we should not wait for the parent render to
complete before attempting to render the final value.
The reason is that the initialValue argument to useDeferredValue is
meant to represent an immediate preview of the final UI. If we can't
render it "immediately", we might as well skip it and go straight to the
"real" value.
This is an improvement over how a userspace implementation of
useDeferredValue would work, because a userspace implementation would
have to wait for the parent task to commit (useEffect) before spawning
the deferred task, creating a waterfall.
bigfootjon pushed a commit that referenced this pull request Apr 18, 2024
A small refactor to how the lane entanglement mechanism works. We can
now distinguish between the lane that "spawned" a render task (i.e. a
new update) versus the lanes that it's entangled with. Both the update
lane and the entangled lanes will be included while rendering, but by
keeping them separate, we don't lose the original priority.
In practical terms, this means we can now entangle a low priority update
with a higher priority lane while rendering at the lower priority.
To do this, lanes that are entangled at the root are now tracked using
the same variable that we use to track the "base lanes" when revealing a
previously hidden tree — conceptually, they are the same thing. I also
renamed this variable (from subtreeLanes to entangledRenderLanes) to
better reflect how it's used.
My primary motivation is related to useDeferredValue, which I'll address
in a later PR.
DiffTrain build for commit 309c8ad.
acdlite added a commit that referenced this pull request Aug 23, 2024
This is a refactor of the fix in #27505.
When a transition update is scheduled by a popstate event, (i.e. a back/
forward navigation) we attempt to render it synchronously even though
it's a transition, since it's likely the previous page's data is cached.
In #27505, I changed the implementation so that it only "upgrades" the
priority of the transition for a single attempt. If the attempt
suspends, say because the data is not cached after all, from then on it
should be treated as a normal transition.
But it turns out #27505 did not work as intended, because it relied on
marking the root with pending synchronous work (root.pendingLanes),
which was never cleared until the popstate update completed.
The test scenarios I wrote accidentally worked for a different reason
related to suspending the work loop, which I'm currently in the middle
of refactoring.
github-actionsBot pushed a commit that referenced this pull request Aug 23, 2024
This is a refactor of the fix in #27505.
When a transition update is scheduled by a popstate event, (i.e. a back/
forward navigation) we attempt to render it synchronously even though
it's a transition, since it's likely the previous page's data is cached.
In #27505, I changed the implementation so that it only "upgrades" the
priority of the transition for a single attempt. If the attempt
suspends, say because the data is not cached after all, from then on it
should be treated as a normal transition.
But it turns out #27505 did not work as intended, because it relied on
marking the root with pending synchronous work (root.pendingLanes),
which was never cleared until the popstate update completed.
The test scenarios I wrote accidentally worked for a different reason
related to suspending the work loop, which I'm currently in the middle
of refactoring.
DiffTrain build for commit ee7f675.
github-actionsBot pushed a commit that referenced this pull request Aug 23, 2024
This is a refactor of the fix in #27505.
When a transition update is scheduled by a popstate event, (i.e. a back/
forward navigation) we attempt to render it synchronously even though
it's a transition, since it's likely the previous page's data is cached.
In #27505, I changed the implementation so that it only "upgrades" the
priority of the transition for a single attempt. If the attempt
suspends, say because the data is not cached after all, from then on it
should be treated as a normal transition.
But it turns out #27505 did not work as intended, because it relied on
marking the root with pending synchronous work (root.pendingLanes),
which was never cleared until the popstate update completed.
The test scenarios I wrote accidentally worked for a different reason
related to suspending the work loop, which I'm currently in the middle
of refactoring.
DiffTrain build for [ee7f675](ee7f675)
Akshato07 pushed a commit to Akshato07/-Luffy that referenced this pull request Feb 20, 2025
### Based on react/react#27505
If a parent render spawns a deferred task with useDeferredValue, but the
parent render suspends, we should not wait for the parent render to
complete before attempting to render the final value.
The reason is that the initialValue argument to useDeferredValue is
meant to represent an immediate preview of the final UI. If we can't
render it "immediately", we might as well skip it and go straight to the
"real" value.
This is an improvement over how a userspace implementation of
useDeferredValue would work, because a userspace implementation would
have to wait for the parent task to commit (useEffect) before spawning
the deferred task, creating a waterfall.
DiffTrain build for commit react/react@b2a68a6.
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CLA SignedReact Core TeamOpened by a member of the React Core Team

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@acdlite@react-sizebot@sebmarkbage@facebook-github-bot
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Track entangled lanes separately from update lane - #27505

Merged
acdlite merged 2 commits into
react:mainfrom
acdlite:track-entangled-lanes-separately
Oct 15, 2023
Merged

Track entangled lanes separately from update lane#27505
acdlite merged 2 commits into
react:mainfrom
acdlite:track-entangled-lanes-separately

Conversation

@acdlite

Copy link
Copy Markdown
Collaborator

A small refactor to how the lane entanglement mechanism works. We can now distinguish between the lane that "spawned" a render task (i.e. a new update) versus the lanes that it's entangled with. Both the update lane and the entangled lanes will be included while rendering, but by keeping them separate, we don't lose the original priority.

In practical terms, this means we can now entangle a low priority update with a higher priority lane while rendering at the lower priority.

To do this, lanes that are entangled at the root are now tracked using the same variable that we use to track the "base lanes" when revealing a previously hidden tree — conceptually, they are the same thing. I also renamed this variable (from subtreeLanes to entangledRenderLanes) to better reflect how it's used.

My primary motivation is related to useDeferredValue, which I'll address in a later PR.

I updated one of the tests related to synchronous popstate transitions
to clarify what the desired behavior is. It's really about what happens
if a popstate transition suspends. It should not cause an error, and
the transition should be allowed to finish once the promise resolves.
Ideally, if the transition suspends, it should completely revert back
to the default behavior for transitions — i.e. it should no longer be
treated as synchronous. Currently we don't do that, and when the promise
resolve the transition will still be rendered synchronously, but we can
improve this later.
@facebook-github-botfacebook-github-bot added CLA Signed React Core Team Opened by a member of the React Core Team labels Oct 12, 2023
@react-sizebot

react-sizebot commented Oct 12, 2023

Copy link
Copy Markdown

Comparing: e61a60f...717595f

Critical size changes

Includes critical production bundles, as well as any change greater than 2%:

Name+/-BaseCurrent+/- gzipBase gzipCurrent gzip
oss-stable/react-dom/cjs/react-dom.production.min.js+0.09%174.53 kB174.68 kB+0.04%54.29 kB54.32 kB
oss-experimental/react-dom/cjs/react-dom.production.min.js+0.09%176.61 kB176.77 kB+0.09%54.94 kB54.99 kB
facebook-www/ReactDOM-prod.classic.js+0.08%565.12 kB565.55 kB+0.11%99.42 kB99.53 kB
facebook-www/ReactDOM-prod.modern.js+0.08%548.98 kB549.40 kB+0.11%96.50 kB96.60 kB

Significant size changes

Includes any change greater than 0.2%:

Expand to show
Name+/-BaseCurrent+/- gzipBase gzipCurrent gzip
oss-stable-semver/react-reconciler/cjs/react-reconciler.development.js+0.22%931.93 kB933.98 kB+0.22%200.11 kB200.55 kB
oss-stable/react-reconciler/cjs/react-reconciler.development.js+0.22%931.95 kB934.01 kB+0.22%200.14 kB200.58 kB
oss-experimental/react-reconciler/cjs/react-reconciler.development.js+0.22%942.04 kB944.09 kB+0.22%202.00 kB202.46 kB
oss-stable-semver/react-test-renderer/cjs/react-test-renderer.development.js+0.20%813.99 kB815.64 kB+0.25%178.18 kB178.62 kB
oss-stable/react-test-renderer/cjs/react-test-renderer.development.js+0.20%814.02 kB815.67 kB+0.25%178.21 kB178.66 kB
oss-experimental/react-test-renderer/cjs/react-test-renderer.development.js+0.20%815.38 kB817.03 kB+0.25%178.45 kB178.89 kB
facebook-react-native/react-test-renderer/cjs/ReactTestRenderer-dev.js+0.20%826.50 kB828.16 kB+0.23%179.67 kB180.09 kB

Generated by 🚫 dangerJS against 717595f

A small refactor to how the lane entanglement mechanism works. We can
now distinguish between the lane that "spawned" a render task (i.e. a
new update) versus the lanes that it's entangled with. Both the update
lane and the entangled lanes will be included while rendering, but
by keeping them separate, we don't lose the original priority.
In practical terms, this means we can now entangle a low priority update
with a higher priority lane while rendering at the lower priority.
To do this, lanes that are entangled at the root are now tracked using
the same variable that we use to track the "base lanes" when revealing
a previously hidden tree — conceptually, they are the same thing. I
also renamed this variable (from subtreeLanes to entangledRenderLanes)
to better reflect how it's used.
My primary motivation is related to useDeferredValue, which I'll address
in a later PR.
@acdlite
acdlite merged commit 309c8ad into react:mainOct 15, 2023
github-actionsBot pushed a commit that referenced this pull request Oct 15, 2023
A small refactor to how the lane entanglement mechanism works. We can
now distinguish between the lane that "spawned" a render task (i.e. a
new update) versus the lanes that it's entangled with. Both the update
lane and the entangled lanes will be included while rendering, but by
keeping them separate, we don't lose the original priority.
In practical terms, this means we can now entangle a low priority update
with a higher priority lane while rendering at the lower priority.
To do this, lanes that are entangled at the root are now tracked using
the same variable that we use to track the "base lanes" when revealing a
previously hidden tree — conceptually, they are the same thing. I also
renamed this variable (from subtreeLanes to entangledRenderLanes) to
better reflect how it's used.
My primary motivation is related to useDeferredValue, which I'll address
in a later PR.
DiffTrain build for [309c8ad](309c8ad)
acdlite added a commit that referenced this pull request Oct 17, 2023
### Based on #27505
If a parent render spawns a deferred task with useDeferredValue, but the
parent render suspends, we should not wait for the parent render to
complete before attempting to render the final value.
The reason is that the initialValue argument to useDeferredValue is
meant to represent an immediate preview of the final UI. If we can't
render it "immediately", we might as well skip it and go straight to the
"real" value.
This is an improvement over how a userspace implementation of
useDeferredValue would work, because a userspace implementation would
have to wait for the parent task to commit (useEffect) before spawning
the deferred task, creating a waterfall.
github-actionsBot pushed a commit that referenced this pull request Oct 17, 2023
### Based on #27505
If a parent render spawns a deferred task with useDeferredValue, but the
parent render suspends, we should not wait for the parent render to
complete before attempting to render the final value.
The reason is that the initialValue argument to useDeferredValue is
meant to represent an immediate preview of the final UI. If we can't
render it "immediately", we might as well skip it and go straight to the
"real" value.
This is an improvement over how a userspace implementation of
useDeferredValue would work, because a userspace implementation would
have to wait for the parent task to commit (useEffect) before spawning
the deferred task, creating a waterfall.
DiffTrain build for [b2a68a6](b2a68a6)
kodiakhqBot pushed a commit to vercel/next.js that referenced this pull request Oct 18, 2023
jerrydev0927 added a commit to jerrydev0927/react that referenced this pull request Jan 5, 2024
### Based on react/react#27505
If a parent render spawns a deferred task with useDeferredValue, but the
parent render suspends, we should not wait for the parent render to
complete before attempting to render the final value.
The reason is that the initialValue argument to useDeferredValue is
meant to represent an immediate preview of the final UI. If we can't
render it "immediately", we might as well skip it and go straight to the
"real" value.
This is an improvement over how a userspace implementation of
useDeferredValue would work, because a userspace implementation would
have to wait for the parent task to commit (useEffect) before spawning
the deferred task, creating a waterfall.
DiffTrain build for [b2a68a65c84b63ac86930d88ae5c84380cbbdeb6](react/react@b2a68a6)
EdisonVan pushed a commit to EdisonVan/react that referenced this pull request Apr 15, 2024
A small refactor to how the lane entanglement mechanism works. We can
now distinguish between the lane that "spawned" a render task (i.e. a
new update) versus the lanes that it's entangled with. Both the update
lane and the entangled lanes will be included while rendering, but by
keeping them separate, we don't lose the original priority.
In practical terms, this means we can now entangle a low priority update
with a higher priority lane while rendering at the lower priority.
To do this, lanes that are entangled at the root are now tracked using
the same variable that we use to track the "base lanes" when revealing a
previously hidden tree — conceptually, they are the same thing. I also
renamed this variable (from subtreeLanes to entangledRenderLanes) to
better reflect how it's used.
My primary motivation is related to useDeferredValue, which I'll address
in a later PR.
EdisonVan pushed a commit to EdisonVan/react that referenced this pull request Apr 15, 2024
### Based on react#27505
If a parent render spawns a deferred task with useDeferredValue, but the
parent render suspends, we should not wait for the parent render to
complete before attempting to render the final value.
The reason is that the initialValue argument to useDeferredValue is
meant to represent an immediate preview of the final UI. If we can't
render it "immediately", we might as well skip it and go straight to the
"real" value.
This is an improvement over how a userspace implementation of
useDeferredValue would work, because a userspace implementation would
have to wait for the parent task to commit (useEffect) before spawning
the deferred task, creating a waterfall.
bigfootjon pushed a commit that referenced this pull request Apr 18, 2024
A small refactor to how the lane entanglement mechanism works. We can
now distinguish between the lane that "spawned" a render task (i.e. a
new update) versus the lanes that it's entangled with. Both the update
lane and the entangled lanes will be included while rendering, but by
keeping them separate, we don't lose the original priority.
In practical terms, this means we can now entangle a low priority update
with a higher priority lane while rendering at the lower priority.
To do this, lanes that are entangled at the root are now tracked using
the same variable that we use to track the "base lanes" when revealing a
previously hidden tree — conceptually, they are the same thing. I also
renamed this variable (from subtreeLanes to entangledRenderLanes) to
better reflect how it's used.
My primary motivation is related to useDeferredValue, which I'll address
in a later PR.
DiffTrain build for commit 309c8ad.
acdlite added a commit that referenced this pull request Aug 23, 2024
This is a refactor of the fix in #27505.
When a transition update is scheduled by a popstate event, (i.e. a back/
forward navigation) we attempt to render it synchronously even though
it's a transition, since it's likely the previous page's data is cached.
In #27505, I changed the implementation so that it only "upgrades" the
priority of the transition for a single attempt. If the attempt
suspends, say because the data is not cached after all, from then on it
should be treated as a normal transition.
But it turns out #27505 did not work as intended, because it relied on
marking the root with pending synchronous work (root.pendingLanes),
which was never cleared until the popstate update completed.
The test scenarios I wrote accidentally worked for a different reason
related to suspending the work loop, which I'm currently in the middle
of refactoring.
github-actionsBot pushed a commit that referenced this pull request Aug 23, 2024
This is a refactor of the fix in #27505.
When a transition update is scheduled by a popstate event, (i.e. a back/
forward navigation) we attempt to render it synchronously even though
it's a transition, since it's likely the previous page's data is cached.
In #27505, I changed the implementation so that it only "upgrades" the
priority of the transition for a single attempt. If the attempt
suspends, say because the data is not cached after all, from then on it
should be treated as a normal transition.
But it turns out #27505 did not work as intended, because it relied on
marking the root with pending synchronous work (root.pendingLanes),
which was never cleared until the popstate update completed.
The test scenarios I wrote accidentally worked for a different reason
related to suspending the work loop, which I'm currently in the middle
of refactoring.
DiffTrain build for commit ee7f675.
github-actionsBot pushed a commit that referenced this pull request Aug 23, 2024
This is a refactor of the fix in #27505.
When a transition update is scheduled by a popstate event, (i.e. a back/
forward navigation) we attempt to render it synchronously even though
it's a transition, since it's likely the previous page's data is cached.
In #27505, I changed the implementation so that it only "upgrades" the
priority of the transition for a single attempt. If the attempt
suspends, say because the data is not cached after all, from then on it
should be treated as a normal transition.
But it turns out #27505 did not work as intended, because it relied on
marking the root with pending synchronous work (root.pendingLanes),
which was never cleared until the popstate update completed.
The test scenarios I wrote accidentally worked for a different reason
related to suspending the work loop, which I'm currently in the middle
of refactoring.
DiffTrain build for [ee7f675](ee7f675)
Akshato07 pushed a commit to Akshato07/-Luffy that referenced this pull request Feb 20, 2025
### Based on react/react#27505
If a parent render spawns a deferred task with useDeferredValue, but the
parent render suspends, we should not wait for the parent render to
complete before attempting to render the final value.
The reason is that the initialValue argument to useDeferredValue is
meant to represent an immediate preview of the final UI. If we can't
render it "immediately", we might as well skip it and go straight to the
"real" value.
This is an improvement over how a userspace implementation of
useDeferredValue would work, because a userspace implementation would
have to wait for the parent task to commit (useEffect) before spawning
the deferred task, creating a waterfall.
DiffTrain build for commit react/react@b2a68a6.
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CLA SignedReact Core TeamOpened by a member of the React Core Team

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@acdlite@react-sizebot@sebmarkbage@facebook-github-bot
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Track entangled lanes separately from update lane - #27505

Merged
acdlite merged 2 commits into
react:mainfrom
acdlite:track-entangled-lanes-separately
Oct 15, 2023
Merged

Track entangled lanes separately from update lane#27505
acdlite merged 2 commits into
react:mainfrom
acdlite:track-entangled-lanes-separately

Conversation

@acdlite

Copy link
Copy Markdown
Collaborator

A small refactor to how the lane entanglement mechanism works. We can now distinguish between the lane that "spawned" a render task (i.e. a new update) versus the lanes that it's entangled with. Both the update lane and the entangled lanes will be included while rendering, but by keeping them separate, we don't lose the original priority.

In practical terms, this means we can now entangle a low priority update with a higher priority lane while rendering at the lower priority.

To do this, lanes that are entangled at the root are now tracked using the same variable that we use to track the "base lanes" when revealing a previously hidden tree — conceptually, they are the same thing. I also renamed this variable (from subtreeLanes to entangledRenderLanes) to better reflect how it's used.

My primary motivation is related to useDeferredValue, which I'll address in a later PR.

I updated one of the tests related to synchronous popstate transitions
to clarify what the desired behavior is. It's really about what happens
if a popstate transition suspends. It should not cause an error, and
the transition should be allowed to finish once the promise resolves.
Ideally, if the transition suspends, it should completely revert back
to the default behavior for transitions — i.e. it should no longer be
treated as synchronous. Currently we don't do that, and when the promise
resolve the transition will still be rendered synchronously, but we can
improve this later.
@facebook-github-botfacebook-github-bot added CLA Signed React Core Team Opened by a member of the React Core Team labels Oct 12, 2023
@react-sizebot

react-sizebot commented Oct 12, 2023

Copy link
Copy Markdown

Comparing: e61a60f...717595f

Critical size changes

Includes critical production bundles, as well as any change greater than 2%:

Name+/-BaseCurrent+/- gzipBase gzipCurrent gzip
oss-stable/react-dom/cjs/react-dom.production.min.js+0.09%174.53 kB174.68 kB+0.04%54.29 kB54.32 kB
oss-experimental/react-dom/cjs/react-dom.production.min.js+0.09%176.61 kB176.77 kB+0.09%54.94 kB54.99 kB
facebook-www/ReactDOM-prod.classic.js+0.08%565.12 kB565.55 kB+0.11%99.42 kB99.53 kB
facebook-www/ReactDOM-prod.modern.js+0.08%548.98 kB549.40 kB+0.11%96.50 kB96.60 kB

Significant size changes

Includes any change greater than 0.2%:

Expand to show
Name+/-BaseCurrent+/- gzipBase gzipCurrent gzip
oss-stable-semver/react-reconciler/cjs/react-reconciler.development.js+0.22%931.93 kB933.98 kB+0.22%200.11 kB200.55 kB
oss-stable/react-reconciler/cjs/react-reconciler.development.js+0.22%931.95 kB934.01 kB+0.22%200.14 kB200.58 kB
oss-experimental/react-reconciler/cjs/react-reconciler.development.js+0.22%942.04 kB944.09 kB+0.22%202.00 kB202.46 kB
oss-stable-semver/react-test-renderer/cjs/react-test-renderer.development.js+0.20%813.99 kB815.64 kB+0.25%178.18 kB178.62 kB
oss-stable/react-test-renderer/cjs/react-test-renderer.development.js+0.20%814.02 kB815.67 kB+0.25%178.21 kB178.66 kB
oss-experimental/react-test-renderer/cjs/react-test-renderer.development.js+0.20%815.38 kB817.03 kB+0.25%178.45 kB178.89 kB
facebook-react-native/react-test-renderer/cjs/ReactTestRenderer-dev.js+0.20%826.50 kB828.16 kB+0.23%179.67 kB180.09 kB

Generated by 🚫 dangerJS against 717595f

A small refactor to how the lane entanglement mechanism works. We can
now distinguish between the lane that "spawned" a render task (i.e. a
new update) versus the lanes that it's entangled with. Both the update
lane and the entangled lanes will be included while rendering, but
by keeping them separate, we don't lose the original priority.
In practical terms, this means we can now entangle a low priority update
with a higher priority lane while rendering at the lower priority.
To do this, lanes that are entangled at the root are now tracked using
the same variable that we use to track the "base lanes" when revealing
a previously hidden tree — conceptually, they are the same thing. I
also renamed this variable (from subtreeLanes to entangledRenderLanes)
to better reflect how it's used.
My primary motivation is related to useDeferredValue, which I'll address
in a later PR.
@acdlite
acdlite merged commit 309c8ad into react:mainOct 15, 2023
github-actionsBot pushed a commit that referenced this pull request Oct 15, 2023
A small refactor to how the lane entanglement mechanism works. We can
now distinguish between the lane that "spawned" a render task (i.e. a
new update) versus the lanes that it's entangled with. Both the update
lane and the entangled lanes will be included while rendering, but by
keeping them separate, we don't lose the original priority.
In practical terms, this means we can now entangle a low priority update
with a higher priority lane while rendering at the lower priority.
To do this, lanes that are entangled at the root are now tracked using
the same variable that we use to track the "base lanes" when revealing a
previously hidden tree — conceptually, they are the same thing. I also
renamed this variable (from subtreeLanes to entangledRenderLanes) to
better reflect how it's used.
My primary motivation is related to useDeferredValue, which I'll address
in a later PR.
DiffTrain build for [309c8ad](309c8ad)
acdlite added a commit that referenced this pull request Oct 17, 2023
### Based on #27505
If a parent render spawns a deferred task with useDeferredValue, but the
parent render suspends, we should not wait for the parent render to
complete before attempting to render the final value.
The reason is that the initialValue argument to useDeferredValue is
meant to represent an immediate preview of the final UI. If we can't
render it "immediately", we might as well skip it and go straight to the
"real" value.
This is an improvement over how a userspace implementation of
useDeferredValue would work, because a userspace implementation would
have to wait for the parent task to commit (useEffect) before spawning
the deferred task, creating a waterfall.
github-actionsBot pushed a commit that referenced this pull request Oct 17, 2023
### Based on #27505
If a parent render spawns a deferred task with useDeferredValue, but the
parent render suspends, we should not wait for the parent render to
complete before attempting to render the final value.
The reason is that the initialValue argument to useDeferredValue is
meant to represent an immediate preview of the final UI. If we can't
render it "immediately", we might as well skip it and go straight to the
"real" value.
This is an improvement over how a userspace implementation of
useDeferredValue would work, because a userspace implementation would
have to wait for the parent task to commit (useEffect) before spawning
the deferred task, creating a waterfall.
DiffTrain build for [b2a68a6](b2a68a6)
kodiakhqBot pushed a commit to vercel/next.js that referenced this pull request Oct 18, 2023
jerrydev0927 added a commit to jerrydev0927/react that referenced this pull request Jan 5, 2024
### Based on react/react#27505
If a parent render spawns a deferred task with useDeferredValue, but the
parent render suspends, we should not wait for the parent render to
complete before attempting to render the final value.
The reason is that the initialValue argument to useDeferredValue is
meant to represent an immediate preview of the final UI. If we can't
render it "immediately", we might as well skip it and go straight to the
"real" value.
This is an improvement over how a userspace implementation of
useDeferredValue would work, because a userspace implementation would
have to wait for the parent task to commit (useEffect) before spawning
the deferred task, creating a waterfall.
DiffTrain build for [b2a68a65c84b63ac86930d88ae5c84380cbbdeb6](react/react@b2a68a6)
EdisonVan pushed a commit to EdisonVan/react that referenced this pull request Apr 15, 2024
A small refactor to how the lane entanglement mechanism works. We can
now distinguish between the lane that "spawned" a render task (i.e. a
new update) versus the lanes that it's entangled with. Both the update
lane and the entangled lanes will be included while rendering, but by
keeping them separate, we don't lose the original priority.
In practical terms, this means we can now entangle a low priority update
with a higher priority lane while rendering at the lower priority.
To do this, lanes that are entangled at the root are now tracked using
the same variable that we use to track the "base lanes" when revealing a
previously hidden tree — conceptually, they are the same thing. I also
renamed this variable (from subtreeLanes to entangledRenderLanes) to
better reflect how it's used.
My primary motivation is related to useDeferredValue, which I'll address
in a later PR.
EdisonVan pushed a commit to EdisonVan/react that referenced this pull request Apr 15, 2024
### Based on react#27505
If a parent render spawns a deferred task with useDeferredValue, but the
parent render suspends, we should not wait for the parent render to
complete before attempting to render the final value.
The reason is that the initialValue argument to useDeferredValue is
meant to represent an immediate preview of the final UI. If we can't
render it "immediately", we might as well skip it and go straight to the
"real" value.
This is an improvement over how a userspace implementation of
useDeferredValue would work, because a userspace implementation would
have to wait for the parent task to commit (useEffect) before spawning
the deferred task, creating a waterfall.
bigfootjon pushed a commit that referenced this pull request Apr 18, 2024
A small refactor to how the lane entanglement mechanism works. We can
now distinguish between the lane that "spawned" a render task (i.e. a
new update) versus the lanes that it's entangled with. Both the update
lane and the entangled lanes will be included while rendering, but by
keeping them separate, we don't lose the original priority.
In practical terms, this means we can now entangle a low priority update
with a higher priority lane while rendering at the lower priority.
To do this, lanes that are entangled at the root are now tracked using
the same variable that we use to track the "base lanes" when revealing a
previously hidden tree — conceptually, they are the same thing. I also
renamed this variable (from subtreeLanes to entangledRenderLanes) to
better reflect how it's used.
My primary motivation is related to useDeferredValue, which I'll address
in a later PR.
DiffTrain build for commit 309c8ad.
acdlite added a commit that referenced this pull request Aug 23, 2024
This is a refactor of the fix in #27505.
When a transition update is scheduled by a popstate event, (i.e. a back/
forward navigation) we attempt to render it synchronously even though
it's a transition, since it's likely the previous page's data is cached.
In #27505, I changed the implementation so that it only "upgrades" the
priority of the transition for a single attempt. If the attempt
suspends, say because the data is not cached after all, from then on it
should be treated as a normal transition.
But it turns out #27505 did not work as intended, because it relied on
marking the root with pending synchronous work (root.pendingLanes),
which was never cleared until the popstate update completed.
The test scenarios I wrote accidentally worked for a different reason
related to suspending the work loop, which I'm currently in the middle
of refactoring.
github-actionsBot pushed a commit that referenced this pull request Aug 23, 2024
This is a refactor of the fix in #27505.
When a transition update is scheduled by a popstate event, (i.e. a back/
forward navigation) we attempt to render it synchronously even though
it's a transition, since it's likely the previous page's data is cached.
In #27505, I changed the implementation so that it only "upgrades" the
priority of the transition for a single attempt. If the attempt
suspends, say because the data is not cached after all, from then on it
should be treated as a normal transition.
But it turns out #27505 did not work as intended, because it relied on
marking the root with pending synchronous work (root.pendingLanes),
which was never cleared until the popstate update completed.
The test scenarios I wrote accidentally worked for a different reason
related to suspending the work loop, which I'm currently in the middle
of refactoring.
DiffTrain build for commit ee7f675.
github-actionsBot pushed a commit that referenced this pull request Aug 23, 2024
This is a refactor of the fix in #27505.
When a transition update is scheduled by a popstate event, (i.e. a back/
forward navigation) we attempt to render it synchronously even though
it's a transition, since it's likely the previous page's data is cached.
In #27505, I changed the implementation so that it only "upgrades" the
priority of the transition for a single attempt. If the attempt
suspends, say because the data is not cached after all, from then on it
should be treated as a normal transition.
But it turns out #27505 did not work as intended, because it relied on
marking the root with pending synchronous work (root.pendingLanes),
which was never cleared until the popstate update completed.
The test scenarios I wrote accidentally worked for a different reason
related to suspending the work loop, which I'm currently in the middle
of refactoring.
DiffTrain build for [ee7f675](ee7f675)
Akshato07 pushed a commit to Akshato07/-Luffy that referenced this pull request Feb 20, 2025
### Based on react/react#27505
If a parent render spawns a deferred task with useDeferredValue, but the
parent render suspends, we should not wait for the parent render to
complete before attempting to render the final value.
The reason is that the initialValue argument to useDeferredValue is
meant to represent an immediate preview of the final UI. If we can't
render it "immediately", we might as well skip it and go straight to the
"real" value.
This is an improvement over how a userspace implementation of
useDeferredValue would work, because a userspace implementation would
have to wait for the parent task to commit (useEffect) before spawning
the deferred task, creating a waterfall.
DiffTrain build for commit react/react@b2a68a6.
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CLA SignedReact Core TeamOpened by a member of the React Core Team

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@acdlite@react-sizebot@sebmarkbage@facebook-github-bot
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

Track entangled lanes separately from update lane - #27505

Merged
acdlite merged 2 commits into
react:mainfrom
acdlite:track-entangled-lanes-separately
Oct 15, 2023
Merged

Track entangled lanes separately from update lane#27505
acdlite merged 2 commits into
react:mainfrom
acdlite:track-entangled-lanes-separately

Conversation

@acdlite

Copy link
Copy Markdown
Collaborator

A small refactor to how the lane entanglement mechanism works. We can now distinguish between the lane that "spawned" a render task (i.e. a new update) versus the lanes that it's entangled with. Both the update lane and the entangled lanes will be included while rendering, but by keeping them separate, we don't lose the original priority.

In practical terms, this means we can now entangle a low priority update with a higher priority lane while rendering at the lower priority.

To do this, lanes that are entangled at the root are now tracked using the same variable that we use to track the "base lanes" when revealing a previously hidden tree — conceptually, they are the same thing. I also renamed this variable (from subtreeLanes to entangledRenderLanes) to better reflect how it's used.

My primary motivation is related to useDeferredValue, which I'll address in a later PR.

I updated one of the tests related to synchronous popstate transitions
to clarify what the desired behavior is. It's really about what happens
if a popstate transition suspends. It should not cause an error, and
the transition should be allowed to finish once the promise resolves.
Ideally, if the transition suspends, it should completely revert back
to the default behavior for transitions — i.e. it should no longer be
treated as synchronous. Currently we don't do that, and when the promise
resolve the transition will still be rendered synchronously, but we can
improve this later.
@facebook-github-botfacebook-github-bot added CLA Signed React Core Team Opened by a member of the React Core Team labels Oct 12, 2023
@react-sizebot

react-sizebot commented Oct 12, 2023

Copy link
Copy Markdown

Comparing: e61a60f...717595f

Critical size changes

Includes critical production bundles, as well as any change greater than 2%:

Name+/-BaseCurrent+/- gzipBase gzipCurrent gzip
oss-stable/react-dom/cjs/react-dom.production.min.js+0.09%174.53 kB174.68 kB+0.04%54.29 kB54.32 kB
oss-experimental/react-dom/cjs/react-dom.production.min.js+0.09%176.61 kB176.77 kB+0.09%54.94 kB54.99 kB
facebook-www/ReactDOM-prod.classic.js+0.08%565.12 kB565.55 kB+0.11%99.42 kB99.53 kB
facebook-www/ReactDOM-prod.modern.js+0.08%548.98 kB549.40 kB+0.11%96.50 kB96.60 kB

Significant size changes

Includes any change greater than 0.2%:

Expand to show
Name+/-BaseCurrent+/- gzipBase gzipCurrent gzip
oss-stable-semver/react-reconciler/cjs/react-reconciler.development.js+0.22%931.93 kB933.98 kB+0.22%200.11 kB200.55 kB
oss-stable/react-reconciler/cjs/react-reconciler.development.js+0.22%931.95 kB934.01 kB+0.22%200.14 kB200.58 kB
oss-experimental/react-reconciler/cjs/react-reconciler.development.js+0.22%942.04 kB944.09 kB+0.22%202.00 kB202.46 kB
oss-stable-semver/react-test-renderer/cjs/react-test-renderer.development.js+0.20%813.99 kB815.64 kB+0.25%178.18 kB178.62 kB
oss-stable/react-test-renderer/cjs/react-test-renderer.development.js+0.20%814.02 kB815.67 kB+0.25%178.21 kB178.66 kB
oss-experimental/react-test-renderer/cjs/react-test-renderer.development.js+0.20%815.38 kB817.03 kB+0.25%178.45 kB178.89 kB
facebook-react-native/react-test-renderer/cjs/ReactTestRenderer-dev.js+0.20%826.50 kB828.16 kB+0.23%179.67 kB180.09 kB

Generated by 🚫 dangerJS against 717595f

A small refactor to how the lane entanglement mechanism works. We can
now distinguish between the lane that "spawned" a render task (i.e. a
new update) versus the lanes that it's entangled with. Both the update
lane and the entangled lanes will be included while rendering, but
by keeping them separate, we don't lose the original priority.
In practical terms, this means we can now entangle a low priority update
with a higher priority lane while rendering at the lower priority.
To do this, lanes that are entangled at the root are now tracked using
the same variable that we use to track the "base lanes" when revealing
a previously hidden tree — conceptually, they are the same thing. I
also renamed this variable (from subtreeLanes to entangledRenderLanes)
to better reflect how it's used.
My primary motivation is related to useDeferredValue, which I'll address
in a later PR.
@acdlite
acdlite merged commit 309c8ad into react:mainOct 15, 2023
github-actionsBot pushed a commit that referenced this pull request Oct 15, 2023
A small refactor to how the lane entanglement mechanism works. We can
now distinguish between the lane that "spawned" a render task (i.e. a
new update) versus the lanes that it's entangled with. Both the update
lane and the entangled lanes will be included while rendering, but by
keeping them separate, we don't lose the original priority.
In practical terms, this means we can now entangle a low priority update
with a higher priority lane while rendering at the lower priority.
To do this, lanes that are entangled at the root are now tracked using
the same variable that we use to track the "base lanes" when revealing a
previously hidden tree — conceptually, they are the same thing. I also
renamed this variable (from subtreeLanes to entangledRenderLanes) to
better reflect how it's used.
My primary motivation is related to useDeferredValue, which I'll address
in a later PR.
DiffTrain build for [309c8ad](309c8ad)
acdlite added a commit that referenced this pull request Oct 17, 2023
### Based on #27505
If a parent render spawns a deferred task with useDeferredValue, but the
parent render suspends, we should not wait for the parent render to
complete before attempting to render the final value.
The reason is that the initialValue argument to useDeferredValue is
meant to represent an immediate preview of the final UI. If we can't
render it "immediately", we might as well skip it and go straight to the
"real" value.
This is an improvement over how a userspace implementation of
useDeferredValue would work, because a userspace implementation would
have to wait for the parent task to commit (useEffect) before spawning
the deferred task, creating a waterfall.
github-actionsBot pushed a commit that referenced this pull request Oct 17, 2023
### Based on #27505
If a parent render spawns a deferred task with useDeferredValue, but the
parent render suspends, we should not wait for the parent render to
complete before attempting to render the final value.
The reason is that the initialValue argument to useDeferredValue is
meant to represent an immediate preview of the final UI. If we can't
render it "immediately", we might as well skip it and go straight to the
"real" value.
This is an improvement over how a userspace implementation of
useDeferredValue would work, because a userspace implementation would
have to wait for the parent task to commit (useEffect) before spawning
the deferred task, creating a waterfall.
DiffTrain build for [b2a68a6](b2a68a6)
kodiakhqBot pushed a commit to vercel/next.js that referenced this pull request Oct 18, 2023
jerrydev0927 added a commit to jerrydev0927/react that referenced this pull request Jan 5, 2024
### Based on react/react#27505
If a parent render spawns a deferred task with useDeferredValue, but the
parent render suspends, we should not wait for the parent render to
complete before attempting to render the final value.
The reason is that the initialValue argument to useDeferredValue is
meant to represent an immediate preview of the final UI. If we can't
render it "immediately", we might as well skip it and go straight to the
"real" value.
This is an improvement over how a userspace implementation of
useDeferredValue would work, because a userspace implementation would
have to wait for the parent task to commit (useEffect) before spawning
the deferred task, creating a waterfall.
DiffTrain build for [b2a68a65c84b63ac86930d88ae5c84380cbbdeb6](react/react@b2a68a6)
EdisonVan pushed a commit to EdisonVan/react that referenced this pull request Apr 15, 2024
A small refactor to how the lane entanglement mechanism works. We can
now distinguish between the lane that "spawned" a render task (i.e. a
new update) versus the lanes that it's entangled with. Both the update
lane and the entangled lanes will be included while rendering, but by
keeping them separate, we don't lose the original priority.
In practical terms, this means we can now entangle a low priority update
with a higher priority lane while rendering at the lower priority.
To do this, lanes that are entangled at the root are now tracked using
the same variable that we use to track the "base lanes" when revealing a
previously hidden tree — conceptually, they are the same thing. I also
renamed this variable (from subtreeLanes to entangledRenderLanes) to
better reflect how it's used.
My primary motivation is related to useDeferredValue, which I'll address
in a later PR.
EdisonVan pushed a commit to EdisonVan/react that referenced this pull request Apr 15, 2024
### Based on react#27505
If a parent render spawns a deferred task with useDeferredValue, but the
parent render suspends, we should not wait for the parent render to
complete before attempting to render the final value.
The reason is that the initialValue argument to useDeferredValue is
meant to represent an immediate preview of the final UI. If we can't
render it "immediately", we might as well skip it and go straight to the
"real" value.
This is an improvement over how a userspace implementation of
useDeferredValue would work, because a userspace implementation would
have to wait for the parent task to commit (useEffect) before spawning
the deferred task, creating a waterfall.
bigfootjon pushed a commit that referenced this pull request Apr 18, 2024
A small refactor to how the lane entanglement mechanism works. We can
now distinguish between the lane that "spawned" a render task (i.e. a
new update) versus the lanes that it's entangled with. Both the update
lane and the entangled lanes will be included while rendering, but by
keeping them separate, we don't lose the original priority.
In practical terms, this means we can now entangle a low priority update
with a higher priority lane while rendering at the lower priority.
To do this, lanes that are entangled at the root are now tracked using
the same variable that we use to track the "base lanes" when revealing a
previously hidden tree — conceptually, they are the same thing. I also
renamed this variable (from subtreeLanes to entangledRenderLanes) to
better reflect how it's used.
My primary motivation is related to useDeferredValue, which I'll address
in a later PR.
DiffTrain build for commit 309c8ad.
acdlite added a commit that referenced this pull request Aug 23, 2024
This is a refactor of the fix in #27505.
When a transition update is scheduled by a popstate event, (i.e. a back/
forward navigation) we attempt to render it synchronously even though
it's a transition, since it's likely the previous page's data is cached.
In #27505, I changed the implementation so that it only "upgrades" the
priority of the transition for a single attempt. If the attempt
suspends, say because the data is not cached after all, from then on it
should be treated as a normal transition.
But it turns out #27505 did not work as intended, because it relied on
marking the root with pending synchronous work (root.pendingLanes),
which was never cleared until the popstate update completed.
The test scenarios I wrote accidentally worked for a different reason
related to suspending the work loop, which I'm currently in the middle
of refactoring.
github-actionsBot pushed a commit that referenced this pull request Aug 23, 2024
This is a refactor of the fix in #27505.
When a transition update is scheduled by a popstate event, (i.e. a back/
forward navigation) we attempt to render it synchronously even though
it's a transition, since it's likely the previous page's data is cached.
In #27505, I changed the implementation so that it only "upgrades" the
priority of the transition for a single attempt. If the attempt
suspends, say because the data is not cached after all, from then on it
should be treated as a normal transition.
But it turns out #27505 did not work as intended, because it relied on
marking the root with pending synchronous work (root.pendingLanes),
which was never cleared until the popstate update completed.
The test scenarios I wrote accidentally worked for a different reason
related to suspending the work loop, which I'm currently in the middle
of refactoring.
DiffTrain build for commit ee7f675.
github-actionsBot pushed a commit that referenced this pull request Aug 23, 2024
This is a refactor of the fix in #27505.
When a transition update is scheduled by a popstate event, (i.e. a back/
forward navigation) we attempt to render it synchronously even though
it's a transition, since it's likely the previous page's data is cached.
In #27505, I changed the implementation so that it only "upgrades" the
priority of the transition for a single attempt. If the attempt
suspends, say because the data is not cached after all, from then on it
should be treated as a normal transition.
But it turns out #27505 did not work as intended, because it relied on
marking the root with pending synchronous work (root.pendingLanes),
which was never cleared until the popstate update completed.
The test scenarios I wrote accidentally worked for a different reason
related to suspending the work loop, which I'm currently in the middle
of refactoring.
DiffTrain build for [ee7f675](ee7f675)
Akshato07 pushed a commit to Akshato07/-Luffy that referenced this pull request Feb 20, 2025
### Based on react/react#27505
If a parent render spawns a deferred task with useDeferredValue, but the
parent render suspends, we should not wait for the parent render to
complete before attempting to render the final value.
The reason is that the initialValue argument to useDeferredValue is
meant to represent an immediate preview of the final UI. If we can't
render it "immediately", we might as well skip it and go straight to the
"real" value.
This is an improvement over how a userspace implementation of
useDeferredValue would work, because a userspace implementation would
have to wait for the parent task to commit (useEffect) before spawning
the deferred task, creating a waterfall.
DiffTrain build for commit react/react@b2a68a6.
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CLA SignedReact Core TeamOpened by a member of the React Core Team

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

@acdlite@react-sizebot@sebmarkbage@facebook-github-bot