Conversation
Install a DevTools hook before react-dom/client so suites can record scheduler priority, and share two-phase renderToPipeableStream replay helpers for hydrateRoot tests. Co-authored-by: Nathaniel Tucker <me@ntucker.me>
Calibrate Immediate vs Normal commits, document discrete-event SyncLane, and show that recreating Suspense elements client-renders a pending boundary so streamed nodes are not adopted. Co-authored-by: Nathaniel Tucker <me@ntucker.me>
Keep the committed UI, accept urgent input, and require non-Immediate store publishes for transition/default setResponse without flushSync or useSyncExternalStore. Co-authored-by: Nathaniel Tucker <me@ntucker.me>
Lock gate-before-consumer identity and in-place reveal, and record per-version outcomes for read-then-suspend and two-pending public DataProvider topologies. Co-authored-by: Nathaniel Tucker <me@ntucker.me>
Hoist a throwing useSyncExternalStore wrapper so public hooks cannot capture the real API, and label the React 19 use() vs React 18 useContext fallback. Co-authored-by: Nathaniel Tucker <me@ntucker.me>
Delete root React resolutions, install 19.3.0, and run the concurrent rendering suites so latest React is locked in CI rather than the 19.2.3 pin. Co-authored-by: Nathaniel Tucker <me@ntucker.me>
|
|
The latest updates on your projects. Learn more about Vercel for GitHub. |
|
Size Change: 0 B Total Size: 81 kB ℹ️ View Unchanged
|
There was a problem hiding this comment.
Benchmark React
Details
| Benchmark suite | Current: 2c592e7 | Previous: 3fa47c8 | Ratio |
|---|---|---|---|
data-client: getlist-100 |
126.58 ops/s (± 4.5%) |
137.94 ops/s (± 4.5%) |
1.09 |
data-client: getlist-500 |
41.07 ops/s (± 6.0%) |
44.05 ops/s (± 3.8%) |
1.07 |
data-client: update-entity |
322.58 ops/s (± 7.6%) |
384.62 ops/s (± 9.3%) |
1.19 |
data-client: update-user |
312.5 ops/s (± 6.9%) |
333.33 ops/s (± 8.6%) |
1.07 |
data-client: getlist-500-sorted |
43.01 ops/s (± 10.3%) |
43.11 ops/s (± 9.4%) |
1.00 |
data-client: update-entity-sorted |
285.71 ops/s (± 8.8%) |
312.5 ops/s (± 7.9%) |
1.09 |
data-client: update-entity-multi-view |
285.71 ops/s (± 6.7%) |
327.96 ops/s (± 7.5%) |
1.15 |
data-client: list-detail-switch-10 |
7.16 ops/s (± 6.4%) |
9.9 ops/s (± 9.4%) |
1.38 |
data-client: update-user-10000 |
72.46 ops/s (± 5.6%) |
72.2 ops/s (± 14.8%) |
1.00 |
data-client: invalidate-and-resolve |
34.01 ops/s (± 5.4%) |
37.67 ops/s (± 5.6%) |
1.11 |
data-client: unshift-item |
204.08 ops/s (± 5.5%) |
219.81 ops/s (± 6.0%) |
1.08 |
data-client: delete-item |
270.27 ops/s (± 4.7%) |
285.71 ops/s (± 3.8%) |
1.06 |
data-client: move-item |
161.29 ops/s (± 8.4%) |
177.01 ops/s (± 7.9%) |
1.10 |
This comment was automatically generated by workflow using github-action-benchmark.
Load renderToPipeableStream from the Node server build, hoist React 18 $RC function declarations onto the global, and lock 18.3/19.2/19.3 shape 2–3 rows. React 18 default-lane publishes still client-render a pending sibling; transition publishes keep it dehydrated without host text. Co-authored-by: Nathaniel Tucker <me@ntucker.me>
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## master #4094 +/- ##
=======================================
Coverage 97.84% 97.84%
=======================================
Files 156 156
Lines 3057 3057
Branches 612 612
=======================================
Hits 2991 2991
Misses 18 18
Partials 48 48 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
Share replayRest, getHydrateRoot, and probe calibration helpers so the suites stop copying stream install and notify-store boilerplate. Keep reactCommitProbe as the first import so the DevTools hook still installs before react-dom/client. Co-authored-by: Nathaniel Tucker <me@ntucker.me>
|
FOLLOW_UP (Staff Architect) — does not block merge after Ready / Solid GOALS lock: public After land, please consider:
No CHANGE_THIS_PR. Draft is fine to review; merge gate remains Ready after |
The recreate-Suspense probe client-renders the pending sibling on 18, which logs the pre-hydration update warning. Expect that warning in this case only; leave other suites' empty-console afterEach asserts unchanged. Co-authored-by: Nathaniel Tucker <me@ntucker.me>
|
FOLLOW_UP (no change required on this PR) Direction looks right for a public-API concurrent-rendering goal lock: shape 1 as the green regression guard, shapes 2/3 as per-minor recorded controls (not #4090 adapter contracts), shared probe + streaming harness after simplify, and a focused When you next touch this area (not blocking Ready/merge):
|
Fixes # .
Motivation
Lock the GOALS bullet Fully concurrent rendering on the latest React with tests against public
@data-client/react(DataProvider,useSuspense,useCache,useLive,useController) plus React itself. Nopackages/*source changes and no changeset.This is a new PR off
master. It does not push to #4090, does not copy #4092 waiter / RSC-first contracts, and does not assert a universal “all live Context publishes preserve pending siblings.”Existing probes establish two conditional cases, not one universal rule:
DataStorewhile a sibling whose data consumer has not rendered past an outer gate is<!--$?-->) remains dehydrated on 19.2.3 / 19.3.0 and later hydrates in place.startTransitiondid not rescue that composition.Shape 1 is a green regression guard for the narrower gate-before-consumer statement on 19.x. Shapes 2 and 3 are causal controls whose outcomes are recorded per React version.
Solution
__tests__/reactCommitProbe.ts+__tests__/streamingHarness.tsx: DevTools commit-priority probe (self-calibrated) and two-phaserenderToPipeableStream/hydrateRootreplay. The Node server build is required so jsdom’s browser export on React 18 still exposesrenderToPipeableStream;executeScriptshoists 18’s$RCfunction declarations onto the global.concurrent-probe-controls.web.tsx: uSES is Immediate even insidestartTransition; plainsetStateis Normal; discretesetResponseis Immediate; recreating Suspense client-renders a pending boundary. On React 18 that control logs “This Suspense boundary received an update before it finished hydrating… wrap the original update in startTransition.” The recreate test expects that warning and drains it so the suiteafterEachempty-console assert stays strict. Hydration and transition suites do not filter it.recordConsoleErrorsis unchanged.concurrent-transition.web.tsx:startTransitionoveruseSuspensekeeps the committed UI, accepts urgent input, then commits B; isolated store publishes are non-Immediate; zeroflushSync/useSyncExternalStore.concurrent-hydration.web.tsx: shape 1 green lock on 19.x; shapes 2–3 recorded per version.useCacheState.web.tsx: hoisted throwinguseSyncExternalStore; React 19use(StateContext); React 18useContextlabeled fallback.unit_tests-19.3: delete root React resolutions,yarn up react@19.3.0, run the focused ReactDOM suites. Thelatestrow stays on the 19.2.3 pin.Simplify (same PR, no assertion or CI-row changes): shared
replayRest/getHydrateRoot/ probe calibration helpers; hydrationstreamPage+publishAOnTransition; collapsed identical shape 2/3 table rows.Per-version results
Focused suites:
packages/react/src/__tests__/concurrent-.*\\.web\\.tsx+useCacheState.web.tsx. 24 passed, 1 skipped on every version below. Noit.failing.unit_tests-^17describe.skip(noreact-dom/client/useTransition).useCacheState16/17 isolate still runs.unit_tests-^18(local yarn-up)2c592e7d30): probe-controls 4 passed (3.621 s); all concurrent suites 20 passed;useCacheState4 passed, 1 skipped. Shape 1 transition publish: Normal commit, B stays pending, host title staystodo A. Shape 1 default-lane: title becomes v2, B is client-rendered.latestunit_tests-19.3(local yarn-up)The adapter-level
flushSyncassertion needs #4090 code and is out of scope.Shape 2 / shape 3 recorded table (public
DataProvider)[][][][][][]Composition difference vs #4090: on public master, the two-pending live-publish topology (shape 3) does not client-render B on 18.3.1, 19.2.3, or 19.3.0 (
fetchIds: [], streamed node adopted). PR 4090’s adapter-shaped liveHYDRATEdid client-render the sibling (clientFetches: ["B"]). That difference is reported, not rewritten.Open questions
None for this PR. Doc patch intents for layering/integrity/19.3 spike docs belong to other subagents.