Skip to content

[Fizz] Finish abort in a scheduled task#36580

Open
gnoff wants to merge 1 commit into
facebook:mainfrom
gnoff:jstory/delayed-abort
Open

[Fizz] Finish abort in a scheduled task#36580
gnoff wants to merge 1 commit into
facebook:mainfrom
gnoff:jstory/delayed-abort

Conversation

@gnoff
Copy link
Copy Markdown
Collaborator

@gnoff gnoff commented May 30, 2026

Stacked on #36584

abort() currently performs both the synchronous transition into an aborted request and the reporting/completion of every unfinished task in the same call. This change splits those phases. Aborting now synchronously marks the request as aborted, captures the abort reason, claims pending tasks so already scheduled work cannot continue rendering them, and captures any DEV async debug information needed at the point of abort. Reporting and completing the claimed tasks is then performed from a scheduled finishAbort() callback.

This split does not yet allow a promise rejected by an abort listener to replace the abort reason: work remains blocked once the request has been aborted, and tests assert that abort-time rejections still report the original abort reason. It establishes the task boundary needed for a follow-up change to selectively process rejected suspended work before completing the remaining aborted tasks.

This is observable for streaming renders because abort cleanup may now happen after already available output is read. A Suspense boundary that was previously converted to client rendering before it could be serialized may instead be emitted as pending first and receive its client-render instruction when the scheduled abort completion runs.

The scheduled finish must also preserve abort-during-render behavior in renderers whose scheduler executes synchronously. The request tracks its currently executing task, and both abort phases leave that task alone so it can unwind through its normal abort path rather than being completed twice or reporting an internal control-flow value.

@meta-cla meta-cla Bot added the CLA Signed label May 30, 2026
@github-actions github-actions Bot added the React Core Team Opened by a member of the React Core Team label May 30, 2026
@react-sizebot
Copy link
Copy Markdown

react-sizebot commented May 30, 2026

Comparing: de8e005...686e01f

Critical size changes

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

Name +/- Base Current +/- gzip Base gzip Current gzip
oss-stable/react-dom/cjs/react-dom.production.js = 6.84 kB 6.84 kB = 1.88 kB 1.88 kB
oss-stable/react-dom/cjs/react-dom-client.production.js = 614.26 kB 614.26 kB = 108.57 kB 108.57 kB
oss-experimental/react-dom/cjs/react-dom.production.js = 6.84 kB 6.84 kB = 1.88 kB 1.88 kB
oss-experimental/react-dom/cjs/react-dom-client.production.js = 680.19 kB 680.19 kB = 119.51 kB 119.51 kB
facebook-www/ReactDOM-prod.classic.js = 700.61 kB 700.61 kB = 123.09 kB 123.09 kB
facebook-www/ReactDOM-prod.modern.js = 690.93 kB 690.93 kB = 121.48 kB 121.48 kB

Significant size changes

Includes any change greater than 0.2%:

Expand to show
Name +/- Base Current +/- gzip Base gzip Current gzip
oss-stable-semver/react-server/cjs/react-server.development.js +0.76% 212.59 kB 214.21 kB +0.22% 37.52 kB 37.61 kB
oss-stable/react-server/cjs/react-server.development.js +0.76% 212.59 kB 214.21 kB +0.22% 37.52 kB 37.61 kB
oss-experimental/react-server/cjs/react-server.development.js +0.74% 217.38 kB 219.00 kB +0.22% 38.44 kB 38.53 kB
oss-stable-semver/react-server/cjs/react-server.production.js +0.53% 147.65 kB 148.43 kB +0.31% 25.98 kB 26.06 kB
oss-stable/react-server/cjs/react-server.production.js +0.53% 147.65 kB 148.43 kB +0.31% 25.98 kB 26.06 kB
oss-experimental/react-server/cjs/react-server.production.js +0.52% 151.19 kB 151.97 kB +0.28% 26.77 kB 26.84 kB
oss-experimental/react-markup/cjs/react-markup.development.js +0.38% 398.32 kB 399.84 kB +0.18% 72.25 kB 72.38 kB
oss-stable-semver/react-dom/cjs/react-dom-server-legacy.node.development.js +0.36% 411.33 kB 412.83 kB +0.18% 74.38 kB 74.51 kB
oss-stable-semver/react-dom/cjs/react-dom-server-legacy.browser.development.js +0.36% 411.33 kB 412.83 kB +0.18% 74.38 kB 74.51 kB
oss-stable/react-dom/cjs/react-dom-server-legacy.node.development.js +0.36% 411.36 kB 412.85 kB +0.18% 74.40 kB 74.54 kB
oss-stable/react-dom/cjs/react-dom-server-legacy.browser.development.js +0.36% 411.36 kB 412.86 kB +0.18% 74.40 kB 74.54 kB
oss-stable-semver/react-dom/cjs/react-dom-server.browser.development.js +0.36% 440.85 kB 442.45 kB +0.19% 78.55 kB 78.70 kB
oss-stable/react-dom/cjs/react-dom-server.browser.development.js +0.36% 440.93 kB 442.52 kB +0.19% 78.60 kB 78.75 kB
oss-stable-semver/react-dom/cjs/react-dom-server.edge.development.js +0.36% 441.63 kB 443.23 kB +0.19% 78.73 kB 78.88 kB
oss-stable/react-dom/cjs/react-dom-server.edge.development.js +0.36% 441.71 kB 443.31 kB +0.19% 78.78 kB 78.93 kB
facebook-www/ReactDOMServerStreaming-dev.modern.js +0.36% 426.20 kB 427.72 kB +0.15% 76.50 kB 76.61 kB
oss-stable-semver/react-dom/cjs/react-dom-server.node.development.js +0.36% 447.89 kB 449.49 kB +0.20% 78.53 kB 78.69 kB
oss-stable/react-dom/cjs/react-dom-server.node.development.js +0.36% 447.97 kB 449.56 kB +0.20% 78.58 kB 78.74 kB
facebook-www/ReactDOMServer-dev.modern.js +0.36% 421.87 kB 423.37 kB +0.19% 75.69 kB 75.83 kB
facebook-www/ReactDOMServer-dev.classic.js +0.35% 425.31 kB 426.81 kB +0.19% 76.30 kB 76.45 kB
oss-experimental/react-dom/cjs/react-dom-server-legacy.node.development.js +0.35% 426.65 kB 428.15 kB +0.19% 76.62 kB 76.76 kB
oss-experimental/react-dom/cjs/react-dom-server-legacy.browser.development.js +0.35% 426.65 kB 428.15 kB +0.19% 76.61 kB 76.76 kB
oss-experimental/react-dom/cjs/react-dom-server.browser.development.js +0.35% 457.21 kB 458.81 kB +0.20% 80.88 kB 81.04 kB
oss-experimental/react-dom/cjs/react-dom-server.edge.development.js +0.35% 458.22 kB 459.82 kB +0.19% 81.11 kB 81.27 kB
oss-experimental/react-dom/cjs/react-dom-server.node.development.js +0.34% 463.98 kB 465.57 kB +0.20% 80.89 kB 81.04 kB
oss-stable-semver/react-dom/cjs/react-dom-server.bun.development.js +0.31% 390.45 kB 391.65 kB +0.16% 74.02 kB 74.13 kB
oss-stable/react-dom/cjs/react-dom-server.bun.development.js +0.31% 390.53 kB 391.73 kB +0.16% 74.04 kB 74.16 kB
oss-experimental/react-dom/cjs/react-dom-server.bun.development.js +0.30% 404.78 kB 405.97 kB +0.11% 76.35 kB 76.44 kB
oss-stable-semver/react-dom/cjs/react-dom-server.browser.production.js +0.26% 279.13 kB 279.86 kB +0.22% 49.67 kB 49.78 kB
oss-stable/react-dom/cjs/react-dom-server.browser.production.js +0.26% 279.20 kB 279.93 kB +0.22% 49.70 kB 49.80 kB
oss-stable-semver/react-dom/cjs/react-dom-server-legacy.browser.production.js +0.26% 251.50 kB 252.15 kB +0.24% 45.30 kB 45.41 kB
oss-stable/react-dom/cjs/react-dom-server-legacy.browser.production.js +0.26% 251.52 kB 252.18 kB +0.24% 45.33 kB 45.44 kB
oss-experimental/react-markup/cjs/react-markup.production.js +0.25% 248.64 kB 249.27 kB +0.22% 46.09 kB 46.19 kB
facebook-www/ReactDOMServer-prod.modern.js +0.25% 258.07 kB 258.73 kB +0.24% 46.09 kB 46.20 kB
oss-stable-semver/react-dom/cjs/react-dom-server.bun.production.js +0.25% 280.17 kB 280.88 kB +0.18% 49.44 kB 49.53 kB
oss-stable/react-dom/cjs/react-dom-server.bun.production.js +0.25% 280.24 kB 280.95 kB +0.18% 49.46 kB 49.55 kB
facebook-www/ReactDOMServer-prod.classic.js +0.25% 260.41 kB 261.06 kB +0.25% 46.44 kB 46.55 kB
oss-experimental/react-dom/cjs/react-dom-server-legacy.browser.production.js +0.25% 261.34 kB 261.99 kB +0.25% 46.73 kB 46.85 kB
oss-experimental/react-dom/cjs/react-dom-server.browser.production.js +0.25% 290.60 kB 291.33 kB +0.22% 51.30 kB 51.41 kB
oss-stable-semver/react-dom/cjs/react-dom-server.edge.production.js +0.25% 285.03 kB 285.74 kB +0.19% 51.87 kB 51.97 kB
oss-stable/react-dom/cjs/react-dom-server.edge.production.js +0.25% 285.11 kB 285.82 kB +0.19% 51.90 kB 51.99 kB
oss-stable-semver/react-dom/cjs/react-dom-server-legacy.node.production.js +0.25% 256.70 kB 257.33 kB +0.22% 47.29 kB 47.39 kB
oss-stable/react-dom/cjs/react-dom-server-legacy.node.production.js +0.25% 256.73 kB 257.36 kB +0.22% 47.31 kB 47.42 kB
oss-experimental/react-dom/cjs/react-dom-server.bun.production.js +0.24% 291.48 kB 292.19 kB +0.19% 51.21 kB 51.31 kB
oss-stable-semver/react-dom/cjs/react-dom-server.node.production.js +0.24% 293.10 kB 293.81 kB +0.18% 51.72 kB 51.82 kB
oss-stable/react-dom/cjs/react-dom-server.node.production.js +0.24% 293.17 kB 293.88 kB +0.18% 51.75 kB 51.84 kB
oss-experimental/react-dom/cjs/react-dom-server.edge.production.js +0.24% 297.18 kB 297.89 kB +0.19% 53.78 kB 53.88 kB
oss-experimental/react-dom/cjs/react-dom-server-legacy.node.production.js +0.24% 267.12 kB 267.75 kB +0.21% 48.96 kB 49.06 kB
facebook-www/ReactDOMServerStreaming-prod.modern.js +0.24% 268.31 kB 268.95 kB +0.19% 49.08 kB 49.17 kB
oss-experimental/react-dom/cjs/react-dom-server.node.production.js +0.23% 304.90 kB 305.61 kB +0.19% 53.62 kB 53.72 kB
oss-experimental/react-markup/cjs/react-markup.react-server.development.js +0.22% 686.73 kB 688.26 kB +0.12% 121.83 kB 121.97 kB

Generated by 🚫 dangerJS against 686e01f

@gnoff gnoff force-pushed the jstory/delayed-abort branch from 36fb8bc to 1ffc433 Compare May 30, 2026 18:49
@gnoff gnoff requested review from eps1lon and unstubbable and removed request for unstubbable May 30, 2026 18:49
@gnoff gnoff force-pushed the jstory/delayed-abort branch 3 times, most recently from d4e3acb to c7e7131 Compare May 31, 2026 18:20
`abort()` currently performs both the synchronous transition into an aborted request and the reporting/completion of every unfinished task in the same call. This change splits those phases. Aborting now synchronously marks the request as aborted, captures the abort reason, claims pending tasks so already scheduled work cannot continue rendering them, and captures any DEV async debug information needed at the point of abort. Reporting and completing the claimed tasks is then performed from a scheduled `finishAbort()` callback.

This split does not yet allow a promise rejected by an abort listener to replace the abort reason: work remains blocked once the request has been aborted, and tests assert that abort-time rejections still report the original abort reason. It establishes the task boundary needed for a follow-up change to selectively process rejected suspended work before completing the remaining aborted tasks.

This is observable for streaming renders because abort cleanup may now happen after already available output is read. A Suspense boundary that was previously converted to client rendering before it could be serialized may instead be emitted as pending first and receive its client-render instruction when the scheduled abort completion runs.

The scheduled finish must also preserve abort-during-render behavior in renderers whose scheduler executes synchronously. The request tracks its currently executing task, and both abort phases leave that task alone so it can unwind through its normal abort path rather than being completed twice or reporting an internal control-flow value.
@gnoff gnoff force-pushed the jstory/delayed-abort branch from c7e7131 to 686e01f Compare May 31, 2026 21:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CLA Signed React Core Team Opened by a member of the React Core Team

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants