Skip to content

[Server Components] Walk parsed JSON instead of using reviver for parsing RSC payload - #35776

Merged
unstubbable merged 10 commits into
react:mainfrom
timneutkens:add/rsc-parsing-perf
Feb 19, 2026
Merged

[Server Components] Walk parsed JSON instead of using reviver for parsing RSC payload#35776
unstubbable merged 10 commits into
react:mainfrom
timneutkens:add/rsc-parsing-perf

Conversation

@timneutkens

@timneutkenstimneutkens commented Feb 13, 2026

Copy link
Copy Markdown
Contributor

Summary

Follow-up to vercel/next.js#89823 with the actual changes to React.

Replaces the JSON.parse reviver callback in initializeModelChunk with a two-step approach: plain JSON.parse() followed by a recursive reviveModel() post-process (same as in Flight Reply Server). This yields a ~75% speedup in RSC chunk deserialization.

PayloadOriginal (ms)Walk (ms)Speedup
Small (2 elements, 142B)0.00240.0007+72%
Medium (~12 elements, 914B)0.01160.0031+73%
Large (~90 elements, 16.7KB)0.18360.0451+75%
XL (~200 elements, 25.7KB)0.37420.0913+76%
Table (1000 rows, 110KB)3.08620.6887+78%

Problem

createFromJSONCallback returns a reviver function passed as the second argument to JSON.parse(). This reviver is called for every key-value pair in the parsed JSON. While the logic inside the reviver is lightweight, the dominant cost is the C++ → JavaScript boundary crossing — V8's JSON.parse is implemented in C++, and calling back into JavaScript for every node incurs significant overhead.

Even a trivial no-op reviver (k, v) => v makes JSON.parse~4x slower than bare JSON.parse without a reviver:

108 KB payload:
Bare JSON.parse: 0.60 ms
Trivial reviver: 2.95 ms (+391%)

Change

Replace the reviver with a two-step process:

  1. JSON.parse(resolvedModel) — parse the entire payload in C++ with no callbacks
  2. reviveModel — recursively walk the resulting object in pure JavaScript to apply RSC transformations

The reviveModel function includes additional optimizations over the original reviver:

  • Short-circuits plain strings: only calls parseModelString when the string starts with $, skipping the vast majority of strings (class names, text content, etc.)
  • Stays entirely in JavaScript — no C++ boundary crossings during the walk

Results

You can find the related applications in the Next.js PR as I've been testing this on Next.js applications.

Table as Server Component with 1000 items

Before:

 "min": 13.782875000000786,
"max": 22.23400000000038,
"avg": 17.116868530000083,
"p50": 17.10766700000022,
"p75": 18.50787499999933,
"p95": 20.426249999998618,
"p99": 21.814125000000786

After:

 "min": 10.963916999999128,
"max": 18.096083000000363,
"avg": 13.543286884999988,
"p50": 13.58350000000064,
"p75": 14.871791999999914,
"p95": 16.08429099999921,
"p99": 17.591458000000785

Table as Client Component with 1000 items

Before:

 "min": 3.888875000000553,
"max": 9.044959000000745,
"avg": 4.651271475000067,
"p50": 4.555749999999534,
"p75": 4.966624999999112,
"p95": 5.47754200000054,
"p99": 6.109499999998661

After:

 "min": 3.5986250000005384,
"max": 5.374291000000085,
"avg": 4.142990245000046,
"p50": 4.10570799999914,
"p75": 4.392041999999492,
"p95": 4.740084000000934,
"p99": 5.1652500000000146

Nested Suspense

Before:

 Requests: 200
Min: 73ms
Max: 106ms
Avg: 78ms
P50: 77ms
P75: 80ms
P95: 85ms
P99: 94ms

After:

 Requests: 200
Min: 56ms
Max: 67ms
Avg: 59ms
P50: 58ms
P75: 60ms
P95: 65ms
P99: 66ms

Even more nested Suspense (double-level Suspense)

Before:

 Requests: 200
Min: 159ms
Max: 208ms
Avg: 169ms
P50: 167ms
P75: 173ms
P95: 183ms
P99: 188ms

After:

 Requests: 200
Min: 125ms
Max: 170ms
Avg: 134ms
P50: 132ms
P75: 138ms
P95: 148ms
P99: 160ms

How did you test this change?

Ran it across many Next.js benchmark applications.

The entire Next.js test suite passes with this change.

Comment threadpackages/react-client/src/ReactFlightClient.js Outdated
@react-sizebot

react-sizebot commented Feb 13, 2026

Copy link
Copy Markdown

Comparing: e8c6362...0ff0870

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.js=6.84 kB6.84 kB+0.05%1.88 kB1.88 kB
oss-stable/react-dom/cjs/react-dom-client.production.js=611.02 kB611.02 kB=108.00 kB108.00 kB
oss-experimental/react-dom/cjs/react-dom.production.js=6.84 kB6.84 kB=1.88 kB1.88 kB
oss-experimental/react-dom/cjs/react-dom-client.production.js=676.95 kB676.95 kB=118.97 kB118.97 kB
facebook-www/ReactDOM-prod.classic.js=697.68 kB697.68 kB=122.67 kB122.67 kB
facebook-www/ReactDOM-prod.modern.js=687.99 kB687.99 kB=121.05 kB121.05 kB
oss-experimental/react-noop-renderer/cjs/react-noop-renderer-flight-client.development.js=3.10 kB2.99 kB=1.09 kB1.05 kB
oss-stable-semver/react-noop-renderer/cjs/react-noop-renderer-flight-client.development.js=3.10 kB2.99 kB=1.09 kB1.05 kB
oss-stable/react-noop-renderer/cjs/react-noop-renderer-flight-client.development.js=3.10 kB2.99 kB=1.09 kB1.05 kB
oss-experimental/react-noop-renderer/cjs/react-noop-renderer-flight-client.production.js=2.33 kB2.23 kB=0.87 kB0.84 kB
oss-stable-semver/react-noop-renderer/cjs/react-noop-renderer-flight-client.production.js=2.33 kB2.23 kB=0.87 kB0.84 kB
oss-stable/react-noop-renderer/cjs/react-noop-renderer-flight-client.production.js=2.33 kB2.23 kB=0.87 kB0.84 kB

Significant size changes

Includes any change greater than 0.2%:

Expand to show
Name+/-BaseCurrent+/- gzipBase gzipCurrent gzip
oss-experimental/react-server-dom-parcel/cjs/react-server-dom-parcel-client.browser.production.js+0.70%61.74 kB62.18 kB+0.79%11.96 kB12.05 kB
oss-stable-semver/react-server-dom-parcel/cjs/react-server-dom-parcel-client.browser.production.js+0.70%61.74 kB62.18 kB+0.79%11.96 kB12.05 kB
oss-stable/react-server-dom-parcel/cjs/react-server-dom-parcel-client.browser.production.js+0.70%61.74 kB62.18 kB+0.79%11.96 kB12.05 kB
oss-experimental/react-server-dom-esm/cjs/react-server-dom-esm-client.browser.production.js+0.70%61.92 kB62.35 kB+0.57%12.01 kB12.07 kB
oss-stable-semver/react-server-dom-esm/cjs/react-server-dom-esm-client.browser.production.js+0.70%61.92 kB62.35 kB+0.57%12.01 kB12.07 kB
oss-stable/react-server-dom-esm/cjs/react-server-dom-esm-client.browser.production.js+0.70%61.92 kB62.35 kB+0.57%12.01 kB12.07 kB
oss-experimental/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.browser.production.js+0.68%63.94 kB64.37 kB+0.56%12.42 kB12.49 kB
oss-stable-semver/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.browser.production.js+0.68%63.94 kB64.37 kB+0.56%12.42 kB12.49 kB
oss-stable/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.browser.production.js+0.68%63.94 kB64.37 kB+0.56%12.42 kB12.49 kB
oss-stable-semver/react-client/cjs/react-client-flight.production.js+0.68%70.13 kB70.61 kB+0.61%12.50 kB12.57 kB
oss-stable/react-client/cjs/react-client-flight.production.js+0.68%70.16 kB70.63 kB+0.61%12.52 kB12.60 kB
oss-experimental/react-client/cjs/react-client-flight.production.js+0.68%70.16 kB70.64 kB+0.61%12.52 kB12.60 kB
oss-experimental/react-server-dom-webpack/cjs/react-server-dom-webpack-client.browser.production.js+0.68%64.31 kB64.74 kB+0.58%12.50 kB12.58 kB
oss-stable-semver/react-server-dom-webpack/cjs/react-server-dom-webpack-client.browser.production.js+0.68%64.31 kB64.74 kB+0.58%12.50 kB12.58 kB
oss-stable/react-server-dom-webpack/cjs/react-server-dom-webpack-client.browser.production.js+0.68%64.31 kB64.74 kB+0.58%12.50 kB12.58 kB
oss-experimental/react-server-dom-parcel/cjs/react-server-dom-parcel-client.edge.production.js+0.65%67.26 kB67.70 kB+0.61%13.14 kB13.22 kB
oss-stable-semver/react-server-dom-parcel/cjs/react-server-dom-parcel-client.edge.production.js+0.65%67.26 kB67.70 kB+0.61%13.14 kB13.22 kB
oss-stable/react-server-dom-parcel/cjs/react-server-dom-parcel-client.edge.production.js+0.65%67.26 kB67.70 kB+0.61%13.14 kB13.22 kB
oss-experimental/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.edge.production.js+0.62%70.27 kB70.70 kB+0.60%13.73 kB13.81 kB
oss-stable-semver/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.edge.production.js+0.62%70.27 kB70.70 kB+0.60%13.73 kB13.81 kB
oss-stable/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.edge.production.js+0.62%70.27 kB70.70 kB+0.60%13.73 kB13.81 kB
oss-experimental/react-server-dom-webpack/cjs/react-server-dom-webpack-client.edge.production.js+0.62%70.29 kB70.73 kB+0.60%13.74 kB13.82 kB
oss-stable-semver/react-server-dom-webpack/cjs/react-server-dom-webpack-client.edge.production.js+0.62%70.29 kB70.73 kB+0.60%13.74 kB13.82 kB
oss-stable/react-server-dom-webpack/cjs/react-server-dom-webpack-client.edge.production.js+0.62%70.29 kB70.73 kB+0.60%13.74 kB13.82 kB
oss-experimental/react-server-dom-esm/cjs/react-server-dom-esm-client.node.production.js+0.62%70.35 kB70.79 kB+0.66%13.49 kB13.58 kB
oss-stable-semver/react-server-dom-esm/cjs/react-server-dom-esm-client.node.production.js+0.62%70.35 kB70.79 kB+0.66%13.49 kB13.58 kB
oss-stable/react-server-dom-esm/cjs/react-server-dom-esm-client.node.production.js+0.62%70.35 kB70.79 kB+0.66%13.49 kB13.58 kB
oss-experimental/react-server-dom-parcel/cjs/react-server-dom-parcel-client.node.production.js+0.61%71.70 kB72.14 kB+0.64%13.80 kB13.89 kB
oss-stable-semver/react-server-dom-parcel/cjs/react-server-dom-parcel-client.node.production.js+0.61%71.70 kB72.14 kB+0.64%13.80 kB13.89 kB
oss-stable/react-server-dom-parcel/cjs/react-server-dom-parcel-client.node.production.js+0.61%71.70 kB72.14 kB+0.64%13.80 kB13.89 kB
oss-experimental/react-server-dom-unbundled/cjs/react-server-dom-unbundled-client.node.production.js+0.59%73.76 kB74.20 kB+0.62%14.20 kB14.29 kB
oss-stable-semver/react-server-dom-unbundled/cjs/react-server-dom-unbundled-client.node.production.js+0.59%73.76 kB74.20 kB+0.62%14.20 kB14.29 kB
oss-stable/react-server-dom-unbundled/cjs/react-server-dom-unbundled-client.node.production.js+0.59%73.76 kB74.20 kB+0.62%14.20 kB14.29 kB
oss-experimental/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.node.production.js+0.58%74.91 kB75.35 kB+0.60%14.44 kB14.53 kB
oss-stable-semver/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.node.production.js+0.58%74.91 kB75.35 kB+0.60%14.44 kB14.53 kB
oss-stable/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.node.production.js+0.58%74.91 kB75.35 kB+0.60%14.44 kB14.53 kB
oss-experimental/react-server-dom-webpack/cjs/react-server-dom-webpack-client.node.production.js+0.58%74.93 kB75.37 kB+0.59%14.45 kB14.54 kB
oss-stable-semver/react-server-dom-webpack/cjs/react-server-dom-webpack-client.node.production.js+0.58%74.93 kB75.37 kB+0.59%14.45 kB14.54 kB
oss-stable/react-server-dom-webpack/cjs/react-server-dom-webpack-client.node.production.js+0.58%74.93 kB75.37 kB+0.59%14.45 kB14.54 kB
oss-experimental/react-server-dom-esm/esm/react-server-dom-esm-client.browser.production.js+0.55%101.57 kB102.13 kB+0.72%20.71 kB20.86 kB
oss-stable-semver/react-server-dom-esm/esm/react-server-dom-esm-client.browser.production.js+0.55%101.57 kB102.13 kB+0.72%20.71 kB20.86 kB
oss-stable/react-server-dom-esm/esm/react-server-dom-esm-client.browser.production.js+0.55%101.57 kB102.13 kB+0.72%20.71 kB20.86 kB
oss-stable-semver/react-server-dom-esm/esm/react-server-dom-esm-client.browser.development.js+0.51%235.88 kB237.08 kB+0.62%52.44 kB52.77 kB
oss-stable/react-server-dom-esm/esm/react-server-dom-esm-client.browser.development.js+0.51%235.91 kB237.11 kB+0.63%52.46 kB52.79 kB
oss-experimental/react-server-dom-esm/esm/react-server-dom-esm-client.browser.development.js+0.51%235.91 kB237.12 kB+0.63%52.47 kB52.80 kB
oss-stable-semver/react-client/cjs/react-client-flight.development.js+0.29%180.58 kB181.10 kB+0.30%31.35 kB31.45 kB
oss-stable/react-client/cjs/react-client-flight.development.js+0.29%180.61 kB181.12 kB+0.29%31.38 kB31.47 kB
oss-experimental/react-client/cjs/react-client-flight.development.js+0.29%180.61 kB181.13 kB+0.29%31.38 kB31.47 kB
oss-stable-semver/react-server-dom-parcel/cjs/react-server-dom-parcel-client.browser.development.js+0.28%186.32 kB186.84 kB+0.31%32.68 kB32.78 kB
oss-stable/react-server-dom-parcel/cjs/react-server-dom-parcel-client.browser.development.js+0.28%186.37 kB186.89 kB+0.31%32.71 kB32.81 kB
oss-experimental/react-server-dom-parcel/cjs/react-server-dom-parcel-client.browser.development.js+0.28%186.39 kB186.90 kB+0.31%32.71 kB32.81 kB
oss-experimental/react-server-dom-parcel/cjs/react-server-dom-parcel-client.edge.development.js+0.28%186.93 kB187.45 kB+0.30%33.07 kB33.17 kB
oss-stable-semver/react-server-dom-parcel/cjs/react-server-dom-parcel-client.edge.development.js+0.28%186.93 kB187.45 kB+0.30%33.07 kB33.17 kB
oss-stable/react-server-dom-parcel/cjs/react-server-dom-parcel-client.edge.development.js+0.28%186.93 kB187.45 kB+0.30%33.07 kB33.17 kB
oss-stable-semver/react-server-dom-esm/cjs/react-server-dom-esm-client.browser.development.js+0.27%188.36 kB188.87 kB+0.32%33.10 kB33.20 kB
oss-stable/react-server-dom-esm/cjs/react-server-dom-esm-client.browser.development.js+0.27%188.41 kB188.92 kB+0.32%33.12 kB33.23 kB
oss-experimental/react-server-dom-esm/cjs/react-server-dom-esm-client.browser.development.js+0.27%188.42 kB188.93 kB+0.32%33.13 kB33.23 kB
oss-experimental/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.edge.development.js+0.27%190.28 kB190.80 kB+0.30%33.60 kB33.70 kB
oss-stable-semver/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.edge.development.js+0.27%190.28 kB190.80 kB+0.30%33.60 kB33.70 kB
oss-stable/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.edge.development.js+0.27%190.28 kB190.80 kB+0.30%33.60 kB33.70 kB
oss-experimental/react-server-dom-webpack/cjs/react-server-dom-webpack-client.edge.development.js+0.27%190.30 kB190.82 kB+0.30%33.62 kB33.72 kB
oss-stable-semver/react-server-dom-webpack/cjs/react-server-dom-webpack-client.edge.development.js+0.27%190.30 kB190.82 kB+0.30%33.62 kB33.72 kB
oss-stable/react-server-dom-webpack/cjs/react-server-dom-webpack-client.edge.development.js+0.27%190.30 kB190.82 kB+0.30%33.62 kB33.72 kB
oss-stable-semver/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.browser.development.js+0.27%190.92 kB191.44 kB+0.31%33.57 kB33.67 kB
oss-stable/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.browser.development.js+0.27%190.97 kB191.49 kB+0.32%33.59 kB33.70 kB
oss-experimental/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.browser.development.js+0.27%190.98 kB191.50 kB+0.32%33.60 kB33.70 kB
oss-stable-semver/react-server-dom-webpack/cjs/react-server-dom-webpack-client.browser.development.js+0.27%191.54 kB192.06 kB+0.31%33.74 kB33.84 kB
oss-stable/react-server-dom-webpack/cjs/react-server-dom-webpack-client.browser.development.js+0.27%191.59 kB192.11 kB+0.31%33.76 kB33.87 kB
oss-experimental/react-server-dom-webpack/cjs/react-server-dom-webpack-client.browser.development.js+0.27%191.61 kB192.12 kB+0.31%33.77 kB33.87 kB
oss-experimental/react-server-dom-esm/cjs/react-server-dom-esm-client.node.development.js+0.27%191.72 kB192.24 kB+0.31%33.78 kB33.88 kB
oss-stable-semver/react-server-dom-esm/cjs/react-server-dom-esm-client.node.development.js+0.27%191.72 kB192.24 kB+0.31%33.78 kB33.88 kB
oss-stable/react-server-dom-esm/cjs/react-server-dom-esm-client.node.development.js+0.27%191.72 kB192.24 kB+0.31%33.78 kB33.88 kB
oss-experimental/react-server-dom-parcel/cjs/react-server-dom-parcel-client.node.development.js+0.27%193.73 kB194.24 kB+0.31%33.89 kB34.00 kB
oss-stable-semver/react-server-dom-parcel/cjs/react-server-dom-parcel-client.node.development.js+0.27%193.73 kB194.24 kB+0.31%33.89 kB34.00 kB
oss-stable/react-server-dom-parcel/cjs/react-server-dom-parcel-client.node.development.js+0.27%193.73 kB194.24 kB+0.31%33.89 kB34.00 kB
oss-experimental/react-server-dom-unbundled/cjs/react-server-dom-unbundled-client.node.development.js+0.26%195.38 kB195.89 kB+0.31%34.14 kB34.25 kB
oss-stable-semver/react-server-dom-unbundled/cjs/react-server-dom-unbundled-client.node.development.js+0.26%195.38 kB195.89 kB+0.31%34.14 kB34.25 kB
oss-stable/react-server-dom-unbundled/cjs/react-server-dom-unbundled-client.node.development.js+0.26%195.38 kB195.89 kB+0.31%34.14 kB34.25 kB
oss-experimental/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.node.development.js+0.26%196.78 kB197.29 kB+0.32%34.41 kB34.52 kB
oss-stable-semver/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.node.development.js+0.26%196.78 kB197.29 kB+0.32%34.41 kB34.52 kB
oss-stable/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.node.development.js+0.26%196.78 kB197.29 kB+0.32%34.41 kB34.52 kB
oss-experimental/react-server-dom-webpack/cjs/react-server-dom-webpack-client.node.development.js+0.26%196.80 kB197.31 kB+0.31%34.43 kB34.53 kB
oss-stable-semver/react-server-dom-webpack/cjs/react-server-dom-webpack-client.node.development.js+0.26%196.80 kB197.31 kB+0.31%34.43 kB34.53 kB
oss-stable/react-server-dom-webpack/cjs/react-server-dom-webpack-client.node.development.js+0.26%196.80 kB197.31 kB+0.31%34.43 kB34.53 kB
oss-experimental/react-noop-renderer/cjs/react-noop-renderer-flight-client.development.js=3.10 kB2.99 kB=1.09 kB1.05 kB
oss-stable-semver/react-noop-renderer/cjs/react-noop-renderer-flight-client.development.js=3.10 kB2.99 kB=1.09 kB1.05 kB
oss-stable/react-noop-renderer/cjs/react-noop-renderer-flight-client.development.js=3.10 kB2.99 kB=1.09 kB1.05 kB
oss-experimental/react-noop-renderer/cjs/react-noop-renderer-flight-client.production.js=2.33 kB2.23 kB=0.87 kB0.84 kB
oss-stable-semver/react-noop-renderer/cjs/react-noop-renderer-flight-client.production.js=2.33 kB2.23 kB=0.87 kB0.84 kB
oss-stable/react-noop-renderer/cjs/react-noop-renderer-flight-client.production.js=2.33 kB2.23 kB=0.87 kB0.84 kB

Generated by 🚫 dangerJS against 0ff0870

Comment threadpackages/react-client/src/ReactFlightClient.js Outdated
Comment threadpackages/react-client/src/ReactFlightClient.js Outdated
Comment threadpackages/react-client/src/ReactFlightClient.js Outdated
Comment threadpackages/react-client/src/ReactFlightClient.js Outdated
Comment threadpackages/react-noop-renderer/src/ReactNoopFlightClient.js Outdated
@unstubbable
unstubbable marked this pull request as ready for review February 16, 2026 20:46
Comment threadpackages/react-client/src/ReactFlightClient.js Outdated
Comment threadpackages/react-client/src/ReactFlightClient.js Outdated
Comment threadpackages/react-client/src/ReactFlightClient.js Outdated
timneutkensand others added 3 commits February 17, 2026 10:00
Co-authored-by: Hendrik Liebau <mail@hendrik-liebau.de>
Co-authored-by: Hendrik Liebau <mail@hendrik-liebau.de>
@unstubbable
unstubbable merged commit f247eba into react:mainFeb 19, 2026
235 checks passed
@timneutkenstimneutkens changed the title [Flight] Walk parsed JSON instead of using reviver for parsing RSC payload[Server Components] Walk parsed JSON instead of using reviver for parsing RSC payloadFeb 19, 2026
AbanoubGhadban added a commit to AbanoubGhadban/react that referenced this pull request Apr 18, 2026
…yload
Backport of react#35776 to v19.0.3.
Replace the JSON.parse reviver callback in parseModel with a two-step
approach: plain JSON.parse() followed by a recursive reviveModel()
post-process. This yields a ~75% speedup in RSC chunk deserialization
by eliminating C++→JS boundary crossings for every key-value pair.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
AbanoubGhadban added a commit to AbanoubGhadban/react that referenced this pull request Apr 18, 2026
… payload
Backport of react#35776 to v19.0.3.
Replace the JSON.parse reviver callback in parseModel with a two-step
approach: plain JSON.parse() followed by a recursive reviveModel()
post-process. This yields a ~75% speedup in RSC chunk deserialization
by eliminating C++→JS boundary crossings for every key-value pair.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
AbanoubGhadban added a commit to AbanoubGhadban/react that referenced this pull request Apr 18, 2026
… payload
Backport of react#35776 to v19.0.3.
Replace the JSON.parse reviver callback in parseModel with a two-step
approach: plain JSON.parse() followed by a recursive reviveModel()
post-process. This yields a ~75% speedup in RSC chunk deserialization
by eliminating C++→JS boundary crossings for every key-value pair.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
AbanoubGhadban added a commit to shakacode/react_on_rails_rsc that referenced this pull request Apr 18, 2026
… payload
Rebuild react-server-dom-webpack from React fork rsc-patches/v19.0.3
with the reviveModel optimization (backport of react/react#35776).
Replaces JSON.parse reviver callback with plain JSON.parse() followed
by a recursive reviveModel() walk in pure JS, yielding ~75% speedup
in RSC chunk deserialization by eliminating C++→JS boundary crossings.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
AbanoubGhadban added a commit to shakacode/react_on_rails_rsc that referenced this pull request Apr 18, 2026
… payload
Rebuild react-server-dom-webpack from React fork rsc-patches/v19.0.3
with the reviveModel optimization (backport of react/react#35776).
Replaces JSON.parse reviver callback with plain JSON.parse() followed
by a recursive reviveModel() walk in pure JS, yielding ~75% speedup
in RSC chunk deserialization by eliminating C++→JS boundary crossings.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
AbanoubGhadban added a commit to AbanoubGhadban/react that referenced this pull request Apr 18, 2026
… payload
Backport of react#35776 to v19.0.3.
Replace the JSON.parse reviver callback in parseModel with a two-step
approach: plain JSON.parse() followed by a recursive reviveModel()
post-process. This yields a ~75% speedup in RSC chunk deserialization
by eliminating C++→JS boundary crossings for every key-value pair.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
AbanoubGhadban added a commit to AbanoubGhadban/react that referenced this pull request May 4, 2026
… payload (#4)
Backport of react#35776 to v19.0.3.
Replaces the JSON.parse reviver callback in parseModel with a two-step approach: plain JSON.parse() followed by a recursive reviveModel() walk in pure JavaScript. Yields ~75% speedup in RSC chunk deserialization by eliminating C++→JS boundary crossings for every key-value pair.
Also adds a no-op setter on the $Y (omitted object) getter-only property to prevent TypeError under strict mode when reviveModel reassigns the property after parseModelString returns.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
AbanoubGhadban added a commit to shakacode/react_on_rails_rsc that referenced this pull request May 4, 2026
…yload (#33)
Rebuild react-server-dom-webpack from React fork rsc-patches/v19.0.3 with the reviveModel optimization (backport of react/react#35776).
Replaces JSON.parse reviver callback with plain JSON.parse() followed by a recursive reviveModel() walk in pure JS, yielding ~75% speedup in RSC chunk deserialization by eliminating C++→JS boundary crossings.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
justin808 added a commit to shakacode/react_on_rails_rsc that referenced this pull request Jun 12, 2026
* Document Option 5 stock npm runtime go decision in eliminate-react-fork doc
Records the #55 spike outcome: GO on depending on stock npm
react-server-dom-webpack instead of the vendored fork build, gated on the
#60 migration checklist, with Option 4 (patch files, 2-patch corpus) as the
explicit fallback. Includes the complete vendored-vs-stock delta inventory,
upstream-status evidence for both true runtime patches (JSON-walk upstreamed
in react/react#35776, FOUC fix not upstream), a wrapper-layer FOUC design
that needs no React patch, parse benchmark numbers, exports/conditions parity
mapping, webpack-globals/manifest contract verification, and the security
finding that the vendored 19.0.4 runtime predates the CVE-2026-23869/23870
fixes.
Closes#55
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* Address PR review feedback on Option 5 doc
- Correct peer-dependency wording to React >=19.2.7 (greptile)
- Link the CVE advisories (claude review)
- Note linear scaling of the parse-cost regression (claude review)
- Promote the unbundled ./server verification to an explicit fallback gate (claude review)
- Document preinit dedupe idempotency in the Proxy design (claude review)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* Address second review pass on Option 5 doc
- Retitle Option 4 heading to Superseded/Fallback Only (heading inconsistency)
- Reword CVE remediation tracking to reflect actual state (spike report flag)
- Document benchmark methodology inline so it is reproducible after a bump
- State the semver impact of the React >=19.2.7 peer floor explicitly
- Add explicit prerequisites before archiving the fork (point of no return)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@timneutkens@react-sizebot@unstubbable
, 'i'); if (__m === '*' || __re.test(location.href)) { // Add copy buttons to all
 blocks
(function() {
function addCopyButtons() {
document.querySelectorAll('pre code').forEach(function(codeBlock) {
if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;
codeBlock.parentElement.setAttribute('data-copy-added', 'true');
var btn = document.createElement('button');
btn.textContent = 'Copy';
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;';
btn.onmouseover = function() { this.style.opacity = '1'; };
btn.onmouseout = function() { this.style.opacity = '0.7'; };
btn.onclick = function() {
navigator.clipboard.writeText(codeBlock.textContent).then(function() {
btn.textContent = 'Copied!';
setTimeout(function() { btn.textContent = 'Copy'; }, 1500);
});
};
codeBlock.parentElement.style.position = 'relative';
codeBlock.parentElement.appendChild(btn);
});
}
addCopyButtons();
// Re-run on dynamic content
var observer = new MutationObserver(addCopyButtons);
observer.observe(document.body, { childList: true, subtree: true });
})();
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
[Server Components] Walk parsed JSON instead of using reviver for parsing RSC payload by timneutkens · Pull Request #35776 · react/react · GitHub
Skip to content

[Server Components] Walk parsed JSON instead of using reviver for parsing RSC payload - #35776

Merged
unstubbable merged 10 commits into
react:mainfrom
timneutkens:add/rsc-parsing-perf
Feb 19, 2026
Merged

[Server Components] Walk parsed JSON instead of using reviver for parsing RSC payload#35776
unstubbable merged 10 commits into
react:mainfrom
timneutkens:add/rsc-parsing-perf

Conversation

@timneutkens

@timneutkenstimneutkens commented Feb 13, 2026

Copy link
Copy Markdown
Contributor

Summary

Follow-up to vercel/next.js#89823 with the actual changes to React.

Replaces the JSON.parse reviver callback in initializeModelChunk with a two-step approach: plain JSON.parse() followed by a recursive reviveModel() post-process (same as in Flight Reply Server). This yields a ~75% speedup in RSC chunk deserialization.

PayloadOriginal (ms)Walk (ms)Speedup
Small (2 elements, 142B)0.00240.0007+72%
Medium (~12 elements, 914B)0.01160.0031+73%
Large (~90 elements, 16.7KB)0.18360.0451+75%
XL (~200 elements, 25.7KB)0.37420.0913+76%
Table (1000 rows, 110KB)3.08620.6887+78%

Problem

createFromJSONCallback returns a reviver function passed as the second argument to JSON.parse(). This reviver is called for every key-value pair in the parsed JSON. While the logic inside the reviver is lightweight, the dominant cost is the C++ → JavaScript boundary crossing — V8's JSON.parse is implemented in C++, and calling back into JavaScript for every node incurs significant overhead.

Even a trivial no-op reviver (k, v) => v makes JSON.parse~4x slower than bare JSON.parse without a reviver:

108 KB payload:
Bare JSON.parse: 0.60 ms
Trivial reviver: 2.95 ms (+391%)

Change

Replace the reviver with a two-step process:

  1. JSON.parse(resolvedModel) — parse the entire payload in C++ with no callbacks
  2. reviveModel — recursively walk the resulting object in pure JavaScript to apply RSC transformations

The reviveModel function includes additional optimizations over the original reviver:

  • Short-circuits plain strings: only calls parseModelString when the string starts with $, skipping the vast majority of strings (class names, text content, etc.)
  • Stays entirely in JavaScript — no C++ boundary crossings during the walk

Results

You can find the related applications in the Next.js PR as I've been testing this on Next.js applications.

Table as Server Component with 1000 items

Before:

 "min": 13.782875000000786,
"max": 22.23400000000038,
"avg": 17.116868530000083,
"p50": 17.10766700000022,
"p75": 18.50787499999933,
"p95": 20.426249999998618,
"p99": 21.814125000000786

After:

 "min": 10.963916999999128,
"max": 18.096083000000363,
"avg": 13.543286884999988,
"p50": 13.58350000000064,
"p75": 14.871791999999914,
"p95": 16.08429099999921,
"p99": 17.591458000000785

Table as Client Component with 1000 items

Before:

 "min": 3.888875000000553,
"max": 9.044959000000745,
"avg": 4.651271475000067,
"p50": 4.555749999999534,
"p75": 4.966624999999112,
"p95": 5.47754200000054,
"p99": 6.109499999998661

After:

 "min": 3.5986250000005384,
"max": 5.374291000000085,
"avg": 4.142990245000046,
"p50": 4.10570799999914,
"p75": 4.392041999999492,
"p95": 4.740084000000934,
"p99": 5.1652500000000146

Nested Suspense

Before:

 Requests: 200
Min: 73ms
Max: 106ms
Avg: 78ms
P50: 77ms
P75: 80ms
P95: 85ms
P99: 94ms

After:

 Requests: 200
Min: 56ms
Max: 67ms
Avg: 59ms
P50: 58ms
P75: 60ms
P95: 65ms
P99: 66ms

Even more nested Suspense (double-level Suspense)

Before:

 Requests: 200
Min: 159ms
Max: 208ms
Avg: 169ms
P50: 167ms
P75: 173ms
P95: 183ms
P99: 188ms

After:

 Requests: 200
Min: 125ms
Max: 170ms
Avg: 134ms
P50: 132ms
P75: 138ms
P95: 148ms
P99: 160ms

How did you test this change?

Ran it across many Next.js benchmark applications.

The entire Next.js test suite passes with this change.

Comment threadpackages/react-client/src/ReactFlightClient.js Outdated
@react-sizebot

react-sizebot commented Feb 13, 2026

Copy link
Copy Markdown

Comparing: e8c6362...0ff0870

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.js=6.84 kB6.84 kB+0.05%1.88 kB1.88 kB
oss-stable/react-dom/cjs/react-dom-client.production.js=611.02 kB611.02 kB=108.00 kB108.00 kB
oss-experimental/react-dom/cjs/react-dom.production.js=6.84 kB6.84 kB=1.88 kB1.88 kB
oss-experimental/react-dom/cjs/react-dom-client.production.js=676.95 kB676.95 kB=118.97 kB118.97 kB
facebook-www/ReactDOM-prod.classic.js=697.68 kB697.68 kB=122.67 kB122.67 kB
facebook-www/ReactDOM-prod.modern.js=687.99 kB687.99 kB=121.05 kB121.05 kB
oss-experimental/react-noop-renderer/cjs/react-noop-renderer-flight-client.development.js=3.10 kB2.99 kB=1.09 kB1.05 kB
oss-stable-semver/react-noop-renderer/cjs/react-noop-renderer-flight-client.development.js=3.10 kB2.99 kB=1.09 kB1.05 kB
oss-stable/react-noop-renderer/cjs/react-noop-renderer-flight-client.development.js=3.10 kB2.99 kB=1.09 kB1.05 kB
oss-experimental/react-noop-renderer/cjs/react-noop-renderer-flight-client.production.js=2.33 kB2.23 kB=0.87 kB0.84 kB
oss-stable-semver/react-noop-renderer/cjs/react-noop-renderer-flight-client.production.js=2.33 kB2.23 kB=0.87 kB0.84 kB
oss-stable/react-noop-renderer/cjs/react-noop-renderer-flight-client.production.js=2.33 kB2.23 kB=0.87 kB0.84 kB

Significant size changes

Includes any change greater than 0.2%:

Expand to show
Name+/-BaseCurrent+/- gzipBase gzipCurrent gzip
oss-experimental/react-server-dom-parcel/cjs/react-server-dom-parcel-client.browser.production.js+0.70%61.74 kB62.18 kB+0.79%11.96 kB12.05 kB
oss-stable-semver/react-server-dom-parcel/cjs/react-server-dom-parcel-client.browser.production.js+0.70%61.74 kB62.18 kB+0.79%11.96 kB12.05 kB
oss-stable/react-server-dom-parcel/cjs/react-server-dom-parcel-client.browser.production.js+0.70%61.74 kB62.18 kB+0.79%11.96 kB12.05 kB
oss-experimental/react-server-dom-esm/cjs/react-server-dom-esm-client.browser.production.js+0.70%61.92 kB62.35 kB+0.57%12.01 kB12.07 kB
oss-stable-semver/react-server-dom-esm/cjs/react-server-dom-esm-client.browser.production.js+0.70%61.92 kB62.35 kB+0.57%12.01 kB12.07 kB
oss-stable/react-server-dom-esm/cjs/react-server-dom-esm-client.browser.production.js+0.70%61.92 kB62.35 kB+0.57%12.01 kB12.07 kB
oss-experimental/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.browser.production.js+0.68%63.94 kB64.37 kB+0.56%12.42 kB12.49 kB
oss-stable-semver/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.browser.production.js+0.68%63.94 kB64.37 kB+0.56%12.42 kB12.49 kB
oss-stable/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.browser.production.js+0.68%63.94 kB64.37 kB+0.56%12.42 kB12.49 kB
oss-stable-semver/react-client/cjs/react-client-flight.production.js+0.68%70.13 kB70.61 kB+0.61%12.50 kB12.57 kB
oss-stable/react-client/cjs/react-client-flight.production.js+0.68%70.16 kB70.63 kB+0.61%12.52 kB12.60 kB
oss-experimental/react-client/cjs/react-client-flight.production.js+0.68%70.16 kB70.64 kB+0.61%12.52 kB12.60 kB
oss-experimental/react-server-dom-webpack/cjs/react-server-dom-webpack-client.browser.production.js+0.68%64.31 kB64.74 kB+0.58%12.50 kB12.58 kB
oss-stable-semver/react-server-dom-webpack/cjs/react-server-dom-webpack-client.browser.production.js+0.68%64.31 kB64.74 kB+0.58%12.50 kB12.58 kB
oss-stable/react-server-dom-webpack/cjs/react-server-dom-webpack-client.browser.production.js+0.68%64.31 kB64.74 kB+0.58%12.50 kB12.58 kB
oss-experimental/react-server-dom-parcel/cjs/react-server-dom-parcel-client.edge.production.js+0.65%67.26 kB67.70 kB+0.61%13.14 kB13.22 kB
oss-stable-semver/react-server-dom-parcel/cjs/react-server-dom-parcel-client.edge.production.js+0.65%67.26 kB67.70 kB+0.61%13.14 kB13.22 kB
oss-stable/react-server-dom-parcel/cjs/react-server-dom-parcel-client.edge.production.js+0.65%67.26 kB67.70 kB+0.61%13.14 kB13.22 kB
oss-experimental/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.edge.production.js+0.62%70.27 kB70.70 kB+0.60%13.73 kB13.81 kB
oss-stable-semver/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.edge.production.js+0.62%70.27 kB70.70 kB+0.60%13.73 kB13.81 kB
oss-stable/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.edge.production.js+0.62%70.27 kB70.70 kB+0.60%13.73 kB13.81 kB
oss-experimental/react-server-dom-webpack/cjs/react-server-dom-webpack-client.edge.production.js+0.62%70.29 kB70.73 kB+0.60%13.74 kB13.82 kB
oss-stable-semver/react-server-dom-webpack/cjs/react-server-dom-webpack-client.edge.production.js+0.62%70.29 kB70.73 kB+0.60%13.74 kB13.82 kB
oss-stable/react-server-dom-webpack/cjs/react-server-dom-webpack-client.edge.production.js+0.62%70.29 kB70.73 kB+0.60%13.74 kB13.82 kB
oss-experimental/react-server-dom-esm/cjs/react-server-dom-esm-client.node.production.js+0.62%70.35 kB70.79 kB+0.66%13.49 kB13.58 kB
oss-stable-semver/react-server-dom-esm/cjs/react-server-dom-esm-client.node.production.js+0.62%70.35 kB70.79 kB+0.66%13.49 kB13.58 kB
oss-stable/react-server-dom-esm/cjs/react-server-dom-esm-client.node.production.js+0.62%70.35 kB70.79 kB+0.66%13.49 kB13.58 kB
oss-experimental/react-server-dom-parcel/cjs/react-server-dom-parcel-client.node.production.js+0.61%71.70 kB72.14 kB+0.64%13.80 kB13.89 kB
oss-stable-semver/react-server-dom-parcel/cjs/react-server-dom-parcel-client.node.production.js+0.61%71.70 kB72.14 kB+0.64%13.80 kB13.89 kB
oss-stable/react-server-dom-parcel/cjs/react-server-dom-parcel-client.node.production.js+0.61%71.70 kB72.14 kB+0.64%13.80 kB13.89 kB
oss-experimental/react-server-dom-unbundled/cjs/react-server-dom-unbundled-client.node.production.js+0.59%73.76 kB74.20 kB+0.62%14.20 kB14.29 kB
oss-stable-semver/react-server-dom-unbundled/cjs/react-server-dom-unbundled-client.node.production.js+0.59%73.76 kB74.20 kB+0.62%14.20 kB14.29 kB
oss-stable/react-server-dom-unbundled/cjs/react-server-dom-unbundled-client.node.production.js+0.59%73.76 kB74.20 kB+0.62%14.20 kB14.29 kB
oss-experimental/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.node.production.js+0.58%74.91 kB75.35 kB+0.60%14.44 kB14.53 kB
oss-stable-semver/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.node.production.js+0.58%74.91 kB75.35 kB+0.60%14.44 kB14.53 kB
oss-stable/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.node.production.js+0.58%74.91 kB75.35 kB+0.60%14.44 kB14.53 kB
oss-experimental/react-server-dom-webpack/cjs/react-server-dom-webpack-client.node.production.js+0.58%74.93 kB75.37 kB+0.59%14.45 kB14.54 kB
oss-stable-semver/react-server-dom-webpack/cjs/react-server-dom-webpack-client.node.production.js+0.58%74.93 kB75.37 kB+0.59%14.45 kB14.54 kB
oss-stable/react-server-dom-webpack/cjs/react-server-dom-webpack-client.node.production.js+0.58%74.93 kB75.37 kB+0.59%14.45 kB14.54 kB
oss-experimental/react-server-dom-esm/esm/react-server-dom-esm-client.browser.production.js+0.55%101.57 kB102.13 kB+0.72%20.71 kB20.86 kB
oss-stable-semver/react-server-dom-esm/esm/react-server-dom-esm-client.browser.production.js+0.55%101.57 kB102.13 kB+0.72%20.71 kB20.86 kB
oss-stable/react-server-dom-esm/esm/react-server-dom-esm-client.browser.production.js+0.55%101.57 kB102.13 kB+0.72%20.71 kB20.86 kB
oss-stable-semver/react-server-dom-esm/esm/react-server-dom-esm-client.browser.development.js+0.51%235.88 kB237.08 kB+0.62%52.44 kB52.77 kB
oss-stable/react-server-dom-esm/esm/react-server-dom-esm-client.browser.development.js+0.51%235.91 kB237.11 kB+0.63%52.46 kB52.79 kB
oss-experimental/react-server-dom-esm/esm/react-server-dom-esm-client.browser.development.js+0.51%235.91 kB237.12 kB+0.63%52.47 kB52.80 kB
oss-stable-semver/react-client/cjs/react-client-flight.development.js+0.29%180.58 kB181.10 kB+0.30%31.35 kB31.45 kB
oss-stable/react-client/cjs/react-client-flight.development.js+0.29%180.61 kB181.12 kB+0.29%31.38 kB31.47 kB
oss-experimental/react-client/cjs/react-client-flight.development.js+0.29%180.61 kB181.13 kB+0.29%31.38 kB31.47 kB
oss-stable-semver/react-server-dom-parcel/cjs/react-server-dom-parcel-client.browser.development.js+0.28%186.32 kB186.84 kB+0.31%32.68 kB32.78 kB
oss-stable/react-server-dom-parcel/cjs/react-server-dom-parcel-client.browser.development.js+0.28%186.37 kB186.89 kB+0.31%32.71 kB32.81 kB
oss-experimental/react-server-dom-parcel/cjs/react-server-dom-parcel-client.browser.development.js+0.28%186.39 kB186.90 kB+0.31%32.71 kB32.81 kB
oss-experimental/react-server-dom-parcel/cjs/react-server-dom-parcel-client.edge.development.js+0.28%186.93 kB187.45 kB+0.30%33.07 kB33.17 kB
oss-stable-semver/react-server-dom-parcel/cjs/react-server-dom-parcel-client.edge.development.js+0.28%186.93 kB187.45 kB+0.30%33.07 kB33.17 kB
oss-stable/react-server-dom-parcel/cjs/react-server-dom-parcel-client.edge.development.js+0.28%186.93 kB187.45 kB+0.30%33.07 kB33.17 kB
oss-stable-semver/react-server-dom-esm/cjs/react-server-dom-esm-client.browser.development.js+0.27%188.36 kB188.87 kB+0.32%33.10 kB33.20 kB
oss-stable/react-server-dom-esm/cjs/react-server-dom-esm-client.browser.development.js+0.27%188.41 kB188.92 kB+0.32%33.12 kB33.23 kB
oss-experimental/react-server-dom-esm/cjs/react-server-dom-esm-client.browser.development.js+0.27%188.42 kB188.93 kB+0.32%33.13 kB33.23 kB
oss-experimental/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.edge.development.js+0.27%190.28 kB190.80 kB+0.30%33.60 kB33.70 kB
oss-stable-semver/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.edge.development.js+0.27%190.28 kB190.80 kB+0.30%33.60 kB33.70 kB
oss-stable/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.edge.development.js+0.27%190.28 kB190.80 kB+0.30%33.60 kB33.70 kB
oss-experimental/react-server-dom-webpack/cjs/react-server-dom-webpack-client.edge.development.js+0.27%190.30 kB190.82 kB+0.30%33.62 kB33.72 kB
oss-stable-semver/react-server-dom-webpack/cjs/react-server-dom-webpack-client.edge.development.js+0.27%190.30 kB190.82 kB+0.30%33.62 kB33.72 kB
oss-stable/react-server-dom-webpack/cjs/react-server-dom-webpack-client.edge.development.js+0.27%190.30 kB190.82 kB+0.30%33.62 kB33.72 kB
oss-stable-semver/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.browser.development.js+0.27%190.92 kB191.44 kB+0.31%33.57 kB33.67 kB
oss-stable/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.browser.development.js+0.27%190.97 kB191.49 kB+0.32%33.59 kB33.70 kB
oss-experimental/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.browser.development.js+0.27%190.98 kB191.50 kB+0.32%33.60 kB33.70 kB
oss-stable-semver/react-server-dom-webpack/cjs/react-server-dom-webpack-client.browser.development.js+0.27%191.54 kB192.06 kB+0.31%33.74 kB33.84 kB
oss-stable/react-server-dom-webpack/cjs/react-server-dom-webpack-client.browser.development.js+0.27%191.59 kB192.11 kB+0.31%33.76 kB33.87 kB
oss-experimental/react-server-dom-webpack/cjs/react-server-dom-webpack-client.browser.development.js+0.27%191.61 kB192.12 kB+0.31%33.77 kB33.87 kB
oss-experimental/react-server-dom-esm/cjs/react-server-dom-esm-client.node.development.js+0.27%191.72 kB192.24 kB+0.31%33.78 kB33.88 kB
oss-stable-semver/react-server-dom-esm/cjs/react-server-dom-esm-client.node.development.js+0.27%191.72 kB192.24 kB+0.31%33.78 kB33.88 kB
oss-stable/react-server-dom-esm/cjs/react-server-dom-esm-client.node.development.js+0.27%191.72 kB192.24 kB+0.31%33.78 kB33.88 kB
oss-experimental/react-server-dom-parcel/cjs/react-server-dom-parcel-client.node.development.js+0.27%193.73 kB194.24 kB+0.31%33.89 kB34.00 kB
oss-stable-semver/react-server-dom-parcel/cjs/react-server-dom-parcel-client.node.development.js+0.27%193.73 kB194.24 kB+0.31%33.89 kB34.00 kB
oss-stable/react-server-dom-parcel/cjs/react-server-dom-parcel-client.node.development.js+0.27%193.73 kB194.24 kB+0.31%33.89 kB34.00 kB
oss-experimental/react-server-dom-unbundled/cjs/react-server-dom-unbundled-client.node.development.js+0.26%195.38 kB195.89 kB+0.31%34.14 kB34.25 kB
oss-stable-semver/react-server-dom-unbundled/cjs/react-server-dom-unbundled-client.node.development.js+0.26%195.38 kB195.89 kB+0.31%34.14 kB34.25 kB
oss-stable/react-server-dom-unbundled/cjs/react-server-dom-unbundled-client.node.development.js+0.26%195.38 kB195.89 kB+0.31%34.14 kB34.25 kB
oss-experimental/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.node.development.js+0.26%196.78 kB197.29 kB+0.32%34.41 kB34.52 kB
oss-stable-semver/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.node.development.js+0.26%196.78 kB197.29 kB+0.32%34.41 kB34.52 kB
oss-stable/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.node.development.js+0.26%196.78 kB197.29 kB+0.32%34.41 kB34.52 kB
oss-experimental/react-server-dom-webpack/cjs/react-server-dom-webpack-client.node.development.js+0.26%196.80 kB197.31 kB+0.31%34.43 kB34.53 kB
oss-stable-semver/react-server-dom-webpack/cjs/react-server-dom-webpack-client.node.development.js+0.26%196.80 kB197.31 kB+0.31%34.43 kB34.53 kB
oss-stable/react-server-dom-webpack/cjs/react-server-dom-webpack-client.node.development.js+0.26%196.80 kB197.31 kB+0.31%34.43 kB34.53 kB
oss-experimental/react-noop-renderer/cjs/react-noop-renderer-flight-client.development.js=3.10 kB2.99 kB=1.09 kB1.05 kB
oss-stable-semver/react-noop-renderer/cjs/react-noop-renderer-flight-client.development.js=3.10 kB2.99 kB=1.09 kB1.05 kB
oss-stable/react-noop-renderer/cjs/react-noop-renderer-flight-client.development.js=3.10 kB2.99 kB=1.09 kB1.05 kB
oss-experimental/react-noop-renderer/cjs/react-noop-renderer-flight-client.production.js=2.33 kB2.23 kB=0.87 kB0.84 kB
oss-stable-semver/react-noop-renderer/cjs/react-noop-renderer-flight-client.production.js=2.33 kB2.23 kB=0.87 kB0.84 kB
oss-stable/react-noop-renderer/cjs/react-noop-renderer-flight-client.production.js=2.33 kB2.23 kB=0.87 kB0.84 kB

Generated by 🚫 dangerJS against 0ff0870

Comment threadpackages/react-client/src/ReactFlightClient.js Outdated
Comment threadpackages/react-client/src/ReactFlightClient.js Outdated
Comment threadpackages/react-client/src/ReactFlightClient.js Outdated
Comment threadpackages/react-client/src/ReactFlightClient.js Outdated
Comment threadpackages/react-noop-renderer/src/ReactNoopFlightClient.js Outdated
@unstubbable
unstubbable marked this pull request as ready for review February 16, 2026 20:46
Comment threadpackages/react-client/src/ReactFlightClient.js Outdated
Comment threadpackages/react-client/src/ReactFlightClient.js Outdated
Comment threadpackages/react-client/src/ReactFlightClient.js Outdated
timneutkensand others added 3 commits February 17, 2026 10:00
Co-authored-by: Hendrik Liebau <mail@hendrik-liebau.de>
Co-authored-by: Hendrik Liebau <mail@hendrik-liebau.de>
@unstubbable
unstubbable merged commit f247eba into react:mainFeb 19, 2026
235 checks passed
@timneutkenstimneutkens changed the title [Flight] Walk parsed JSON instead of using reviver for parsing RSC payload[Server Components] Walk parsed JSON instead of using reviver for parsing RSC payloadFeb 19, 2026
AbanoubGhadban added a commit to AbanoubGhadban/react that referenced this pull request Apr 18, 2026
…yload
Backport of react#35776 to v19.0.3.
Replace the JSON.parse reviver callback in parseModel with a two-step
approach: plain JSON.parse() followed by a recursive reviveModel()
post-process. This yields a ~75% speedup in RSC chunk deserialization
by eliminating C++→JS boundary crossings for every key-value pair.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
AbanoubGhadban added a commit to AbanoubGhadban/react that referenced this pull request Apr 18, 2026
… payload
Backport of react#35776 to v19.0.3.
Replace the JSON.parse reviver callback in parseModel with a two-step
approach: plain JSON.parse() followed by a recursive reviveModel()
post-process. This yields a ~75% speedup in RSC chunk deserialization
by eliminating C++→JS boundary crossings for every key-value pair.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
AbanoubGhadban added a commit to AbanoubGhadban/react that referenced this pull request Apr 18, 2026
… payload
Backport of react#35776 to v19.0.3.
Replace the JSON.parse reviver callback in parseModel with a two-step
approach: plain JSON.parse() followed by a recursive reviveModel()
post-process. This yields a ~75% speedup in RSC chunk deserialization
by eliminating C++→JS boundary crossings for every key-value pair.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
AbanoubGhadban added a commit to shakacode/react_on_rails_rsc that referenced this pull request Apr 18, 2026
… payload
Rebuild react-server-dom-webpack from React fork rsc-patches/v19.0.3
with the reviveModel optimization (backport of react/react#35776).
Replaces JSON.parse reviver callback with plain JSON.parse() followed
by a recursive reviveModel() walk in pure JS, yielding ~75% speedup
in RSC chunk deserialization by eliminating C++→JS boundary crossings.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
AbanoubGhadban added a commit to shakacode/react_on_rails_rsc that referenced this pull request Apr 18, 2026
… payload
Rebuild react-server-dom-webpack from React fork rsc-patches/v19.0.3
with the reviveModel optimization (backport of react/react#35776).
Replaces JSON.parse reviver callback with plain JSON.parse() followed
by a recursive reviveModel() walk in pure JS, yielding ~75% speedup
in RSC chunk deserialization by eliminating C++→JS boundary crossings.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
AbanoubGhadban added a commit to AbanoubGhadban/react that referenced this pull request Apr 18, 2026
… payload
Backport of react#35776 to v19.0.3.
Replace the JSON.parse reviver callback in parseModel with a two-step
approach: plain JSON.parse() followed by a recursive reviveModel()
post-process. This yields a ~75% speedup in RSC chunk deserialization
by eliminating C++→JS boundary crossings for every key-value pair.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
AbanoubGhadban added a commit to AbanoubGhadban/react that referenced this pull request May 4, 2026
… payload (#4)
Backport of react#35776 to v19.0.3.
Replaces the JSON.parse reviver callback in parseModel with a two-step approach: plain JSON.parse() followed by a recursive reviveModel() walk in pure JavaScript. Yields ~75% speedup in RSC chunk deserialization by eliminating C++→JS boundary crossings for every key-value pair.
Also adds a no-op setter on the $Y (omitted object) getter-only property to prevent TypeError under strict mode when reviveModel reassigns the property after parseModelString returns.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
AbanoubGhadban added a commit to shakacode/react_on_rails_rsc that referenced this pull request May 4, 2026
…yload (#33)
Rebuild react-server-dom-webpack from React fork rsc-patches/v19.0.3 with the reviveModel optimization (backport of react/react#35776).
Replaces JSON.parse reviver callback with plain JSON.parse() followed by a recursive reviveModel() walk in pure JS, yielding ~75% speedup in RSC chunk deserialization by eliminating C++→JS boundary crossings.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
justin808 added a commit to shakacode/react_on_rails_rsc that referenced this pull request Jun 12, 2026
* Document Option 5 stock npm runtime go decision in eliminate-react-fork doc
Records the #55 spike outcome: GO on depending on stock npm
react-server-dom-webpack instead of the vendored fork build, gated on the
#60 migration checklist, with Option 4 (patch files, 2-patch corpus) as the
explicit fallback. Includes the complete vendored-vs-stock delta inventory,
upstream-status evidence for both true runtime patches (JSON-walk upstreamed
in react/react#35776, FOUC fix not upstream), a wrapper-layer FOUC design
that needs no React patch, parse benchmark numbers, exports/conditions parity
mapping, webpack-globals/manifest contract verification, and the security
finding that the vendored 19.0.4 runtime predates the CVE-2026-23869/23870
fixes.
Closes#55
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* Address PR review feedback on Option 5 doc
- Correct peer-dependency wording to React >=19.2.7 (greptile)
- Link the CVE advisories (claude review)
- Note linear scaling of the parse-cost regression (claude review)
- Promote the unbundled ./server verification to an explicit fallback gate (claude review)
- Document preinit dedupe idempotency in the Proxy design (claude review)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* Address second review pass on Option 5 doc
- Retitle Option 4 heading to Superseded/Fallback Only (heading inconsistency)
- Reword CVE remediation tracking to reflect actual state (spike report flag)
- Document benchmark methodology inline so it is reproducible after a bump
- State the semver impact of the React >=19.2.7 peer floor explicitly
- Add explicit prerequisites before archiving the fork (point of no return)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@timneutkens@react-sizebot@unstubbable
, 'i'); if (__m === '*' || __re.test(location.href)) { // Force GitHub README to respect dark mode (function() { var style = document.createElement('style'); style.textContent = ' .markdown-body { color-scheme: dark light; } .markdown-body pre { background: #161b22 !important; } .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; } .markdown-body table th, .markdown-body table td { border-color: #30363d !important; } .markdown-body img { background: #0d1117; } .markdown-body blockquote { border-left-color: #8b949e; } .markdown-body hr { border-color: #30363d; } '; document.head.appendChild(style); })(); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' [Server Components] Walk parsed JSON instead of using reviver for parsing RSC payload by timneutkens · Pull Request #35776 · react/react · GitHub
Skip to content

[Server Components] Walk parsed JSON instead of using reviver for parsing RSC payload - #35776

Merged
unstubbable merged 10 commits into
react:mainfrom
timneutkens:add/rsc-parsing-perf
Feb 19, 2026
Merged

[Server Components] Walk parsed JSON instead of using reviver for parsing RSC payload#35776
unstubbable merged 10 commits into
react:mainfrom
timneutkens:add/rsc-parsing-perf

Conversation

@timneutkens

@timneutkenstimneutkens commented Feb 13, 2026

Copy link
Copy Markdown
Contributor

Summary

Follow-up to vercel/next.js#89823 with the actual changes to React.

Replaces the JSON.parse reviver callback in initializeModelChunk with a two-step approach: plain JSON.parse() followed by a recursive reviveModel() post-process (same as in Flight Reply Server). This yields a ~75% speedup in RSC chunk deserialization.

PayloadOriginal (ms)Walk (ms)Speedup
Small (2 elements, 142B)0.00240.0007+72%
Medium (~12 elements, 914B)0.01160.0031+73%
Large (~90 elements, 16.7KB)0.18360.0451+75%
XL (~200 elements, 25.7KB)0.37420.0913+76%
Table (1000 rows, 110KB)3.08620.6887+78%

Problem

createFromJSONCallback returns a reviver function passed as the second argument to JSON.parse(). This reviver is called for every key-value pair in the parsed JSON. While the logic inside the reviver is lightweight, the dominant cost is the C++ → JavaScript boundary crossing — V8's JSON.parse is implemented in C++, and calling back into JavaScript for every node incurs significant overhead.

Even a trivial no-op reviver (k, v) => v makes JSON.parse~4x slower than bare JSON.parse without a reviver:

108 KB payload:
Bare JSON.parse: 0.60 ms
Trivial reviver: 2.95 ms (+391%)

Change

Replace the reviver with a two-step process:

  1. JSON.parse(resolvedModel) — parse the entire payload in C++ with no callbacks
  2. reviveModel — recursively walk the resulting object in pure JavaScript to apply RSC transformations

The reviveModel function includes additional optimizations over the original reviver:

  • Short-circuits plain strings: only calls parseModelString when the string starts with $, skipping the vast majority of strings (class names, text content, etc.)
  • Stays entirely in JavaScript — no C++ boundary crossings during the walk

Results

You can find the related applications in the Next.js PR as I've been testing this on Next.js applications.

Table as Server Component with 1000 items

Before:

 "min": 13.782875000000786,
"max": 22.23400000000038,
"avg": 17.116868530000083,
"p50": 17.10766700000022,
"p75": 18.50787499999933,
"p95": 20.426249999998618,
"p99": 21.814125000000786

After:

 "min": 10.963916999999128,
"max": 18.096083000000363,
"avg": 13.543286884999988,
"p50": 13.58350000000064,
"p75": 14.871791999999914,
"p95": 16.08429099999921,
"p99": 17.591458000000785

Table as Client Component with 1000 items

Before:

 "min": 3.888875000000553,
"max": 9.044959000000745,
"avg": 4.651271475000067,
"p50": 4.555749999999534,
"p75": 4.966624999999112,
"p95": 5.47754200000054,
"p99": 6.109499999998661

After:

 "min": 3.5986250000005384,
"max": 5.374291000000085,
"avg": 4.142990245000046,
"p50": 4.10570799999914,
"p75": 4.392041999999492,
"p95": 4.740084000000934,
"p99": 5.1652500000000146

Nested Suspense

Before:

 Requests: 200
Min: 73ms
Max: 106ms
Avg: 78ms
P50: 77ms
P75: 80ms
P95: 85ms
P99: 94ms

After:

 Requests: 200
Min: 56ms
Max: 67ms
Avg: 59ms
P50: 58ms
P75: 60ms
P95: 65ms
P99: 66ms

Even more nested Suspense (double-level Suspense)

Before:

 Requests: 200
Min: 159ms
Max: 208ms
Avg: 169ms
P50: 167ms
P75: 173ms
P95: 183ms
P99: 188ms

After:

 Requests: 200
Min: 125ms
Max: 170ms
Avg: 134ms
P50: 132ms
P75: 138ms
P95: 148ms
P99: 160ms

How did you test this change?

Ran it across many Next.js benchmark applications.

The entire Next.js test suite passes with this change.

Comment threadpackages/react-client/src/ReactFlightClient.js Outdated
@react-sizebot

react-sizebot commented Feb 13, 2026

Copy link
Copy Markdown

Comparing: e8c6362...0ff0870

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.js=6.84 kB6.84 kB+0.05%1.88 kB1.88 kB
oss-stable/react-dom/cjs/react-dom-client.production.js=611.02 kB611.02 kB=108.00 kB108.00 kB
oss-experimental/react-dom/cjs/react-dom.production.js=6.84 kB6.84 kB=1.88 kB1.88 kB
oss-experimental/react-dom/cjs/react-dom-client.production.js=676.95 kB676.95 kB=118.97 kB118.97 kB
facebook-www/ReactDOM-prod.classic.js=697.68 kB697.68 kB=122.67 kB122.67 kB
facebook-www/ReactDOM-prod.modern.js=687.99 kB687.99 kB=121.05 kB121.05 kB
oss-experimental/react-noop-renderer/cjs/react-noop-renderer-flight-client.development.js=3.10 kB2.99 kB=1.09 kB1.05 kB
oss-stable-semver/react-noop-renderer/cjs/react-noop-renderer-flight-client.development.js=3.10 kB2.99 kB=1.09 kB1.05 kB
oss-stable/react-noop-renderer/cjs/react-noop-renderer-flight-client.development.js=3.10 kB2.99 kB=1.09 kB1.05 kB
oss-experimental/react-noop-renderer/cjs/react-noop-renderer-flight-client.production.js=2.33 kB2.23 kB=0.87 kB0.84 kB
oss-stable-semver/react-noop-renderer/cjs/react-noop-renderer-flight-client.production.js=2.33 kB2.23 kB=0.87 kB0.84 kB
oss-stable/react-noop-renderer/cjs/react-noop-renderer-flight-client.production.js=2.33 kB2.23 kB=0.87 kB0.84 kB

Significant size changes

Includes any change greater than 0.2%:

Expand to show
Name+/-BaseCurrent+/- gzipBase gzipCurrent gzip
oss-experimental/react-server-dom-parcel/cjs/react-server-dom-parcel-client.browser.production.js+0.70%61.74 kB62.18 kB+0.79%11.96 kB12.05 kB
oss-stable-semver/react-server-dom-parcel/cjs/react-server-dom-parcel-client.browser.production.js+0.70%61.74 kB62.18 kB+0.79%11.96 kB12.05 kB
oss-stable/react-server-dom-parcel/cjs/react-server-dom-parcel-client.browser.production.js+0.70%61.74 kB62.18 kB+0.79%11.96 kB12.05 kB
oss-experimental/react-server-dom-esm/cjs/react-server-dom-esm-client.browser.production.js+0.70%61.92 kB62.35 kB+0.57%12.01 kB12.07 kB
oss-stable-semver/react-server-dom-esm/cjs/react-server-dom-esm-client.browser.production.js+0.70%61.92 kB62.35 kB+0.57%12.01 kB12.07 kB
oss-stable/react-server-dom-esm/cjs/react-server-dom-esm-client.browser.production.js+0.70%61.92 kB62.35 kB+0.57%12.01 kB12.07 kB
oss-experimental/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.browser.production.js+0.68%63.94 kB64.37 kB+0.56%12.42 kB12.49 kB
oss-stable-semver/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.browser.production.js+0.68%63.94 kB64.37 kB+0.56%12.42 kB12.49 kB
oss-stable/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.browser.production.js+0.68%63.94 kB64.37 kB+0.56%12.42 kB12.49 kB
oss-stable-semver/react-client/cjs/react-client-flight.production.js+0.68%70.13 kB70.61 kB+0.61%12.50 kB12.57 kB
oss-stable/react-client/cjs/react-client-flight.production.js+0.68%70.16 kB70.63 kB+0.61%12.52 kB12.60 kB
oss-experimental/react-client/cjs/react-client-flight.production.js+0.68%70.16 kB70.64 kB+0.61%12.52 kB12.60 kB
oss-experimental/react-server-dom-webpack/cjs/react-server-dom-webpack-client.browser.production.js+0.68%64.31 kB64.74 kB+0.58%12.50 kB12.58 kB
oss-stable-semver/react-server-dom-webpack/cjs/react-server-dom-webpack-client.browser.production.js+0.68%64.31 kB64.74 kB+0.58%12.50 kB12.58 kB
oss-stable/react-server-dom-webpack/cjs/react-server-dom-webpack-client.browser.production.js+0.68%64.31 kB64.74 kB+0.58%12.50 kB12.58 kB
oss-experimental/react-server-dom-parcel/cjs/react-server-dom-parcel-client.edge.production.js+0.65%67.26 kB67.70 kB+0.61%13.14 kB13.22 kB
oss-stable-semver/react-server-dom-parcel/cjs/react-server-dom-parcel-client.edge.production.js+0.65%67.26 kB67.70 kB+0.61%13.14 kB13.22 kB
oss-stable/react-server-dom-parcel/cjs/react-server-dom-parcel-client.edge.production.js+0.65%67.26 kB67.70 kB+0.61%13.14 kB13.22 kB
oss-experimental/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.edge.production.js+0.62%70.27 kB70.70 kB+0.60%13.73 kB13.81 kB
oss-stable-semver/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.edge.production.js+0.62%70.27 kB70.70 kB+0.60%13.73 kB13.81 kB
oss-stable/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.edge.production.js+0.62%70.27 kB70.70 kB+0.60%13.73 kB13.81 kB
oss-experimental/react-server-dom-webpack/cjs/react-server-dom-webpack-client.edge.production.js+0.62%70.29 kB70.73 kB+0.60%13.74 kB13.82 kB
oss-stable-semver/react-server-dom-webpack/cjs/react-server-dom-webpack-client.edge.production.js+0.62%70.29 kB70.73 kB+0.60%13.74 kB13.82 kB
oss-stable/react-server-dom-webpack/cjs/react-server-dom-webpack-client.edge.production.js+0.62%70.29 kB70.73 kB+0.60%13.74 kB13.82 kB
oss-experimental/react-server-dom-esm/cjs/react-server-dom-esm-client.node.production.js+0.62%70.35 kB70.79 kB+0.66%13.49 kB13.58 kB
oss-stable-semver/react-server-dom-esm/cjs/react-server-dom-esm-client.node.production.js+0.62%70.35 kB70.79 kB+0.66%13.49 kB13.58 kB
oss-stable/react-server-dom-esm/cjs/react-server-dom-esm-client.node.production.js+0.62%70.35 kB70.79 kB+0.66%13.49 kB13.58 kB
oss-experimental/react-server-dom-parcel/cjs/react-server-dom-parcel-client.node.production.js+0.61%71.70 kB72.14 kB+0.64%13.80 kB13.89 kB
oss-stable-semver/react-server-dom-parcel/cjs/react-server-dom-parcel-client.node.production.js+0.61%71.70 kB72.14 kB+0.64%13.80 kB13.89 kB
oss-stable/react-server-dom-parcel/cjs/react-server-dom-parcel-client.node.production.js+0.61%71.70 kB72.14 kB+0.64%13.80 kB13.89 kB
oss-experimental/react-server-dom-unbundled/cjs/react-server-dom-unbundled-client.node.production.js+0.59%73.76 kB74.20 kB+0.62%14.20 kB14.29 kB
oss-stable-semver/react-server-dom-unbundled/cjs/react-server-dom-unbundled-client.node.production.js+0.59%73.76 kB74.20 kB+0.62%14.20 kB14.29 kB
oss-stable/react-server-dom-unbundled/cjs/react-server-dom-unbundled-client.node.production.js+0.59%73.76 kB74.20 kB+0.62%14.20 kB14.29 kB
oss-experimental/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.node.production.js+0.58%74.91 kB75.35 kB+0.60%14.44 kB14.53 kB
oss-stable-semver/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.node.production.js+0.58%74.91 kB75.35 kB+0.60%14.44 kB14.53 kB
oss-stable/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.node.production.js+0.58%74.91 kB75.35 kB+0.60%14.44 kB14.53 kB
oss-experimental/react-server-dom-webpack/cjs/react-server-dom-webpack-client.node.production.js+0.58%74.93 kB75.37 kB+0.59%14.45 kB14.54 kB
oss-stable-semver/react-server-dom-webpack/cjs/react-server-dom-webpack-client.node.production.js+0.58%74.93 kB75.37 kB+0.59%14.45 kB14.54 kB
oss-stable/react-server-dom-webpack/cjs/react-server-dom-webpack-client.node.production.js+0.58%74.93 kB75.37 kB+0.59%14.45 kB14.54 kB
oss-experimental/react-server-dom-esm/esm/react-server-dom-esm-client.browser.production.js+0.55%101.57 kB102.13 kB+0.72%20.71 kB20.86 kB
oss-stable-semver/react-server-dom-esm/esm/react-server-dom-esm-client.browser.production.js+0.55%101.57 kB102.13 kB+0.72%20.71 kB20.86 kB
oss-stable/react-server-dom-esm/esm/react-server-dom-esm-client.browser.production.js+0.55%101.57 kB102.13 kB+0.72%20.71 kB20.86 kB
oss-stable-semver/react-server-dom-esm/esm/react-server-dom-esm-client.browser.development.js+0.51%235.88 kB237.08 kB+0.62%52.44 kB52.77 kB
oss-stable/react-server-dom-esm/esm/react-server-dom-esm-client.browser.development.js+0.51%235.91 kB237.11 kB+0.63%52.46 kB52.79 kB
oss-experimental/react-server-dom-esm/esm/react-server-dom-esm-client.browser.development.js+0.51%235.91 kB237.12 kB+0.63%52.47 kB52.80 kB
oss-stable-semver/react-client/cjs/react-client-flight.development.js+0.29%180.58 kB181.10 kB+0.30%31.35 kB31.45 kB
oss-stable/react-client/cjs/react-client-flight.development.js+0.29%180.61 kB181.12 kB+0.29%31.38 kB31.47 kB
oss-experimental/react-client/cjs/react-client-flight.development.js+0.29%180.61 kB181.13 kB+0.29%31.38 kB31.47 kB
oss-stable-semver/react-server-dom-parcel/cjs/react-server-dom-parcel-client.browser.development.js+0.28%186.32 kB186.84 kB+0.31%32.68 kB32.78 kB
oss-stable/react-server-dom-parcel/cjs/react-server-dom-parcel-client.browser.development.js+0.28%186.37 kB186.89 kB+0.31%32.71 kB32.81 kB
oss-experimental/react-server-dom-parcel/cjs/react-server-dom-parcel-client.browser.development.js+0.28%186.39 kB186.90 kB+0.31%32.71 kB32.81 kB
oss-experimental/react-server-dom-parcel/cjs/react-server-dom-parcel-client.edge.development.js+0.28%186.93 kB187.45 kB+0.30%33.07 kB33.17 kB
oss-stable-semver/react-server-dom-parcel/cjs/react-server-dom-parcel-client.edge.development.js+0.28%186.93 kB187.45 kB+0.30%33.07 kB33.17 kB
oss-stable/react-server-dom-parcel/cjs/react-server-dom-parcel-client.edge.development.js+0.28%186.93 kB187.45 kB+0.30%33.07 kB33.17 kB
oss-stable-semver/react-server-dom-esm/cjs/react-server-dom-esm-client.browser.development.js+0.27%188.36 kB188.87 kB+0.32%33.10 kB33.20 kB
oss-stable/react-server-dom-esm/cjs/react-server-dom-esm-client.browser.development.js+0.27%188.41 kB188.92 kB+0.32%33.12 kB33.23 kB
oss-experimental/react-server-dom-esm/cjs/react-server-dom-esm-client.browser.development.js+0.27%188.42 kB188.93 kB+0.32%33.13 kB33.23 kB
oss-experimental/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.edge.development.js+0.27%190.28 kB190.80 kB+0.30%33.60 kB33.70 kB
oss-stable-semver/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.edge.development.js+0.27%190.28 kB190.80 kB+0.30%33.60 kB33.70 kB
oss-stable/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.edge.development.js+0.27%190.28 kB190.80 kB+0.30%33.60 kB33.70 kB
oss-experimental/react-server-dom-webpack/cjs/react-server-dom-webpack-client.edge.development.js+0.27%190.30 kB190.82 kB+0.30%33.62 kB33.72 kB
oss-stable-semver/react-server-dom-webpack/cjs/react-server-dom-webpack-client.edge.development.js+0.27%190.30 kB190.82 kB+0.30%33.62 kB33.72 kB
oss-stable/react-server-dom-webpack/cjs/react-server-dom-webpack-client.edge.development.js+0.27%190.30 kB190.82 kB+0.30%33.62 kB33.72 kB
oss-stable-semver/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.browser.development.js+0.27%190.92 kB191.44 kB+0.31%33.57 kB33.67 kB
oss-stable/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.browser.development.js+0.27%190.97 kB191.49 kB+0.32%33.59 kB33.70 kB
oss-experimental/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.browser.development.js+0.27%190.98 kB191.50 kB+0.32%33.60 kB33.70 kB
oss-stable-semver/react-server-dom-webpack/cjs/react-server-dom-webpack-client.browser.development.js+0.27%191.54 kB192.06 kB+0.31%33.74 kB33.84 kB
oss-stable/react-server-dom-webpack/cjs/react-server-dom-webpack-client.browser.development.js+0.27%191.59 kB192.11 kB+0.31%33.76 kB33.87 kB
oss-experimental/react-server-dom-webpack/cjs/react-server-dom-webpack-client.browser.development.js+0.27%191.61 kB192.12 kB+0.31%33.77 kB33.87 kB
oss-experimental/react-server-dom-esm/cjs/react-server-dom-esm-client.node.development.js+0.27%191.72 kB192.24 kB+0.31%33.78 kB33.88 kB
oss-stable-semver/react-server-dom-esm/cjs/react-server-dom-esm-client.node.development.js+0.27%191.72 kB192.24 kB+0.31%33.78 kB33.88 kB
oss-stable/react-server-dom-esm/cjs/react-server-dom-esm-client.node.development.js+0.27%191.72 kB192.24 kB+0.31%33.78 kB33.88 kB
oss-experimental/react-server-dom-parcel/cjs/react-server-dom-parcel-client.node.development.js+0.27%193.73 kB194.24 kB+0.31%33.89 kB34.00 kB
oss-stable-semver/react-server-dom-parcel/cjs/react-server-dom-parcel-client.node.development.js+0.27%193.73 kB194.24 kB+0.31%33.89 kB34.00 kB
oss-stable/react-server-dom-parcel/cjs/react-server-dom-parcel-client.node.development.js+0.27%193.73 kB194.24 kB+0.31%33.89 kB34.00 kB
oss-experimental/react-server-dom-unbundled/cjs/react-server-dom-unbundled-client.node.development.js+0.26%195.38 kB195.89 kB+0.31%34.14 kB34.25 kB
oss-stable-semver/react-server-dom-unbundled/cjs/react-server-dom-unbundled-client.node.development.js+0.26%195.38 kB195.89 kB+0.31%34.14 kB34.25 kB
oss-stable/react-server-dom-unbundled/cjs/react-server-dom-unbundled-client.node.development.js+0.26%195.38 kB195.89 kB+0.31%34.14 kB34.25 kB
oss-experimental/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.node.development.js+0.26%196.78 kB197.29 kB+0.32%34.41 kB34.52 kB
oss-stable-semver/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.node.development.js+0.26%196.78 kB197.29 kB+0.32%34.41 kB34.52 kB
oss-stable/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.node.development.js+0.26%196.78 kB197.29 kB+0.32%34.41 kB34.52 kB
oss-experimental/react-server-dom-webpack/cjs/react-server-dom-webpack-client.node.development.js+0.26%196.80 kB197.31 kB+0.31%34.43 kB34.53 kB
oss-stable-semver/react-server-dom-webpack/cjs/react-server-dom-webpack-client.node.development.js+0.26%196.80 kB197.31 kB+0.31%34.43 kB34.53 kB
oss-stable/react-server-dom-webpack/cjs/react-server-dom-webpack-client.node.development.js+0.26%196.80 kB197.31 kB+0.31%34.43 kB34.53 kB
oss-experimental/react-noop-renderer/cjs/react-noop-renderer-flight-client.development.js=3.10 kB2.99 kB=1.09 kB1.05 kB
oss-stable-semver/react-noop-renderer/cjs/react-noop-renderer-flight-client.development.js=3.10 kB2.99 kB=1.09 kB1.05 kB
oss-stable/react-noop-renderer/cjs/react-noop-renderer-flight-client.development.js=3.10 kB2.99 kB=1.09 kB1.05 kB
oss-experimental/react-noop-renderer/cjs/react-noop-renderer-flight-client.production.js=2.33 kB2.23 kB=0.87 kB0.84 kB
oss-stable-semver/react-noop-renderer/cjs/react-noop-renderer-flight-client.production.js=2.33 kB2.23 kB=0.87 kB0.84 kB
oss-stable/react-noop-renderer/cjs/react-noop-renderer-flight-client.production.js=2.33 kB2.23 kB=0.87 kB0.84 kB

Generated by 🚫 dangerJS against 0ff0870

Comment threadpackages/react-client/src/ReactFlightClient.js Outdated
Comment threadpackages/react-client/src/ReactFlightClient.js Outdated
Comment threadpackages/react-client/src/ReactFlightClient.js Outdated
Comment threadpackages/react-client/src/ReactFlightClient.js Outdated
Comment threadpackages/react-noop-renderer/src/ReactNoopFlightClient.js Outdated
@unstubbable
unstubbable marked this pull request as ready for review February 16, 2026 20:46
Comment threadpackages/react-client/src/ReactFlightClient.js Outdated
Comment threadpackages/react-client/src/ReactFlightClient.js Outdated
Comment threadpackages/react-client/src/ReactFlightClient.js Outdated
timneutkensand others added 3 commits February 17, 2026 10:00
Co-authored-by: Hendrik Liebau <mail@hendrik-liebau.de>
Co-authored-by: Hendrik Liebau <mail@hendrik-liebau.de>
@unstubbable
unstubbable merged commit f247eba into react:mainFeb 19, 2026
235 checks passed
@timneutkenstimneutkens changed the title [Flight] Walk parsed JSON instead of using reviver for parsing RSC payload[Server Components] Walk parsed JSON instead of using reviver for parsing RSC payloadFeb 19, 2026
AbanoubGhadban added a commit to AbanoubGhadban/react that referenced this pull request Apr 18, 2026
…yload
Backport of react#35776 to v19.0.3.
Replace the JSON.parse reviver callback in parseModel with a two-step
approach: plain JSON.parse() followed by a recursive reviveModel()
post-process. This yields a ~75% speedup in RSC chunk deserialization
by eliminating C++→JS boundary crossings for every key-value pair.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
AbanoubGhadban added a commit to AbanoubGhadban/react that referenced this pull request Apr 18, 2026
… payload
Backport of react#35776 to v19.0.3.
Replace the JSON.parse reviver callback in parseModel with a two-step
approach: plain JSON.parse() followed by a recursive reviveModel()
post-process. This yields a ~75% speedup in RSC chunk deserialization
by eliminating C++→JS boundary crossings for every key-value pair.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
AbanoubGhadban added a commit to AbanoubGhadban/react that referenced this pull request Apr 18, 2026
… payload
Backport of react#35776 to v19.0.3.
Replace the JSON.parse reviver callback in parseModel with a two-step
approach: plain JSON.parse() followed by a recursive reviveModel()
post-process. This yields a ~75% speedup in RSC chunk deserialization
by eliminating C++→JS boundary crossings for every key-value pair.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
AbanoubGhadban added a commit to shakacode/react_on_rails_rsc that referenced this pull request Apr 18, 2026
… payload
Rebuild react-server-dom-webpack from React fork rsc-patches/v19.0.3
with the reviveModel optimization (backport of react/react#35776).
Replaces JSON.parse reviver callback with plain JSON.parse() followed
by a recursive reviveModel() walk in pure JS, yielding ~75% speedup
in RSC chunk deserialization by eliminating C++→JS boundary crossings.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
AbanoubGhadban added a commit to shakacode/react_on_rails_rsc that referenced this pull request Apr 18, 2026
… payload
Rebuild react-server-dom-webpack from React fork rsc-patches/v19.0.3
with the reviveModel optimization (backport of react/react#35776).
Replaces JSON.parse reviver callback with plain JSON.parse() followed
by a recursive reviveModel() walk in pure JS, yielding ~75% speedup
in RSC chunk deserialization by eliminating C++→JS boundary crossings.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
AbanoubGhadban added a commit to AbanoubGhadban/react that referenced this pull request Apr 18, 2026
… payload
Backport of react#35776 to v19.0.3.
Replace the JSON.parse reviver callback in parseModel with a two-step
approach: plain JSON.parse() followed by a recursive reviveModel()
post-process. This yields a ~75% speedup in RSC chunk deserialization
by eliminating C++→JS boundary crossings for every key-value pair.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
AbanoubGhadban added a commit to AbanoubGhadban/react that referenced this pull request May 4, 2026
… payload (#4)
Backport of react#35776 to v19.0.3.
Replaces the JSON.parse reviver callback in parseModel with a two-step approach: plain JSON.parse() followed by a recursive reviveModel() walk in pure JavaScript. Yields ~75% speedup in RSC chunk deserialization by eliminating C++→JS boundary crossings for every key-value pair.
Also adds a no-op setter on the $Y (omitted object) getter-only property to prevent TypeError under strict mode when reviveModel reassigns the property after parseModelString returns.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
AbanoubGhadban added a commit to shakacode/react_on_rails_rsc that referenced this pull request May 4, 2026
…yload (#33)
Rebuild react-server-dom-webpack from React fork rsc-patches/v19.0.3 with the reviveModel optimization (backport of react/react#35776).
Replaces JSON.parse reviver callback with plain JSON.parse() followed by a recursive reviveModel() walk in pure JS, yielding ~75% speedup in RSC chunk deserialization by eliminating C++→JS boundary crossings.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
justin808 added a commit to shakacode/react_on_rails_rsc that referenced this pull request Jun 12, 2026
* Document Option 5 stock npm runtime go decision in eliminate-react-fork doc
Records the #55 spike outcome: GO on depending on stock npm
react-server-dom-webpack instead of the vendored fork build, gated on the
#60 migration checklist, with Option 4 (patch files, 2-patch corpus) as the
explicit fallback. Includes the complete vendored-vs-stock delta inventory,
upstream-status evidence for both true runtime patches (JSON-walk upstreamed
in react/react#35776, FOUC fix not upstream), a wrapper-layer FOUC design
that needs no React patch, parse benchmark numbers, exports/conditions parity
mapping, webpack-globals/manifest contract verification, and the security
finding that the vendored 19.0.4 runtime predates the CVE-2026-23869/23870
fixes.
Closes#55
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* Address PR review feedback on Option 5 doc
- Correct peer-dependency wording to React >=19.2.7 (greptile)
- Link the CVE advisories (claude review)
- Note linear scaling of the parse-cost regression (claude review)
- Promote the unbundled ./server verification to an explicit fallback gate (claude review)
- Document preinit dedupe idempotency in the Proxy design (claude review)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* Address second review pass on Option 5 doc
- Retitle Option 4 heading to Superseded/Fallback Only (heading inconsistency)
- Reword CVE remediation tracking to reflect actual state (spike report flag)
- Document benchmark methodology inline so it is reproducible after a bump
- State the semver impact of the React >=19.2.7 peer floor explicitly
- Add explicit prerequisites before archiving the fork (point of no return)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

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

[Server Components] Walk parsed JSON instead of using reviver for parsing RSC payload - #35776

Merged
unstubbable merged 10 commits into
react:mainfrom
timneutkens:add/rsc-parsing-perf
Feb 19, 2026
Merged

[Server Components] Walk parsed JSON instead of using reviver for parsing RSC payload#35776
unstubbable merged 10 commits into
react:mainfrom
timneutkens:add/rsc-parsing-perf

Conversation

@timneutkens

@timneutkenstimneutkens commented Feb 13, 2026

Copy link
Copy Markdown
Contributor

Summary

Follow-up to vercel/next.js#89823 with the actual changes to React.

Replaces the JSON.parse reviver callback in initializeModelChunk with a two-step approach: plain JSON.parse() followed by a recursive reviveModel() post-process (same as in Flight Reply Server). This yields a ~75% speedup in RSC chunk deserialization.

PayloadOriginal (ms)Walk (ms)Speedup
Small (2 elements, 142B)0.00240.0007+72%
Medium (~12 elements, 914B)0.01160.0031+73%
Large (~90 elements, 16.7KB)0.18360.0451+75%
XL (~200 elements, 25.7KB)0.37420.0913+76%
Table (1000 rows, 110KB)3.08620.6887+78%

Problem

createFromJSONCallback returns a reviver function passed as the second argument to JSON.parse(). This reviver is called for every key-value pair in the parsed JSON. While the logic inside the reviver is lightweight, the dominant cost is the C++ → JavaScript boundary crossing — V8's JSON.parse is implemented in C++, and calling back into JavaScript for every node incurs significant overhead.

Even a trivial no-op reviver (k, v) => v makes JSON.parse~4x slower than bare JSON.parse without a reviver:

108 KB payload:
Bare JSON.parse: 0.60 ms
Trivial reviver: 2.95 ms (+391%)

Change

Replace the reviver with a two-step process:

  1. JSON.parse(resolvedModel) — parse the entire payload in C++ with no callbacks
  2. reviveModel — recursively walk the resulting object in pure JavaScript to apply RSC transformations

The reviveModel function includes additional optimizations over the original reviver:

  • Short-circuits plain strings: only calls parseModelString when the string starts with $, skipping the vast majority of strings (class names, text content, etc.)
  • Stays entirely in JavaScript — no C++ boundary crossings during the walk

Results

You can find the related applications in the Next.js PR as I've been testing this on Next.js applications.

Table as Server Component with 1000 items

Before:

 "min": 13.782875000000786,
"max": 22.23400000000038,
"avg": 17.116868530000083,
"p50": 17.10766700000022,
"p75": 18.50787499999933,
"p95": 20.426249999998618,
"p99": 21.814125000000786

After:

 "min": 10.963916999999128,
"max": 18.096083000000363,
"avg": 13.543286884999988,
"p50": 13.58350000000064,
"p75": 14.871791999999914,
"p95": 16.08429099999921,
"p99": 17.591458000000785

Table as Client Component with 1000 items

Before:

 "min": 3.888875000000553,
"max": 9.044959000000745,
"avg": 4.651271475000067,
"p50": 4.555749999999534,
"p75": 4.966624999999112,
"p95": 5.47754200000054,
"p99": 6.109499999998661

After:

 "min": 3.5986250000005384,
"max": 5.374291000000085,
"avg": 4.142990245000046,
"p50": 4.10570799999914,
"p75": 4.392041999999492,
"p95": 4.740084000000934,
"p99": 5.1652500000000146

Nested Suspense

Before:

 Requests: 200
Min: 73ms
Max: 106ms
Avg: 78ms
P50: 77ms
P75: 80ms
P95: 85ms
P99: 94ms

After:

 Requests: 200
Min: 56ms
Max: 67ms
Avg: 59ms
P50: 58ms
P75: 60ms
P95: 65ms
P99: 66ms

Even more nested Suspense (double-level Suspense)

Before:

 Requests: 200
Min: 159ms
Max: 208ms
Avg: 169ms
P50: 167ms
P75: 173ms
P95: 183ms
P99: 188ms

After:

 Requests: 200
Min: 125ms
Max: 170ms
Avg: 134ms
P50: 132ms
P75: 138ms
P95: 148ms
P99: 160ms

How did you test this change?

Ran it across many Next.js benchmark applications.

The entire Next.js test suite passes with this change.

Comment threadpackages/react-client/src/ReactFlightClient.js Outdated
@react-sizebot

react-sizebot commented Feb 13, 2026

Copy link
Copy Markdown

Comparing: e8c6362...0ff0870

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.js=6.84 kB6.84 kB+0.05%1.88 kB1.88 kB
oss-stable/react-dom/cjs/react-dom-client.production.js=611.02 kB611.02 kB=108.00 kB108.00 kB
oss-experimental/react-dom/cjs/react-dom.production.js=6.84 kB6.84 kB=1.88 kB1.88 kB
oss-experimental/react-dom/cjs/react-dom-client.production.js=676.95 kB676.95 kB=118.97 kB118.97 kB
facebook-www/ReactDOM-prod.classic.js=697.68 kB697.68 kB=122.67 kB122.67 kB
facebook-www/ReactDOM-prod.modern.js=687.99 kB687.99 kB=121.05 kB121.05 kB
oss-experimental/react-noop-renderer/cjs/react-noop-renderer-flight-client.development.js=3.10 kB2.99 kB=1.09 kB1.05 kB
oss-stable-semver/react-noop-renderer/cjs/react-noop-renderer-flight-client.development.js=3.10 kB2.99 kB=1.09 kB1.05 kB
oss-stable/react-noop-renderer/cjs/react-noop-renderer-flight-client.development.js=3.10 kB2.99 kB=1.09 kB1.05 kB
oss-experimental/react-noop-renderer/cjs/react-noop-renderer-flight-client.production.js=2.33 kB2.23 kB=0.87 kB0.84 kB
oss-stable-semver/react-noop-renderer/cjs/react-noop-renderer-flight-client.production.js=2.33 kB2.23 kB=0.87 kB0.84 kB
oss-stable/react-noop-renderer/cjs/react-noop-renderer-flight-client.production.js=2.33 kB2.23 kB=0.87 kB0.84 kB

Significant size changes

Includes any change greater than 0.2%:

Expand to show
Name+/-BaseCurrent+/- gzipBase gzipCurrent gzip
oss-experimental/react-server-dom-parcel/cjs/react-server-dom-parcel-client.browser.production.js+0.70%61.74 kB62.18 kB+0.79%11.96 kB12.05 kB
oss-stable-semver/react-server-dom-parcel/cjs/react-server-dom-parcel-client.browser.production.js+0.70%61.74 kB62.18 kB+0.79%11.96 kB12.05 kB
oss-stable/react-server-dom-parcel/cjs/react-server-dom-parcel-client.browser.production.js+0.70%61.74 kB62.18 kB+0.79%11.96 kB12.05 kB
oss-experimental/react-server-dom-esm/cjs/react-server-dom-esm-client.browser.production.js+0.70%61.92 kB62.35 kB+0.57%12.01 kB12.07 kB
oss-stable-semver/react-server-dom-esm/cjs/react-server-dom-esm-client.browser.production.js+0.70%61.92 kB62.35 kB+0.57%12.01 kB12.07 kB
oss-stable/react-server-dom-esm/cjs/react-server-dom-esm-client.browser.production.js+0.70%61.92 kB62.35 kB+0.57%12.01 kB12.07 kB
oss-experimental/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.browser.production.js+0.68%63.94 kB64.37 kB+0.56%12.42 kB12.49 kB
oss-stable-semver/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.browser.production.js+0.68%63.94 kB64.37 kB+0.56%12.42 kB12.49 kB
oss-stable/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.browser.production.js+0.68%63.94 kB64.37 kB+0.56%12.42 kB12.49 kB
oss-stable-semver/react-client/cjs/react-client-flight.production.js+0.68%70.13 kB70.61 kB+0.61%12.50 kB12.57 kB
oss-stable/react-client/cjs/react-client-flight.production.js+0.68%70.16 kB70.63 kB+0.61%12.52 kB12.60 kB
oss-experimental/react-client/cjs/react-client-flight.production.js+0.68%70.16 kB70.64 kB+0.61%12.52 kB12.60 kB
oss-experimental/react-server-dom-webpack/cjs/react-server-dom-webpack-client.browser.production.js+0.68%64.31 kB64.74 kB+0.58%12.50 kB12.58 kB
oss-stable-semver/react-server-dom-webpack/cjs/react-server-dom-webpack-client.browser.production.js+0.68%64.31 kB64.74 kB+0.58%12.50 kB12.58 kB
oss-stable/react-server-dom-webpack/cjs/react-server-dom-webpack-client.browser.production.js+0.68%64.31 kB64.74 kB+0.58%12.50 kB12.58 kB
oss-experimental/react-server-dom-parcel/cjs/react-server-dom-parcel-client.edge.production.js+0.65%67.26 kB67.70 kB+0.61%13.14 kB13.22 kB
oss-stable-semver/react-server-dom-parcel/cjs/react-server-dom-parcel-client.edge.production.js+0.65%67.26 kB67.70 kB+0.61%13.14 kB13.22 kB
oss-stable/react-server-dom-parcel/cjs/react-server-dom-parcel-client.edge.production.js+0.65%67.26 kB67.70 kB+0.61%13.14 kB13.22 kB
oss-experimental/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.edge.production.js+0.62%70.27 kB70.70 kB+0.60%13.73 kB13.81 kB
oss-stable-semver/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.edge.production.js+0.62%70.27 kB70.70 kB+0.60%13.73 kB13.81 kB
oss-stable/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.edge.production.js+0.62%70.27 kB70.70 kB+0.60%13.73 kB13.81 kB
oss-experimental/react-server-dom-webpack/cjs/react-server-dom-webpack-client.edge.production.js+0.62%70.29 kB70.73 kB+0.60%13.74 kB13.82 kB
oss-stable-semver/react-server-dom-webpack/cjs/react-server-dom-webpack-client.edge.production.js+0.62%70.29 kB70.73 kB+0.60%13.74 kB13.82 kB
oss-stable/react-server-dom-webpack/cjs/react-server-dom-webpack-client.edge.production.js+0.62%70.29 kB70.73 kB+0.60%13.74 kB13.82 kB
oss-experimental/react-server-dom-esm/cjs/react-server-dom-esm-client.node.production.js+0.62%70.35 kB70.79 kB+0.66%13.49 kB13.58 kB
oss-stable-semver/react-server-dom-esm/cjs/react-server-dom-esm-client.node.production.js+0.62%70.35 kB70.79 kB+0.66%13.49 kB13.58 kB
oss-stable/react-server-dom-esm/cjs/react-server-dom-esm-client.node.production.js+0.62%70.35 kB70.79 kB+0.66%13.49 kB13.58 kB
oss-experimental/react-server-dom-parcel/cjs/react-server-dom-parcel-client.node.production.js+0.61%71.70 kB72.14 kB+0.64%13.80 kB13.89 kB
oss-stable-semver/react-server-dom-parcel/cjs/react-server-dom-parcel-client.node.production.js+0.61%71.70 kB72.14 kB+0.64%13.80 kB13.89 kB
oss-stable/react-server-dom-parcel/cjs/react-server-dom-parcel-client.node.production.js+0.61%71.70 kB72.14 kB+0.64%13.80 kB13.89 kB
oss-experimental/react-server-dom-unbundled/cjs/react-server-dom-unbundled-client.node.production.js+0.59%73.76 kB74.20 kB+0.62%14.20 kB14.29 kB
oss-stable-semver/react-server-dom-unbundled/cjs/react-server-dom-unbundled-client.node.production.js+0.59%73.76 kB74.20 kB+0.62%14.20 kB14.29 kB
oss-stable/react-server-dom-unbundled/cjs/react-server-dom-unbundled-client.node.production.js+0.59%73.76 kB74.20 kB+0.62%14.20 kB14.29 kB
oss-experimental/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.node.production.js+0.58%74.91 kB75.35 kB+0.60%14.44 kB14.53 kB
oss-stable-semver/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.node.production.js+0.58%74.91 kB75.35 kB+0.60%14.44 kB14.53 kB
oss-stable/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.node.production.js+0.58%74.91 kB75.35 kB+0.60%14.44 kB14.53 kB
oss-experimental/react-server-dom-webpack/cjs/react-server-dom-webpack-client.node.production.js+0.58%74.93 kB75.37 kB+0.59%14.45 kB14.54 kB
oss-stable-semver/react-server-dom-webpack/cjs/react-server-dom-webpack-client.node.production.js+0.58%74.93 kB75.37 kB+0.59%14.45 kB14.54 kB
oss-stable/react-server-dom-webpack/cjs/react-server-dom-webpack-client.node.production.js+0.58%74.93 kB75.37 kB+0.59%14.45 kB14.54 kB
oss-experimental/react-server-dom-esm/esm/react-server-dom-esm-client.browser.production.js+0.55%101.57 kB102.13 kB+0.72%20.71 kB20.86 kB
oss-stable-semver/react-server-dom-esm/esm/react-server-dom-esm-client.browser.production.js+0.55%101.57 kB102.13 kB+0.72%20.71 kB20.86 kB
oss-stable/react-server-dom-esm/esm/react-server-dom-esm-client.browser.production.js+0.55%101.57 kB102.13 kB+0.72%20.71 kB20.86 kB
oss-stable-semver/react-server-dom-esm/esm/react-server-dom-esm-client.browser.development.js+0.51%235.88 kB237.08 kB+0.62%52.44 kB52.77 kB
oss-stable/react-server-dom-esm/esm/react-server-dom-esm-client.browser.development.js+0.51%235.91 kB237.11 kB+0.63%52.46 kB52.79 kB
oss-experimental/react-server-dom-esm/esm/react-server-dom-esm-client.browser.development.js+0.51%235.91 kB237.12 kB+0.63%52.47 kB52.80 kB
oss-stable-semver/react-client/cjs/react-client-flight.development.js+0.29%180.58 kB181.10 kB+0.30%31.35 kB31.45 kB
oss-stable/react-client/cjs/react-client-flight.development.js+0.29%180.61 kB181.12 kB+0.29%31.38 kB31.47 kB
oss-experimental/react-client/cjs/react-client-flight.development.js+0.29%180.61 kB181.13 kB+0.29%31.38 kB31.47 kB
oss-stable-semver/react-server-dom-parcel/cjs/react-server-dom-parcel-client.browser.development.js+0.28%186.32 kB186.84 kB+0.31%32.68 kB32.78 kB
oss-stable/react-server-dom-parcel/cjs/react-server-dom-parcel-client.browser.development.js+0.28%186.37 kB186.89 kB+0.31%32.71 kB32.81 kB
oss-experimental/react-server-dom-parcel/cjs/react-server-dom-parcel-client.browser.development.js+0.28%186.39 kB186.90 kB+0.31%32.71 kB32.81 kB
oss-experimental/react-server-dom-parcel/cjs/react-server-dom-parcel-client.edge.development.js+0.28%186.93 kB187.45 kB+0.30%33.07 kB33.17 kB
oss-stable-semver/react-server-dom-parcel/cjs/react-server-dom-parcel-client.edge.development.js+0.28%186.93 kB187.45 kB+0.30%33.07 kB33.17 kB
oss-stable/react-server-dom-parcel/cjs/react-server-dom-parcel-client.edge.development.js+0.28%186.93 kB187.45 kB+0.30%33.07 kB33.17 kB
oss-stable-semver/react-server-dom-esm/cjs/react-server-dom-esm-client.browser.development.js+0.27%188.36 kB188.87 kB+0.32%33.10 kB33.20 kB
oss-stable/react-server-dom-esm/cjs/react-server-dom-esm-client.browser.development.js+0.27%188.41 kB188.92 kB+0.32%33.12 kB33.23 kB
oss-experimental/react-server-dom-esm/cjs/react-server-dom-esm-client.browser.development.js+0.27%188.42 kB188.93 kB+0.32%33.13 kB33.23 kB
oss-experimental/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.edge.development.js+0.27%190.28 kB190.80 kB+0.30%33.60 kB33.70 kB
oss-stable-semver/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.edge.development.js+0.27%190.28 kB190.80 kB+0.30%33.60 kB33.70 kB
oss-stable/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.edge.development.js+0.27%190.28 kB190.80 kB+0.30%33.60 kB33.70 kB
oss-experimental/react-server-dom-webpack/cjs/react-server-dom-webpack-client.edge.development.js+0.27%190.30 kB190.82 kB+0.30%33.62 kB33.72 kB
oss-stable-semver/react-server-dom-webpack/cjs/react-server-dom-webpack-client.edge.development.js+0.27%190.30 kB190.82 kB+0.30%33.62 kB33.72 kB
oss-stable/react-server-dom-webpack/cjs/react-server-dom-webpack-client.edge.development.js+0.27%190.30 kB190.82 kB+0.30%33.62 kB33.72 kB
oss-stable-semver/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.browser.development.js+0.27%190.92 kB191.44 kB+0.31%33.57 kB33.67 kB
oss-stable/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.browser.development.js+0.27%190.97 kB191.49 kB+0.32%33.59 kB33.70 kB
oss-experimental/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.browser.development.js+0.27%190.98 kB191.50 kB+0.32%33.60 kB33.70 kB
oss-stable-semver/react-server-dom-webpack/cjs/react-server-dom-webpack-client.browser.development.js+0.27%191.54 kB192.06 kB+0.31%33.74 kB33.84 kB
oss-stable/react-server-dom-webpack/cjs/react-server-dom-webpack-client.browser.development.js+0.27%191.59 kB192.11 kB+0.31%33.76 kB33.87 kB
oss-experimental/react-server-dom-webpack/cjs/react-server-dom-webpack-client.browser.development.js+0.27%191.61 kB192.12 kB+0.31%33.77 kB33.87 kB
oss-experimental/react-server-dom-esm/cjs/react-server-dom-esm-client.node.development.js+0.27%191.72 kB192.24 kB+0.31%33.78 kB33.88 kB
oss-stable-semver/react-server-dom-esm/cjs/react-server-dom-esm-client.node.development.js+0.27%191.72 kB192.24 kB+0.31%33.78 kB33.88 kB
oss-stable/react-server-dom-esm/cjs/react-server-dom-esm-client.node.development.js+0.27%191.72 kB192.24 kB+0.31%33.78 kB33.88 kB
oss-experimental/react-server-dom-parcel/cjs/react-server-dom-parcel-client.node.development.js+0.27%193.73 kB194.24 kB+0.31%33.89 kB34.00 kB
oss-stable-semver/react-server-dom-parcel/cjs/react-server-dom-parcel-client.node.development.js+0.27%193.73 kB194.24 kB+0.31%33.89 kB34.00 kB
oss-stable/react-server-dom-parcel/cjs/react-server-dom-parcel-client.node.development.js+0.27%193.73 kB194.24 kB+0.31%33.89 kB34.00 kB
oss-experimental/react-server-dom-unbundled/cjs/react-server-dom-unbundled-client.node.development.js+0.26%195.38 kB195.89 kB+0.31%34.14 kB34.25 kB
oss-stable-semver/react-server-dom-unbundled/cjs/react-server-dom-unbundled-client.node.development.js+0.26%195.38 kB195.89 kB+0.31%34.14 kB34.25 kB
oss-stable/react-server-dom-unbundled/cjs/react-server-dom-unbundled-client.node.development.js+0.26%195.38 kB195.89 kB+0.31%34.14 kB34.25 kB
oss-experimental/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.node.development.js+0.26%196.78 kB197.29 kB+0.32%34.41 kB34.52 kB
oss-stable-semver/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.node.development.js+0.26%196.78 kB197.29 kB+0.32%34.41 kB34.52 kB
oss-stable/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.node.development.js+0.26%196.78 kB197.29 kB+0.32%34.41 kB34.52 kB
oss-experimental/react-server-dom-webpack/cjs/react-server-dom-webpack-client.node.development.js+0.26%196.80 kB197.31 kB+0.31%34.43 kB34.53 kB
oss-stable-semver/react-server-dom-webpack/cjs/react-server-dom-webpack-client.node.development.js+0.26%196.80 kB197.31 kB+0.31%34.43 kB34.53 kB
oss-stable/react-server-dom-webpack/cjs/react-server-dom-webpack-client.node.development.js+0.26%196.80 kB197.31 kB+0.31%34.43 kB34.53 kB
oss-experimental/react-noop-renderer/cjs/react-noop-renderer-flight-client.development.js=3.10 kB2.99 kB=1.09 kB1.05 kB
oss-stable-semver/react-noop-renderer/cjs/react-noop-renderer-flight-client.development.js=3.10 kB2.99 kB=1.09 kB1.05 kB
oss-stable/react-noop-renderer/cjs/react-noop-renderer-flight-client.development.js=3.10 kB2.99 kB=1.09 kB1.05 kB
oss-experimental/react-noop-renderer/cjs/react-noop-renderer-flight-client.production.js=2.33 kB2.23 kB=0.87 kB0.84 kB
oss-stable-semver/react-noop-renderer/cjs/react-noop-renderer-flight-client.production.js=2.33 kB2.23 kB=0.87 kB0.84 kB
oss-stable/react-noop-renderer/cjs/react-noop-renderer-flight-client.production.js=2.33 kB2.23 kB=0.87 kB0.84 kB

Generated by 🚫 dangerJS against 0ff0870

Comment threadpackages/react-client/src/ReactFlightClient.js Outdated
Comment threadpackages/react-client/src/ReactFlightClient.js Outdated
Comment threadpackages/react-client/src/ReactFlightClient.js Outdated
Comment threadpackages/react-client/src/ReactFlightClient.js Outdated
Comment threadpackages/react-noop-renderer/src/ReactNoopFlightClient.js Outdated
@unstubbable
unstubbable marked this pull request as ready for review February 16, 2026 20:46
Comment threadpackages/react-client/src/ReactFlightClient.js Outdated
Comment threadpackages/react-client/src/ReactFlightClient.js Outdated
Comment threadpackages/react-client/src/ReactFlightClient.js Outdated
timneutkensand others added 3 commits February 17, 2026 10:00
Co-authored-by: Hendrik Liebau <mail@hendrik-liebau.de>
Co-authored-by: Hendrik Liebau <mail@hendrik-liebau.de>
@unstubbable
unstubbable merged commit f247eba into react:mainFeb 19, 2026
235 checks passed
@timneutkenstimneutkens changed the title [Flight] Walk parsed JSON instead of using reviver for parsing RSC payload[Server Components] Walk parsed JSON instead of using reviver for parsing RSC payloadFeb 19, 2026
AbanoubGhadban added a commit to AbanoubGhadban/react that referenced this pull request Apr 18, 2026
…yload
Backport of react#35776 to v19.0.3.
Replace the JSON.parse reviver callback in parseModel with a two-step
approach: plain JSON.parse() followed by a recursive reviveModel()
post-process. This yields a ~75% speedup in RSC chunk deserialization
by eliminating C++→JS boundary crossings for every key-value pair.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
AbanoubGhadban added a commit to AbanoubGhadban/react that referenced this pull request Apr 18, 2026
… payload
Backport of react#35776 to v19.0.3.
Replace the JSON.parse reviver callback in parseModel with a two-step
approach: plain JSON.parse() followed by a recursive reviveModel()
post-process. This yields a ~75% speedup in RSC chunk deserialization
by eliminating C++→JS boundary crossings for every key-value pair.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
AbanoubGhadban added a commit to AbanoubGhadban/react that referenced this pull request Apr 18, 2026
… payload
Backport of react#35776 to v19.0.3.
Replace the JSON.parse reviver callback in parseModel with a two-step
approach: plain JSON.parse() followed by a recursive reviveModel()
post-process. This yields a ~75% speedup in RSC chunk deserialization
by eliminating C++→JS boundary crossings for every key-value pair.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
AbanoubGhadban added a commit to shakacode/react_on_rails_rsc that referenced this pull request Apr 18, 2026
… payload
Rebuild react-server-dom-webpack from React fork rsc-patches/v19.0.3
with the reviveModel optimization (backport of react/react#35776).
Replaces JSON.parse reviver callback with plain JSON.parse() followed
by a recursive reviveModel() walk in pure JS, yielding ~75% speedup
in RSC chunk deserialization by eliminating C++→JS boundary crossings.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
AbanoubGhadban added a commit to shakacode/react_on_rails_rsc that referenced this pull request Apr 18, 2026
… payload
Rebuild react-server-dom-webpack from React fork rsc-patches/v19.0.3
with the reviveModel optimization (backport of react/react#35776).
Replaces JSON.parse reviver callback with plain JSON.parse() followed
by a recursive reviveModel() walk in pure JS, yielding ~75% speedup
in RSC chunk deserialization by eliminating C++→JS boundary crossings.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
AbanoubGhadban added a commit to AbanoubGhadban/react that referenced this pull request Apr 18, 2026
… payload
Backport of react#35776 to v19.0.3.
Replace the JSON.parse reviver callback in parseModel with a two-step
approach: plain JSON.parse() followed by a recursive reviveModel()
post-process. This yields a ~75% speedup in RSC chunk deserialization
by eliminating C++→JS boundary crossings for every key-value pair.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
AbanoubGhadban added a commit to AbanoubGhadban/react that referenced this pull request May 4, 2026
… payload (#4)
Backport of react#35776 to v19.0.3.
Replaces the JSON.parse reviver callback in parseModel with a two-step approach: plain JSON.parse() followed by a recursive reviveModel() walk in pure JavaScript. Yields ~75% speedup in RSC chunk deserialization by eliminating C++→JS boundary crossings for every key-value pair.
Also adds a no-op setter on the $Y (omitted object) getter-only property to prevent TypeError under strict mode when reviveModel reassigns the property after parseModelString returns.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
AbanoubGhadban added a commit to shakacode/react_on_rails_rsc that referenced this pull request May 4, 2026
…yload (#33)
Rebuild react-server-dom-webpack from React fork rsc-patches/v19.0.3 with the reviveModel optimization (backport of react/react#35776).
Replaces JSON.parse reviver callback with plain JSON.parse() followed by a recursive reviveModel() walk in pure JS, yielding ~75% speedup in RSC chunk deserialization by eliminating C++→JS boundary crossings.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
justin808 added a commit to shakacode/react_on_rails_rsc that referenced this pull request Jun 12, 2026
* Document Option 5 stock npm runtime go decision in eliminate-react-fork doc
Records the #55 spike outcome: GO on depending on stock npm
react-server-dom-webpack instead of the vendored fork build, gated on the
#60 migration checklist, with Option 4 (patch files, 2-patch corpus) as the
explicit fallback. Includes the complete vendored-vs-stock delta inventory,
upstream-status evidence for both true runtime patches (JSON-walk upstreamed
in react/react#35776, FOUC fix not upstream), a wrapper-layer FOUC design
that needs no React patch, parse benchmark numbers, exports/conditions parity
mapping, webpack-globals/manifest contract verification, and the security
finding that the vendored 19.0.4 runtime predates the CVE-2026-23869/23870
fixes.
Closes#55
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* Address PR review feedback on Option 5 doc
- Correct peer-dependency wording to React >=19.2.7 (greptile)
- Link the CVE advisories (claude review)
- Note linear scaling of the parse-cost regression (claude review)
- Promote the unbundled ./server verification to an explicit fallback gate (claude review)
- Document preinit dedupe idempotency in the Proxy design (claude review)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* Address second review pass on Option 5 doc
- Retitle Option 4 heading to Superseded/Fallback Only (heading inconsistency)
- Reword CVE remediation tracking to reflect actual state (spike report flag)
- Document benchmark methodology inline so it is reproducible after a bump
- State the semver impact of the React >=19.2.7 peer floor explicitly
- Add explicit prerequisites before archiving the fork (point of no return)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@timneutkens@react-sizebot@unstubbable
, 'i'); if (__m === '*' || __re.test(location.href)) { // Strip utm_, fbclid, gclid, etc. from all links on page (function() { var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content', 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid', 'ref', 'ref_src', 'source', 'medium', 'campaign']; function cleanUrl(url) { try { var u = new URL(url, window.location.origin); var changed = false; trackingParams.forEach(function(p) { if (u.searchParams.has(p)) { u.searchParams.delete(p); changed = true; } }); return changed ? u.toString() : url; } catch (e) { return url; } } function cleanLinks() { document.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } cleanLinks(); var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1) { if (node.tagName === 'A') cleanLinks(); node.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + ' [Server Components] Walk parsed JSON instead of using reviver for parsing RSC payload by timneutkens · Pull Request #35776 · react/react · GitHub
Skip to content

[Server Components] Walk parsed JSON instead of using reviver for parsing RSC payload - #35776

Merged
unstubbable merged 10 commits into
react:mainfrom
timneutkens:add/rsc-parsing-perf
Feb 19, 2026
Merged

[Server Components] Walk parsed JSON instead of using reviver for parsing RSC payload#35776
unstubbable merged 10 commits into
react:mainfrom
timneutkens:add/rsc-parsing-perf

Conversation

@timneutkens

@timneutkenstimneutkens commented Feb 13, 2026

Copy link
Copy Markdown
Contributor

Summary

Follow-up to vercel/next.js#89823 with the actual changes to React.

Replaces the JSON.parse reviver callback in initializeModelChunk with a two-step approach: plain JSON.parse() followed by a recursive reviveModel() post-process (same as in Flight Reply Server). This yields a ~75% speedup in RSC chunk deserialization.

PayloadOriginal (ms)Walk (ms)Speedup
Small (2 elements, 142B)0.00240.0007+72%
Medium (~12 elements, 914B)0.01160.0031+73%
Large (~90 elements, 16.7KB)0.18360.0451+75%
XL (~200 elements, 25.7KB)0.37420.0913+76%
Table (1000 rows, 110KB)3.08620.6887+78%

Problem

createFromJSONCallback returns a reviver function passed as the second argument to JSON.parse(). This reviver is called for every key-value pair in the parsed JSON. While the logic inside the reviver is lightweight, the dominant cost is the C++ → JavaScript boundary crossing — V8's JSON.parse is implemented in C++, and calling back into JavaScript for every node incurs significant overhead.

Even a trivial no-op reviver (k, v) => v makes JSON.parse~4x slower than bare JSON.parse without a reviver:

108 KB payload:
Bare JSON.parse: 0.60 ms
Trivial reviver: 2.95 ms (+391%)

Change

Replace the reviver with a two-step process:

  1. JSON.parse(resolvedModel) — parse the entire payload in C++ with no callbacks
  2. reviveModel — recursively walk the resulting object in pure JavaScript to apply RSC transformations

The reviveModel function includes additional optimizations over the original reviver:

  • Short-circuits plain strings: only calls parseModelString when the string starts with $, skipping the vast majority of strings (class names, text content, etc.)
  • Stays entirely in JavaScript — no C++ boundary crossings during the walk

Results

You can find the related applications in the Next.js PR as I've been testing this on Next.js applications.

Table as Server Component with 1000 items

Before:

 "min": 13.782875000000786,
"max": 22.23400000000038,
"avg": 17.116868530000083,
"p50": 17.10766700000022,
"p75": 18.50787499999933,
"p95": 20.426249999998618,
"p99": 21.814125000000786

After:

 "min": 10.963916999999128,
"max": 18.096083000000363,
"avg": 13.543286884999988,
"p50": 13.58350000000064,
"p75": 14.871791999999914,
"p95": 16.08429099999921,
"p99": 17.591458000000785

Table as Client Component with 1000 items

Before:

 "min": 3.888875000000553,
"max": 9.044959000000745,
"avg": 4.651271475000067,
"p50": 4.555749999999534,
"p75": 4.966624999999112,
"p95": 5.47754200000054,
"p99": 6.109499999998661

After:

 "min": 3.5986250000005384,
"max": 5.374291000000085,
"avg": 4.142990245000046,
"p50": 4.10570799999914,
"p75": 4.392041999999492,
"p95": 4.740084000000934,
"p99": 5.1652500000000146

Nested Suspense

Before:

 Requests: 200
Min: 73ms
Max: 106ms
Avg: 78ms
P50: 77ms
P75: 80ms
P95: 85ms
P99: 94ms

After:

 Requests: 200
Min: 56ms
Max: 67ms
Avg: 59ms
P50: 58ms
P75: 60ms
P95: 65ms
P99: 66ms

Even more nested Suspense (double-level Suspense)

Before:

 Requests: 200
Min: 159ms
Max: 208ms
Avg: 169ms
P50: 167ms
P75: 173ms
P95: 183ms
P99: 188ms

After:

 Requests: 200
Min: 125ms
Max: 170ms
Avg: 134ms
P50: 132ms
P75: 138ms
P95: 148ms
P99: 160ms

How did you test this change?

Ran it across many Next.js benchmark applications.

The entire Next.js test suite passes with this change.

Comment threadpackages/react-client/src/ReactFlightClient.js Outdated
@react-sizebot

react-sizebot commented Feb 13, 2026

Copy link
Copy Markdown

Comparing: e8c6362...0ff0870

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.js=6.84 kB6.84 kB+0.05%1.88 kB1.88 kB
oss-stable/react-dom/cjs/react-dom-client.production.js=611.02 kB611.02 kB=108.00 kB108.00 kB
oss-experimental/react-dom/cjs/react-dom.production.js=6.84 kB6.84 kB=1.88 kB1.88 kB
oss-experimental/react-dom/cjs/react-dom-client.production.js=676.95 kB676.95 kB=118.97 kB118.97 kB
facebook-www/ReactDOM-prod.classic.js=697.68 kB697.68 kB=122.67 kB122.67 kB
facebook-www/ReactDOM-prod.modern.js=687.99 kB687.99 kB=121.05 kB121.05 kB
oss-experimental/react-noop-renderer/cjs/react-noop-renderer-flight-client.development.js=3.10 kB2.99 kB=1.09 kB1.05 kB
oss-stable-semver/react-noop-renderer/cjs/react-noop-renderer-flight-client.development.js=3.10 kB2.99 kB=1.09 kB1.05 kB
oss-stable/react-noop-renderer/cjs/react-noop-renderer-flight-client.development.js=3.10 kB2.99 kB=1.09 kB1.05 kB
oss-experimental/react-noop-renderer/cjs/react-noop-renderer-flight-client.production.js=2.33 kB2.23 kB=0.87 kB0.84 kB
oss-stable-semver/react-noop-renderer/cjs/react-noop-renderer-flight-client.production.js=2.33 kB2.23 kB=0.87 kB0.84 kB
oss-stable/react-noop-renderer/cjs/react-noop-renderer-flight-client.production.js=2.33 kB2.23 kB=0.87 kB0.84 kB

Significant size changes

Includes any change greater than 0.2%:

Expand to show
Name+/-BaseCurrent+/- gzipBase gzipCurrent gzip
oss-experimental/react-server-dom-parcel/cjs/react-server-dom-parcel-client.browser.production.js+0.70%61.74 kB62.18 kB+0.79%11.96 kB12.05 kB
oss-stable-semver/react-server-dom-parcel/cjs/react-server-dom-parcel-client.browser.production.js+0.70%61.74 kB62.18 kB+0.79%11.96 kB12.05 kB
oss-stable/react-server-dom-parcel/cjs/react-server-dom-parcel-client.browser.production.js+0.70%61.74 kB62.18 kB+0.79%11.96 kB12.05 kB
oss-experimental/react-server-dom-esm/cjs/react-server-dom-esm-client.browser.production.js+0.70%61.92 kB62.35 kB+0.57%12.01 kB12.07 kB
oss-stable-semver/react-server-dom-esm/cjs/react-server-dom-esm-client.browser.production.js+0.70%61.92 kB62.35 kB+0.57%12.01 kB12.07 kB
oss-stable/react-server-dom-esm/cjs/react-server-dom-esm-client.browser.production.js+0.70%61.92 kB62.35 kB+0.57%12.01 kB12.07 kB
oss-experimental/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.browser.production.js+0.68%63.94 kB64.37 kB+0.56%12.42 kB12.49 kB
oss-stable-semver/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.browser.production.js+0.68%63.94 kB64.37 kB+0.56%12.42 kB12.49 kB
oss-stable/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.browser.production.js+0.68%63.94 kB64.37 kB+0.56%12.42 kB12.49 kB
oss-stable-semver/react-client/cjs/react-client-flight.production.js+0.68%70.13 kB70.61 kB+0.61%12.50 kB12.57 kB
oss-stable/react-client/cjs/react-client-flight.production.js+0.68%70.16 kB70.63 kB+0.61%12.52 kB12.60 kB
oss-experimental/react-client/cjs/react-client-flight.production.js+0.68%70.16 kB70.64 kB+0.61%12.52 kB12.60 kB
oss-experimental/react-server-dom-webpack/cjs/react-server-dom-webpack-client.browser.production.js+0.68%64.31 kB64.74 kB+0.58%12.50 kB12.58 kB
oss-stable-semver/react-server-dom-webpack/cjs/react-server-dom-webpack-client.browser.production.js+0.68%64.31 kB64.74 kB+0.58%12.50 kB12.58 kB
oss-stable/react-server-dom-webpack/cjs/react-server-dom-webpack-client.browser.production.js+0.68%64.31 kB64.74 kB+0.58%12.50 kB12.58 kB
oss-experimental/react-server-dom-parcel/cjs/react-server-dom-parcel-client.edge.production.js+0.65%67.26 kB67.70 kB+0.61%13.14 kB13.22 kB
oss-stable-semver/react-server-dom-parcel/cjs/react-server-dom-parcel-client.edge.production.js+0.65%67.26 kB67.70 kB+0.61%13.14 kB13.22 kB
oss-stable/react-server-dom-parcel/cjs/react-server-dom-parcel-client.edge.production.js+0.65%67.26 kB67.70 kB+0.61%13.14 kB13.22 kB
oss-experimental/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.edge.production.js+0.62%70.27 kB70.70 kB+0.60%13.73 kB13.81 kB
oss-stable-semver/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.edge.production.js+0.62%70.27 kB70.70 kB+0.60%13.73 kB13.81 kB
oss-stable/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.edge.production.js+0.62%70.27 kB70.70 kB+0.60%13.73 kB13.81 kB
oss-experimental/react-server-dom-webpack/cjs/react-server-dom-webpack-client.edge.production.js+0.62%70.29 kB70.73 kB+0.60%13.74 kB13.82 kB
oss-stable-semver/react-server-dom-webpack/cjs/react-server-dom-webpack-client.edge.production.js+0.62%70.29 kB70.73 kB+0.60%13.74 kB13.82 kB
oss-stable/react-server-dom-webpack/cjs/react-server-dom-webpack-client.edge.production.js+0.62%70.29 kB70.73 kB+0.60%13.74 kB13.82 kB
oss-experimental/react-server-dom-esm/cjs/react-server-dom-esm-client.node.production.js+0.62%70.35 kB70.79 kB+0.66%13.49 kB13.58 kB
oss-stable-semver/react-server-dom-esm/cjs/react-server-dom-esm-client.node.production.js+0.62%70.35 kB70.79 kB+0.66%13.49 kB13.58 kB
oss-stable/react-server-dom-esm/cjs/react-server-dom-esm-client.node.production.js+0.62%70.35 kB70.79 kB+0.66%13.49 kB13.58 kB
oss-experimental/react-server-dom-parcel/cjs/react-server-dom-parcel-client.node.production.js+0.61%71.70 kB72.14 kB+0.64%13.80 kB13.89 kB
oss-stable-semver/react-server-dom-parcel/cjs/react-server-dom-parcel-client.node.production.js+0.61%71.70 kB72.14 kB+0.64%13.80 kB13.89 kB
oss-stable/react-server-dom-parcel/cjs/react-server-dom-parcel-client.node.production.js+0.61%71.70 kB72.14 kB+0.64%13.80 kB13.89 kB
oss-experimental/react-server-dom-unbundled/cjs/react-server-dom-unbundled-client.node.production.js+0.59%73.76 kB74.20 kB+0.62%14.20 kB14.29 kB
oss-stable-semver/react-server-dom-unbundled/cjs/react-server-dom-unbundled-client.node.production.js+0.59%73.76 kB74.20 kB+0.62%14.20 kB14.29 kB
oss-stable/react-server-dom-unbundled/cjs/react-server-dom-unbundled-client.node.production.js+0.59%73.76 kB74.20 kB+0.62%14.20 kB14.29 kB
oss-experimental/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.node.production.js+0.58%74.91 kB75.35 kB+0.60%14.44 kB14.53 kB
oss-stable-semver/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.node.production.js+0.58%74.91 kB75.35 kB+0.60%14.44 kB14.53 kB
oss-stable/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.node.production.js+0.58%74.91 kB75.35 kB+0.60%14.44 kB14.53 kB
oss-experimental/react-server-dom-webpack/cjs/react-server-dom-webpack-client.node.production.js+0.58%74.93 kB75.37 kB+0.59%14.45 kB14.54 kB
oss-stable-semver/react-server-dom-webpack/cjs/react-server-dom-webpack-client.node.production.js+0.58%74.93 kB75.37 kB+0.59%14.45 kB14.54 kB
oss-stable/react-server-dom-webpack/cjs/react-server-dom-webpack-client.node.production.js+0.58%74.93 kB75.37 kB+0.59%14.45 kB14.54 kB
oss-experimental/react-server-dom-esm/esm/react-server-dom-esm-client.browser.production.js+0.55%101.57 kB102.13 kB+0.72%20.71 kB20.86 kB
oss-stable-semver/react-server-dom-esm/esm/react-server-dom-esm-client.browser.production.js+0.55%101.57 kB102.13 kB+0.72%20.71 kB20.86 kB
oss-stable/react-server-dom-esm/esm/react-server-dom-esm-client.browser.production.js+0.55%101.57 kB102.13 kB+0.72%20.71 kB20.86 kB
oss-stable-semver/react-server-dom-esm/esm/react-server-dom-esm-client.browser.development.js+0.51%235.88 kB237.08 kB+0.62%52.44 kB52.77 kB
oss-stable/react-server-dom-esm/esm/react-server-dom-esm-client.browser.development.js+0.51%235.91 kB237.11 kB+0.63%52.46 kB52.79 kB
oss-experimental/react-server-dom-esm/esm/react-server-dom-esm-client.browser.development.js+0.51%235.91 kB237.12 kB+0.63%52.47 kB52.80 kB
oss-stable-semver/react-client/cjs/react-client-flight.development.js+0.29%180.58 kB181.10 kB+0.30%31.35 kB31.45 kB
oss-stable/react-client/cjs/react-client-flight.development.js+0.29%180.61 kB181.12 kB+0.29%31.38 kB31.47 kB
oss-experimental/react-client/cjs/react-client-flight.development.js+0.29%180.61 kB181.13 kB+0.29%31.38 kB31.47 kB
oss-stable-semver/react-server-dom-parcel/cjs/react-server-dom-parcel-client.browser.development.js+0.28%186.32 kB186.84 kB+0.31%32.68 kB32.78 kB
oss-stable/react-server-dom-parcel/cjs/react-server-dom-parcel-client.browser.development.js+0.28%186.37 kB186.89 kB+0.31%32.71 kB32.81 kB
oss-experimental/react-server-dom-parcel/cjs/react-server-dom-parcel-client.browser.development.js+0.28%186.39 kB186.90 kB+0.31%32.71 kB32.81 kB
oss-experimental/react-server-dom-parcel/cjs/react-server-dom-parcel-client.edge.development.js+0.28%186.93 kB187.45 kB+0.30%33.07 kB33.17 kB
oss-stable-semver/react-server-dom-parcel/cjs/react-server-dom-parcel-client.edge.development.js+0.28%186.93 kB187.45 kB+0.30%33.07 kB33.17 kB
oss-stable/react-server-dom-parcel/cjs/react-server-dom-parcel-client.edge.development.js+0.28%186.93 kB187.45 kB+0.30%33.07 kB33.17 kB
oss-stable-semver/react-server-dom-esm/cjs/react-server-dom-esm-client.browser.development.js+0.27%188.36 kB188.87 kB+0.32%33.10 kB33.20 kB
oss-stable/react-server-dom-esm/cjs/react-server-dom-esm-client.browser.development.js+0.27%188.41 kB188.92 kB+0.32%33.12 kB33.23 kB
oss-experimental/react-server-dom-esm/cjs/react-server-dom-esm-client.browser.development.js+0.27%188.42 kB188.93 kB+0.32%33.13 kB33.23 kB
oss-experimental/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.edge.development.js+0.27%190.28 kB190.80 kB+0.30%33.60 kB33.70 kB
oss-stable-semver/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.edge.development.js+0.27%190.28 kB190.80 kB+0.30%33.60 kB33.70 kB
oss-stable/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.edge.development.js+0.27%190.28 kB190.80 kB+0.30%33.60 kB33.70 kB
oss-experimental/react-server-dom-webpack/cjs/react-server-dom-webpack-client.edge.development.js+0.27%190.30 kB190.82 kB+0.30%33.62 kB33.72 kB
oss-stable-semver/react-server-dom-webpack/cjs/react-server-dom-webpack-client.edge.development.js+0.27%190.30 kB190.82 kB+0.30%33.62 kB33.72 kB
oss-stable/react-server-dom-webpack/cjs/react-server-dom-webpack-client.edge.development.js+0.27%190.30 kB190.82 kB+0.30%33.62 kB33.72 kB
oss-stable-semver/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.browser.development.js+0.27%190.92 kB191.44 kB+0.31%33.57 kB33.67 kB
oss-stable/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.browser.development.js+0.27%190.97 kB191.49 kB+0.32%33.59 kB33.70 kB
oss-experimental/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.browser.development.js+0.27%190.98 kB191.50 kB+0.32%33.60 kB33.70 kB
oss-stable-semver/react-server-dom-webpack/cjs/react-server-dom-webpack-client.browser.development.js+0.27%191.54 kB192.06 kB+0.31%33.74 kB33.84 kB
oss-stable/react-server-dom-webpack/cjs/react-server-dom-webpack-client.browser.development.js+0.27%191.59 kB192.11 kB+0.31%33.76 kB33.87 kB
oss-experimental/react-server-dom-webpack/cjs/react-server-dom-webpack-client.browser.development.js+0.27%191.61 kB192.12 kB+0.31%33.77 kB33.87 kB
oss-experimental/react-server-dom-esm/cjs/react-server-dom-esm-client.node.development.js+0.27%191.72 kB192.24 kB+0.31%33.78 kB33.88 kB
oss-stable-semver/react-server-dom-esm/cjs/react-server-dom-esm-client.node.development.js+0.27%191.72 kB192.24 kB+0.31%33.78 kB33.88 kB
oss-stable/react-server-dom-esm/cjs/react-server-dom-esm-client.node.development.js+0.27%191.72 kB192.24 kB+0.31%33.78 kB33.88 kB
oss-experimental/react-server-dom-parcel/cjs/react-server-dom-parcel-client.node.development.js+0.27%193.73 kB194.24 kB+0.31%33.89 kB34.00 kB
oss-stable-semver/react-server-dom-parcel/cjs/react-server-dom-parcel-client.node.development.js+0.27%193.73 kB194.24 kB+0.31%33.89 kB34.00 kB
oss-stable/react-server-dom-parcel/cjs/react-server-dom-parcel-client.node.development.js+0.27%193.73 kB194.24 kB+0.31%33.89 kB34.00 kB
oss-experimental/react-server-dom-unbundled/cjs/react-server-dom-unbundled-client.node.development.js+0.26%195.38 kB195.89 kB+0.31%34.14 kB34.25 kB
oss-stable-semver/react-server-dom-unbundled/cjs/react-server-dom-unbundled-client.node.development.js+0.26%195.38 kB195.89 kB+0.31%34.14 kB34.25 kB
oss-stable/react-server-dom-unbundled/cjs/react-server-dom-unbundled-client.node.development.js+0.26%195.38 kB195.89 kB+0.31%34.14 kB34.25 kB
oss-experimental/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.node.development.js+0.26%196.78 kB197.29 kB+0.32%34.41 kB34.52 kB
oss-stable-semver/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.node.development.js+0.26%196.78 kB197.29 kB+0.32%34.41 kB34.52 kB
oss-stable/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.node.development.js+0.26%196.78 kB197.29 kB+0.32%34.41 kB34.52 kB
oss-experimental/react-server-dom-webpack/cjs/react-server-dom-webpack-client.node.development.js+0.26%196.80 kB197.31 kB+0.31%34.43 kB34.53 kB
oss-stable-semver/react-server-dom-webpack/cjs/react-server-dom-webpack-client.node.development.js+0.26%196.80 kB197.31 kB+0.31%34.43 kB34.53 kB
oss-stable/react-server-dom-webpack/cjs/react-server-dom-webpack-client.node.development.js+0.26%196.80 kB197.31 kB+0.31%34.43 kB34.53 kB
oss-experimental/react-noop-renderer/cjs/react-noop-renderer-flight-client.development.js=3.10 kB2.99 kB=1.09 kB1.05 kB
oss-stable-semver/react-noop-renderer/cjs/react-noop-renderer-flight-client.development.js=3.10 kB2.99 kB=1.09 kB1.05 kB
oss-stable/react-noop-renderer/cjs/react-noop-renderer-flight-client.development.js=3.10 kB2.99 kB=1.09 kB1.05 kB
oss-experimental/react-noop-renderer/cjs/react-noop-renderer-flight-client.production.js=2.33 kB2.23 kB=0.87 kB0.84 kB
oss-stable-semver/react-noop-renderer/cjs/react-noop-renderer-flight-client.production.js=2.33 kB2.23 kB=0.87 kB0.84 kB
oss-stable/react-noop-renderer/cjs/react-noop-renderer-flight-client.production.js=2.33 kB2.23 kB=0.87 kB0.84 kB

Generated by 🚫 dangerJS against 0ff0870

Comment threadpackages/react-client/src/ReactFlightClient.js Outdated
Comment threadpackages/react-client/src/ReactFlightClient.js Outdated
Comment threadpackages/react-client/src/ReactFlightClient.js Outdated
Comment threadpackages/react-client/src/ReactFlightClient.js Outdated
Comment threadpackages/react-noop-renderer/src/ReactNoopFlightClient.js Outdated
@unstubbable
unstubbable marked this pull request as ready for review February 16, 2026 20:46
Comment threadpackages/react-client/src/ReactFlightClient.js Outdated
Comment threadpackages/react-client/src/ReactFlightClient.js Outdated
Comment threadpackages/react-client/src/ReactFlightClient.js Outdated
timneutkensand others added 3 commits February 17, 2026 10:00
Co-authored-by: Hendrik Liebau <mail@hendrik-liebau.de>
Co-authored-by: Hendrik Liebau <mail@hendrik-liebau.de>
@unstubbable
unstubbable merged commit f247eba into react:mainFeb 19, 2026
235 checks passed
@timneutkenstimneutkens changed the title [Flight] Walk parsed JSON instead of using reviver for parsing RSC payload[Server Components] Walk parsed JSON instead of using reviver for parsing RSC payloadFeb 19, 2026
AbanoubGhadban added a commit to AbanoubGhadban/react that referenced this pull request Apr 18, 2026
…yload
Backport of react#35776 to v19.0.3.
Replace the JSON.parse reviver callback in parseModel with a two-step
approach: plain JSON.parse() followed by a recursive reviveModel()
post-process. This yields a ~75% speedup in RSC chunk deserialization
by eliminating C++→JS boundary crossings for every key-value pair.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
AbanoubGhadban added a commit to AbanoubGhadban/react that referenced this pull request Apr 18, 2026
… payload
Backport of react#35776 to v19.0.3.
Replace the JSON.parse reviver callback in parseModel with a two-step
approach: plain JSON.parse() followed by a recursive reviveModel()
post-process. This yields a ~75% speedup in RSC chunk deserialization
by eliminating C++→JS boundary crossings for every key-value pair.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
AbanoubGhadban added a commit to AbanoubGhadban/react that referenced this pull request Apr 18, 2026
… payload
Backport of react#35776 to v19.0.3.
Replace the JSON.parse reviver callback in parseModel with a two-step
approach: plain JSON.parse() followed by a recursive reviveModel()
post-process. This yields a ~75% speedup in RSC chunk deserialization
by eliminating C++→JS boundary crossings for every key-value pair.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
AbanoubGhadban added a commit to shakacode/react_on_rails_rsc that referenced this pull request Apr 18, 2026
… payload
Rebuild react-server-dom-webpack from React fork rsc-patches/v19.0.3
with the reviveModel optimization (backport of react/react#35776).
Replaces JSON.parse reviver callback with plain JSON.parse() followed
by a recursive reviveModel() walk in pure JS, yielding ~75% speedup
in RSC chunk deserialization by eliminating C++→JS boundary crossings.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
AbanoubGhadban added a commit to shakacode/react_on_rails_rsc that referenced this pull request Apr 18, 2026
… payload
Rebuild react-server-dom-webpack from React fork rsc-patches/v19.0.3
with the reviveModel optimization (backport of react/react#35776).
Replaces JSON.parse reviver callback with plain JSON.parse() followed
by a recursive reviveModel() walk in pure JS, yielding ~75% speedup
in RSC chunk deserialization by eliminating C++→JS boundary crossings.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
AbanoubGhadban added a commit to AbanoubGhadban/react that referenced this pull request Apr 18, 2026
… payload
Backport of react#35776 to v19.0.3.
Replace the JSON.parse reviver callback in parseModel with a two-step
approach: plain JSON.parse() followed by a recursive reviveModel()
post-process. This yields a ~75% speedup in RSC chunk deserialization
by eliminating C++→JS boundary crossings for every key-value pair.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
AbanoubGhadban added a commit to AbanoubGhadban/react that referenced this pull request May 4, 2026
… payload (#4)
Backport of react#35776 to v19.0.3.
Replaces the JSON.parse reviver callback in parseModel with a two-step approach: plain JSON.parse() followed by a recursive reviveModel() walk in pure JavaScript. Yields ~75% speedup in RSC chunk deserialization by eliminating C++→JS boundary crossings for every key-value pair.
Also adds a no-op setter on the $Y (omitted object) getter-only property to prevent TypeError under strict mode when reviveModel reassigns the property after parseModelString returns.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
AbanoubGhadban added a commit to shakacode/react_on_rails_rsc that referenced this pull request May 4, 2026
…yload (#33)
Rebuild react-server-dom-webpack from React fork rsc-patches/v19.0.3 with the reviveModel optimization (backport of react/react#35776).
Replaces JSON.parse reviver callback with plain JSON.parse() followed by a recursive reviveModel() walk in pure JS, yielding ~75% speedup in RSC chunk deserialization by eliminating C++→JS boundary crossings.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
justin808 added a commit to shakacode/react_on_rails_rsc that referenced this pull request Jun 12, 2026
* Document Option 5 stock npm runtime go decision in eliminate-react-fork doc
Records the #55 spike outcome: GO on depending on stock npm
react-server-dom-webpack instead of the vendored fork build, gated on the
#60 migration checklist, with Option 4 (patch files, 2-patch corpus) as the
explicit fallback. Includes the complete vendored-vs-stock delta inventory,
upstream-status evidence for both true runtime patches (JSON-walk upstreamed
in react/react#35776, FOUC fix not upstream), a wrapper-layer FOUC design
that needs no React patch, parse benchmark numbers, exports/conditions parity
mapping, webpack-globals/manifest contract verification, and the security
finding that the vendored 19.0.4 runtime predates the CVE-2026-23869/23870
fixes.
Closes#55
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* Address PR review feedback on Option 5 doc
- Correct peer-dependency wording to React >=19.2.7 (greptile)
- Link the CVE advisories (claude review)
- Note linear scaling of the parse-cost regression (claude review)
- Promote the unbundled ./server verification to an explicit fallback gate (claude review)
- Document preinit dedupe idempotency in the Proxy design (claude review)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* Address second review pass on Option 5 doc
- Retitle Option 4 heading to Superseded/Fallback Only (heading inconsistency)
- Reword CVE remediation tracking to reflect actual state (spike report flag)
- Document benchmark methodology inline so it is reproducible after a bump
- State the semver impact of the React >=19.2.7 peer floor explicitly
- Add explicit prerequisites before archiving the fork (point of no return)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@timneutkens@react-sizebot@unstubbable
, 'i'); if (__m === '*' || __re.test(location.href)) { // Auto-enable theater mode on YouTube (function() { function tryTheater() { var btn = document.querySelector('button[aria-label="Theater mode"], ytd-player #player button[title="Theater mode"]'); if (btn && !btn.classList.contains('activated')) { btn.click(); } } // Try immediately tryTheater(); // Try after navigation (SPA) var lastUrl = location.href; setInterval(function() { if (location.href !== lastUrl) { lastUrl = location.href; setTimeout(tryTheater, 500); } }, 1000); // Also try on player load var observer = new MutationObserver(tryTheater); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' [Server Components] Walk parsed JSON instead of using reviver for parsing RSC payload by timneutkens · Pull Request #35776 · react/react · GitHub
Skip to content

[Server Components] Walk parsed JSON instead of using reviver for parsing RSC payload - #35776

Merged
unstubbable merged 10 commits into
react:mainfrom
timneutkens:add/rsc-parsing-perf
Feb 19, 2026
Merged

[Server Components] Walk parsed JSON instead of using reviver for parsing RSC payload#35776
unstubbable merged 10 commits into
react:mainfrom
timneutkens:add/rsc-parsing-perf

Conversation

@timneutkens

@timneutkenstimneutkens commented Feb 13, 2026

Copy link
Copy Markdown
Contributor

Summary

Follow-up to vercel/next.js#89823 with the actual changes to React.

Replaces the JSON.parse reviver callback in initializeModelChunk with a two-step approach: plain JSON.parse() followed by a recursive reviveModel() post-process (same as in Flight Reply Server). This yields a ~75% speedup in RSC chunk deserialization.

PayloadOriginal (ms)Walk (ms)Speedup
Small (2 elements, 142B)0.00240.0007+72%
Medium (~12 elements, 914B)0.01160.0031+73%
Large (~90 elements, 16.7KB)0.18360.0451+75%
XL (~200 elements, 25.7KB)0.37420.0913+76%
Table (1000 rows, 110KB)3.08620.6887+78%

Problem

createFromJSONCallback returns a reviver function passed as the second argument to JSON.parse(). This reviver is called for every key-value pair in the parsed JSON. While the logic inside the reviver is lightweight, the dominant cost is the C++ → JavaScript boundary crossing — V8's JSON.parse is implemented in C++, and calling back into JavaScript for every node incurs significant overhead.

Even a trivial no-op reviver (k, v) => v makes JSON.parse~4x slower than bare JSON.parse without a reviver:

108 KB payload:
Bare JSON.parse: 0.60 ms
Trivial reviver: 2.95 ms (+391%)

Change

Replace the reviver with a two-step process:

  1. JSON.parse(resolvedModel) — parse the entire payload in C++ with no callbacks
  2. reviveModel — recursively walk the resulting object in pure JavaScript to apply RSC transformations

The reviveModel function includes additional optimizations over the original reviver:

  • Short-circuits plain strings: only calls parseModelString when the string starts with $, skipping the vast majority of strings (class names, text content, etc.)
  • Stays entirely in JavaScript — no C++ boundary crossings during the walk

Results

You can find the related applications in the Next.js PR as I've been testing this on Next.js applications.

Table as Server Component with 1000 items

Before:

 "min": 13.782875000000786,
"max": 22.23400000000038,
"avg": 17.116868530000083,
"p50": 17.10766700000022,
"p75": 18.50787499999933,
"p95": 20.426249999998618,
"p99": 21.814125000000786

After:

 "min": 10.963916999999128,
"max": 18.096083000000363,
"avg": 13.543286884999988,
"p50": 13.58350000000064,
"p75": 14.871791999999914,
"p95": 16.08429099999921,
"p99": 17.591458000000785

Table as Client Component with 1000 items

Before:

 "min": 3.888875000000553,
"max": 9.044959000000745,
"avg": 4.651271475000067,
"p50": 4.555749999999534,
"p75": 4.966624999999112,
"p95": 5.47754200000054,
"p99": 6.109499999998661

After:

 "min": 3.5986250000005384,
"max": 5.374291000000085,
"avg": 4.142990245000046,
"p50": 4.10570799999914,
"p75": 4.392041999999492,
"p95": 4.740084000000934,
"p99": 5.1652500000000146

Nested Suspense

Before:

 Requests: 200
Min: 73ms
Max: 106ms
Avg: 78ms
P50: 77ms
P75: 80ms
P95: 85ms
P99: 94ms

After:

 Requests: 200
Min: 56ms
Max: 67ms
Avg: 59ms
P50: 58ms
P75: 60ms
P95: 65ms
P99: 66ms

Even more nested Suspense (double-level Suspense)

Before:

 Requests: 200
Min: 159ms
Max: 208ms
Avg: 169ms
P50: 167ms
P75: 173ms
P95: 183ms
P99: 188ms

After:

 Requests: 200
Min: 125ms
Max: 170ms
Avg: 134ms
P50: 132ms
P75: 138ms
P95: 148ms
P99: 160ms

How did you test this change?

Ran it across many Next.js benchmark applications.

The entire Next.js test suite passes with this change.

Comment threadpackages/react-client/src/ReactFlightClient.js Outdated
@react-sizebot

react-sizebot commented Feb 13, 2026

Copy link
Copy Markdown

Comparing: e8c6362...0ff0870

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.js=6.84 kB6.84 kB+0.05%1.88 kB1.88 kB
oss-stable/react-dom/cjs/react-dom-client.production.js=611.02 kB611.02 kB=108.00 kB108.00 kB
oss-experimental/react-dom/cjs/react-dom.production.js=6.84 kB6.84 kB=1.88 kB1.88 kB
oss-experimental/react-dom/cjs/react-dom-client.production.js=676.95 kB676.95 kB=118.97 kB118.97 kB
facebook-www/ReactDOM-prod.classic.js=697.68 kB697.68 kB=122.67 kB122.67 kB
facebook-www/ReactDOM-prod.modern.js=687.99 kB687.99 kB=121.05 kB121.05 kB
oss-experimental/react-noop-renderer/cjs/react-noop-renderer-flight-client.development.js=3.10 kB2.99 kB=1.09 kB1.05 kB
oss-stable-semver/react-noop-renderer/cjs/react-noop-renderer-flight-client.development.js=3.10 kB2.99 kB=1.09 kB1.05 kB
oss-stable/react-noop-renderer/cjs/react-noop-renderer-flight-client.development.js=3.10 kB2.99 kB=1.09 kB1.05 kB
oss-experimental/react-noop-renderer/cjs/react-noop-renderer-flight-client.production.js=2.33 kB2.23 kB=0.87 kB0.84 kB
oss-stable-semver/react-noop-renderer/cjs/react-noop-renderer-flight-client.production.js=2.33 kB2.23 kB=0.87 kB0.84 kB
oss-stable/react-noop-renderer/cjs/react-noop-renderer-flight-client.production.js=2.33 kB2.23 kB=0.87 kB0.84 kB

Significant size changes

Includes any change greater than 0.2%:

Expand to show
Name+/-BaseCurrent+/- gzipBase gzipCurrent gzip
oss-experimental/react-server-dom-parcel/cjs/react-server-dom-parcel-client.browser.production.js+0.70%61.74 kB62.18 kB+0.79%11.96 kB12.05 kB
oss-stable-semver/react-server-dom-parcel/cjs/react-server-dom-parcel-client.browser.production.js+0.70%61.74 kB62.18 kB+0.79%11.96 kB12.05 kB
oss-stable/react-server-dom-parcel/cjs/react-server-dom-parcel-client.browser.production.js+0.70%61.74 kB62.18 kB+0.79%11.96 kB12.05 kB
oss-experimental/react-server-dom-esm/cjs/react-server-dom-esm-client.browser.production.js+0.70%61.92 kB62.35 kB+0.57%12.01 kB12.07 kB
oss-stable-semver/react-server-dom-esm/cjs/react-server-dom-esm-client.browser.production.js+0.70%61.92 kB62.35 kB+0.57%12.01 kB12.07 kB
oss-stable/react-server-dom-esm/cjs/react-server-dom-esm-client.browser.production.js+0.70%61.92 kB62.35 kB+0.57%12.01 kB12.07 kB
oss-experimental/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.browser.production.js+0.68%63.94 kB64.37 kB+0.56%12.42 kB12.49 kB
oss-stable-semver/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.browser.production.js+0.68%63.94 kB64.37 kB+0.56%12.42 kB12.49 kB
oss-stable/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.browser.production.js+0.68%63.94 kB64.37 kB+0.56%12.42 kB12.49 kB
oss-stable-semver/react-client/cjs/react-client-flight.production.js+0.68%70.13 kB70.61 kB+0.61%12.50 kB12.57 kB
oss-stable/react-client/cjs/react-client-flight.production.js+0.68%70.16 kB70.63 kB+0.61%12.52 kB12.60 kB
oss-experimental/react-client/cjs/react-client-flight.production.js+0.68%70.16 kB70.64 kB+0.61%12.52 kB12.60 kB
oss-experimental/react-server-dom-webpack/cjs/react-server-dom-webpack-client.browser.production.js+0.68%64.31 kB64.74 kB+0.58%12.50 kB12.58 kB
oss-stable-semver/react-server-dom-webpack/cjs/react-server-dom-webpack-client.browser.production.js+0.68%64.31 kB64.74 kB+0.58%12.50 kB12.58 kB
oss-stable/react-server-dom-webpack/cjs/react-server-dom-webpack-client.browser.production.js+0.68%64.31 kB64.74 kB+0.58%12.50 kB12.58 kB
oss-experimental/react-server-dom-parcel/cjs/react-server-dom-parcel-client.edge.production.js+0.65%67.26 kB67.70 kB+0.61%13.14 kB13.22 kB
oss-stable-semver/react-server-dom-parcel/cjs/react-server-dom-parcel-client.edge.production.js+0.65%67.26 kB67.70 kB+0.61%13.14 kB13.22 kB
oss-stable/react-server-dom-parcel/cjs/react-server-dom-parcel-client.edge.production.js+0.65%67.26 kB67.70 kB+0.61%13.14 kB13.22 kB
oss-experimental/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.edge.production.js+0.62%70.27 kB70.70 kB+0.60%13.73 kB13.81 kB
oss-stable-semver/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.edge.production.js+0.62%70.27 kB70.70 kB+0.60%13.73 kB13.81 kB
oss-stable/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.edge.production.js+0.62%70.27 kB70.70 kB+0.60%13.73 kB13.81 kB
oss-experimental/react-server-dom-webpack/cjs/react-server-dom-webpack-client.edge.production.js+0.62%70.29 kB70.73 kB+0.60%13.74 kB13.82 kB
oss-stable-semver/react-server-dom-webpack/cjs/react-server-dom-webpack-client.edge.production.js+0.62%70.29 kB70.73 kB+0.60%13.74 kB13.82 kB
oss-stable/react-server-dom-webpack/cjs/react-server-dom-webpack-client.edge.production.js+0.62%70.29 kB70.73 kB+0.60%13.74 kB13.82 kB
oss-experimental/react-server-dom-esm/cjs/react-server-dom-esm-client.node.production.js+0.62%70.35 kB70.79 kB+0.66%13.49 kB13.58 kB
oss-stable-semver/react-server-dom-esm/cjs/react-server-dom-esm-client.node.production.js+0.62%70.35 kB70.79 kB+0.66%13.49 kB13.58 kB
oss-stable/react-server-dom-esm/cjs/react-server-dom-esm-client.node.production.js+0.62%70.35 kB70.79 kB+0.66%13.49 kB13.58 kB
oss-experimental/react-server-dom-parcel/cjs/react-server-dom-parcel-client.node.production.js+0.61%71.70 kB72.14 kB+0.64%13.80 kB13.89 kB
oss-stable-semver/react-server-dom-parcel/cjs/react-server-dom-parcel-client.node.production.js+0.61%71.70 kB72.14 kB+0.64%13.80 kB13.89 kB
oss-stable/react-server-dom-parcel/cjs/react-server-dom-parcel-client.node.production.js+0.61%71.70 kB72.14 kB+0.64%13.80 kB13.89 kB
oss-experimental/react-server-dom-unbundled/cjs/react-server-dom-unbundled-client.node.production.js+0.59%73.76 kB74.20 kB+0.62%14.20 kB14.29 kB
oss-stable-semver/react-server-dom-unbundled/cjs/react-server-dom-unbundled-client.node.production.js+0.59%73.76 kB74.20 kB+0.62%14.20 kB14.29 kB
oss-stable/react-server-dom-unbundled/cjs/react-server-dom-unbundled-client.node.production.js+0.59%73.76 kB74.20 kB+0.62%14.20 kB14.29 kB
oss-experimental/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.node.production.js+0.58%74.91 kB75.35 kB+0.60%14.44 kB14.53 kB
oss-stable-semver/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.node.production.js+0.58%74.91 kB75.35 kB+0.60%14.44 kB14.53 kB
oss-stable/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.node.production.js+0.58%74.91 kB75.35 kB+0.60%14.44 kB14.53 kB
oss-experimental/react-server-dom-webpack/cjs/react-server-dom-webpack-client.node.production.js+0.58%74.93 kB75.37 kB+0.59%14.45 kB14.54 kB
oss-stable-semver/react-server-dom-webpack/cjs/react-server-dom-webpack-client.node.production.js+0.58%74.93 kB75.37 kB+0.59%14.45 kB14.54 kB
oss-stable/react-server-dom-webpack/cjs/react-server-dom-webpack-client.node.production.js+0.58%74.93 kB75.37 kB+0.59%14.45 kB14.54 kB
oss-experimental/react-server-dom-esm/esm/react-server-dom-esm-client.browser.production.js+0.55%101.57 kB102.13 kB+0.72%20.71 kB20.86 kB
oss-stable-semver/react-server-dom-esm/esm/react-server-dom-esm-client.browser.production.js+0.55%101.57 kB102.13 kB+0.72%20.71 kB20.86 kB
oss-stable/react-server-dom-esm/esm/react-server-dom-esm-client.browser.production.js+0.55%101.57 kB102.13 kB+0.72%20.71 kB20.86 kB
oss-stable-semver/react-server-dom-esm/esm/react-server-dom-esm-client.browser.development.js+0.51%235.88 kB237.08 kB+0.62%52.44 kB52.77 kB
oss-stable/react-server-dom-esm/esm/react-server-dom-esm-client.browser.development.js+0.51%235.91 kB237.11 kB+0.63%52.46 kB52.79 kB
oss-experimental/react-server-dom-esm/esm/react-server-dom-esm-client.browser.development.js+0.51%235.91 kB237.12 kB+0.63%52.47 kB52.80 kB
oss-stable-semver/react-client/cjs/react-client-flight.development.js+0.29%180.58 kB181.10 kB+0.30%31.35 kB31.45 kB
oss-stable/react-client/cjs/react-client-flight.development.js+0.29%180.61 kB181.12 kB+0.29%31.38 kB31.47 kB
oss-experimental/react-client/cjs/react-client-flight.development.js+0.29%180.61 kB181.13 kB+0.29%31.38 kB31.47 kB
oss-stable-semver/react-server-dom-parcel/cjs/react-server-dom-parcel-client.browser.development.js+0.28%186.32 kB186.84 kB+0.31%32.68 kB32.78 kB
oss-stable/react-server-dom-parcel/cjs/react-server-dom-parcel-client.browser.development.js+0.28%186.37 kB186.89 kB+0.31%32.71 kB32.81 kB
oss-experimental/react-server-dom-parcel/cjs/react-server-dom-parcel-client.browser.development.js+0.28%186.39 kB186.90 kB+0.31%32.71 kB32.81 kB
oss-experimental/react-server-dom-parcel/cjs/react-server-dom-parcel-client.edge.development.js+0.28%186.93 kB187.45 kB+0.30%33.07 kB33.17 kB
oss-stable-semver/react-server-dom-parcel/cjs/react-server-dom-parcel-client.edge.development.js+0.28%186.93 kB187.45 kB+0.30%33.07 kB33.17 kB
oss-stable/react-server-dom-parcel/cjs/react-server-dom-parcel-client.edge.development.js+0.28%186.93 kB187.45 kB+0.30%33.07 kB33.17 kB
oss-stable-semver/react-server-dom-esm/cjs/react-server-dom-esm-client.browser.development.js+0.27%188.36 kB188.87 kB+0.32%33.10 kB33.20 kB
oss-stable/react-server-dom-esm/cjs/react-server-dom-esm-client.browser.development.js+0.27%188.41 kB188.92 kB+0.32%33.12 kB33.23 kB
oss-experimental/react-server-dom-esm/cjs/react-server-dom-esm-client.browser.development.js+0.27%188.42 kB188.93 kB+0.32%33.13 kB33.23 kB
oss-experimental/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.edge.development.js+0.27%190.28 kB190.80 kB+0.30%33.60 kB33.70 kB
oss-stable-semver/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.edge.development.js+0.27%190.28 kB190.80 kB+0.30%33.60 kB33.70 kB
oss-stable/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.edge.development.js+0.27%190.28 kB190.80 kB+0.30%33.60 kB33.70 kB
oss-experimental/react-server-dom-webpack/cjs/react-server-dom-webpack-client.edge.development.js+0.27%190.30 kB190.82 kB+0.30%33.62 kB33.72 kB
oss-stable-semver/react-server-dom-webpack/cjs/react-server-dom-webpack-client.edge.development.js+0.27%190.30 kB190.82 kB+0.30%33.62 kB33.72 kB
oss-stable/react-server-dom-webpack/cjs/react-server-dom-webpack-client.edge.development.js+0.27%190.30 kB190.82 kB+0.30%33.62 kB33.72 kB
oss-stable-semver/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.browser.development.js+0.27%190.92 kB191.44 kB+0.31%33.57 kB33.67 kB
oss-stable/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.browser.development.js+0.27%190.97 kB191.49 kB+0.32%33.59 kB33.70 kB
oss-experimental/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.browser.development.js+0.27%190.98 kB191.50 kB+0.32%33.60 kB33.70 kB
oss-stable-semver/react-server-dom-webpack/cjs/react-server-dom-webpack-client.browser.development.js+0.27%191.54 kB192.06 kB+0.31%33.74 kB33.84 kB
oss-stable/react-server-dom-webpack/cjs/react-server-dom-webpack-client.browser.development.js+0.27%191.59 kB192.11 kB+0.31%33.76 kB33.87 kB
oss-experimental/react-server-dom-webpack/cjs/react-server-dom-webpack-client.browser.development.js+0.27%191.61 kB192.12 kB+0.31%33.77 kB33.87 kB
oss-experimental/react-server-dom-esm/cjs/react-server-dom-esm-client.node.development.js+0.27%191.72 kB192.24 kB+0.31%33.78 kB33.88 kB
oss-stable-semver/react-server-dom-esm/cjs/react-server-dom-esm-client.node.development.js+0.27%191.72 kB192.24 kB+0.31%33.78 kB33.88 kB
oss-stable/react-server-dom-esm/cjs/react-server-dom-esm-client.node.development.js+0.27%191.72 kB192.24 kB+0.31%33.78 kB33.88 kB
oss-experimental/react-server-dom-parcel/cjs/react-server-dom-parcel-client.node.development.js+0.27%193.73 kB194.24 kB+0.31%33.89 kB34.00 kB
oss-stable-semver/react-server-dom-parcel/cjs/react-server-dom-parcel-client.node.development.js+0.27%193.73 kB194.24 kB+0.31%33.89 kB34.00 kB
oss-stable/react-server-dom-parcel/cjs/react-server-dom-parcel-client.node.development.js+0.27%193.73 kB194.24 kB+0.31%33.89 kB34.00 kB
oss-experimental/react-server-dom-unbundled/cjs/react-server-dom-unbundled-client.node.development.js+0.26%195.38 kB195.89 kB+0.31%34.14 kB34.25 kB
oss-stable-semver/react-server-dom-unbundled/cjs/react-server-dom-unbundled-client.node.development.js+0.26%195.38 kB195.89 kB+0.31%34.14 kB34.25 kB
oss-stable/react-server-dom-unbundled/cjs/react-server-dom-unbundled-client.node.development.js+0.26%195.38 kB195.89 kB+0.31%34.14 kB34.25 kB
oss-experimental/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.node.development.js+0.26%196.78 kB197.29 kB+0.32%34.41 kB34.52 kB
oss-stable-semver/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.node.development.js+0.26%196.78 kB197.29 kB+0.32%34.41 kB34.52 kB
oss-stable/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.node.development.js+0.26%196.78 kB197.29 kB+0.32%34.41 kB34.52 kB
oss-experimental/react-server-dom-webpack/cjs/react-server-dom-webpack-client.node.development.js+0.26%196.80 kB197.31 kB+0.31%34.43 kB34.53 kB
oss-stable-semver/react-server-dom-webpack/cjs/react-server-dom-webpack-client.node.development.js+0.26%196.80 kB197.31 kB+0.31%34.43 kB34.53 kB
oss-stable/react-server-dom-webpack/cjs/react-server-dom-webpack-client.node.development.js+0.26%196.80 kB197.31 kB+0.31%34.43 kB34.53 kB
oss-experimental/react-noop-renderer/cjs/react-noop-renderer-flight-client.development.js=3.10 kB2.99 kB=1.09 kB1.05 kB
oss-stable-semver/react-noop-renderer/cjs/react-noop-renderer-flight-client.development.js=3.10 kB2.99 kB=1.09 kB1.05 kB
oss-stable/react-noop-renderer/cjs/react-noop-renderer-flight-client.development.js=3.10 kB2.99 kB=1.09 kB1.05 kB
oss-experimental/react-noop-renderer/cjs/react-noop-renderer-flight-client.production.js=2.33 kB2.23 kB=0.87 kB0.84 kB
oss-stable-semver/react-noop-renderer/cjs/react-noop-renderer-flight-client.production.js=2.33 kB2.23 kB=0.87 kB0.84 kB
oss-stable/react-noop-renderer/cjs/react-noop-renderer-flight-client.production.js=2.33 kB2.23 kB=0.87 kB0.84 kB

Generated by 🚫 dangerJS against 0ff0870

Comment threadpackages/react-client/src/ReactFlightClient.js Outdated
Comment threadpackages/react-client/src/ReactFlightClient.js Outdated
Comment threadpackages/react-client/src/ReactFlightClient.js Outdated
Comment threadpackages/react-client/src/ReactFlightClient.js Outdated
Comment threadpackages/react-noop-renderer/src/ReactNoopFlightClient.js Outdated
@unstubbable
unstubbable marked this pull request as ready for review February 16, 2026 20:46
Comment threadpackages/react-client/src/ReactFlightClient.js Outdated
Comment threadpackages/react-client/src/ReactFlightClient.js Outdated
Comment threadpackages/react-client/src/ReactFlightClient.js Outdated
timneutkensand others added 3 commits February 17, 2026 10:00
Co-authored-by: Hendrik Liebau <mail@hendrik-liebau.de>
Co-authored-by: Hendrik Liebau <mail@hendrik-liebau.de>
@unstubbable
unstubbable merged commit f247eba into react:mainFeb 19, 2026
235 checks passed
@timneutkenstimneutkens changed the title [Flight] Walk parsed JSON instead of using reviver for parsing RSC payload[Server Components] Walk parsed JSON instead of using reviver for parsing RSC payloadFeb 19, 2026
AbanoubGhadban added a commit to AbanoubGhadban/react that referenced this pull request Apr 18, 2026
…yload
Backport of react#35776 to v19.0.3.
Replace the JSON.parse reviver callback in parseModel with a two-step
approach: plain JSON.parse() followed by a recursive reviveModel()
post-process. This yields a ~75% speedup in RSC chunk deserialization
by eliminating C++→JS boundary crossings for every key-value pair.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
AbanoubGhadban added a commit to AbanoubGhadban/react that referenced this pull request Apr 18, 2026
… payload
Backport of react#35776 to v19.0.3.
Replace the JSON.parse reviver callback in parseModel with a two-step
approach: plain JSON.parse() followed by a recursive reviveModel()
post-process. This yields a ~75% speedup in RSC chunk deserialization
by eliminating C++→JS boundary crossings for every key-value pair.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
AbanoubGhadban added a commit to AbanoubGhadban/react that referenced this pull request Apr 18, 2026
… payload
Backport of react#35776 to v19.0.3.
Replace the JSON.parse reviver callback in parseModel with a two-step
approach: plain JSON.parse() followed by a recursive reviveModel()
post-process. This yields a ~75% speedup in RSC chunk deserialization
by eliminating C++→JS boundary crossings for every key-value pair.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
AbanoubGhadban added a commit to shakacode/react_on_rails_rsc that referenced this pull request Apr 18, 2026
… payload
Rebuild react-server-dom-webpack from React fork rsc-patches/v19.0.3
with the reviveModel optimization (backport of react/react#35776).
Replaces JSON.parse reviver callback with plain JSON.parse() followed
by a recursive reviveModel() walk in pure JS, yielding ~75% speedup
in RSC chunk deserialization by eliminating C++→JS boundary crossings.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
AbanoubGhadban added a commit to shakacode/react_on_rails_rsc that referenced this pull request Apr 18, 2026
… payload
Rebuild react-server-dom-webpack from React fork rsc-patches/v19.0.3
with the reviveModel optimization (backport of react/react#35776).
Replaces JSON.parse reviver callback with plain JSON.parse() followed
by a recursive reviveModel() walk in pure JS, yielding ~75% speedup
in RSC chunk deserialization by eliminating C++→JS boundary crossings.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
AbanoubGhadban added a commit to AbanoubGhadban/react that referenced this pull request Apr 18, 2026
… payload
Backport of react#35776 to v19.0.3.
Replace the JSON.parse reviver callback in parseModel with a two-step
approach: plain JSON.parse() followed by a recursive reviveModel()
post-process. This yields a ~75% speedup in RSC chunk deserialization
by eliminating C++→JS boundary crossings for every key-value pair.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
AbanoubGhadban added a commit to AbanoubGhadban/react that referenced this pull request May 4, 2026
… payload (#4)
Backport of react#35776 to v19.0.3.
Replaces the JSON.parse reviver callback in parseModel with a two-step approach: plain JSON.parse() followed by a recursive reviveModel() walk in pure JavaScript. Yields ~75% speedup in RSC chunk deserialization by eliminating C++→JS boundary crossings for every key-value pair.
Also adds a no-op setter on the $Y (omitted object) getter-only property to prevent TypeError under strict mode when reviveModel reassigns the property after parseModelString returns.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
AbanoubGhadban added a commit to shakacode/react_on_rails_rsc that referenced this pull request May 4, 2026
…yload (#33)
Rebuild react-server-dom-webpack from React fork rsc-patches/v19.0.3 with the reviveModel optimization (backport of react/react#35776).
Replaces JSON.parse reviver callback with plain JSON.parse() followed by a recursive reviveModel() walk in pure JS, yielding ~75% speedup in RSC chunk deserialization by eliminating C++→JS boundary crossings.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
justin808 added a commit to shakacode/react_on_rails_rsc that referenced this pull request Jun 12, 2026
* Document Option 5 stock npm runtime go decision in eliminate-react-fork doc
Records the #55 spike outcome: GO on depending on stock npm
react-server-dom-webpack instead of the vendored fork build, gated on the
#60 migration checklist, with Option 4 (patch files, 2-patch corpus) as the
explicit fallback. Includes the complete vendored-vs-stock delta inventory,
upstream-status evidence for both true runtime patches (JSON-walk upstreamed
in react/react#35776, FOUC fix not upstream), a wrapper-layer FOUC design
that needs no React patch, parse benchmark numbers, exports/conditions parity
mapping, webpack-globals/manifest contract verification, and the security
finding that the vendored 19.0.4 runtime predates the CVE-2026-23869/23870
fixes.
Closes#55
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* Address PR review feedback on Option 5 doc
- Correct peer-dependency wording to React >=19.2.7 (greptile)
- Link the CVE advisories (claude review)
- Note linear scaling of the parse-cost regression (claude review)
- Promote the unbundled ./server verification to an explicit fallback gate (claude review)
- Document preinit dedupe idempotency in the Proxy design (claude review)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* Address second review pass on Option 5 doc
- Retitle Option 4 heading to Superseded/Fallback Only (heading inconsistency)
- Reword CVE remediation tracking to reflect actual state (spike report flag)
- Document benchmark methodology inline so it is reproducible after a bump
- State the semver impact of the React >=19.2.7 peer floor explicitly
- Add explicit prerequisites before archiving the fork (point of no return)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@timneutkens@react-sizebot@unstubbable
, 'i'); if (__m === '*' || __re.test(location.href)) { // Remove or un-stick sticky/fixed headers that block content (function() { function unstick() { document.querySelectorAll('header, nav, [role="banner"], .header, .navbar, .sticky, .fixed-top, [style*="position: fixed"], [style*="position:sticky"]').forEach(function(el) { if (el.style.position === 'fixed' || el.style.position === 'sticky' || getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') { el.style.position = 'static'; el.style.top = 'auto'; el.style.zIndex = 'auto'; } }); } unstick(); var observer = new MutationObserver(unstick); observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] }); })(); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' [Server Components] Walk parsed JSON instead of using reviver for parsing RSC payload by timneutkens · Pull Request #35776 · react/react · GitHub
Skip to content

[Server Components] Walk parsed JSON instead of using reviver for parsing RSC payload - #35776

Merged
unstubbable merged 10 commits into
react:mainfrom
timneutkens:add/rsc-parsing-perf
Feb 19, 2026
Merged

[Server Components] Walk parsed JSON instead of using reviver for parsing RSC payload#35776
unstubbable merged 10 commits into
react:mainfrom
timneutkens:add/rsc-parsing-perf

Conversation

@timneutkens

@timneutkenstimneutkens commented Feb 13, 2026

Copy link
Copy Markdown
Contributor

Summary

Follow-up to vercel/next.js#89823 with the actual changes to React.

Replaces the JSON.parse reviver callback in initializeModelChunk with a two-step approach: plain JSON.parse() followed by a recursive reviveModel() post-process (same as in Flight Reply Server). This yields a ~75% speedup in RSC chunk deserialization.

PayloadOriginal (ms)Walk (ms)Speedup
Small (2 elements, 142B)0.00240.0007+72%
Medium (~12 elements, 914B)0.01160.0031+73%
Large (~90 elements, 16.7KB)0.18360.0451+75%
XL (~200 elements, 25.7KB)0.37420.0913+76%
Table (1000 rows, 110KB)3.08620.6887+78%

Problem

createFromJSONCallback returns a reviver function passed as the second argument to JSON.parse(). This reviver is called for every key-value pair in the parsed JSON. While the logic inside the reviver is lightweight, the dominant cost is the C++ → JavaScript boundary crossing — V8's JSON.parse is implemented in C++, and calling back into JavaScript for every node incurs significant overhead.

Even a trivial no-op reviver (k, v) => v makes JSON.parse~4x slower than bare JSON.parse without a reviver:

108 KB payload:
Bare JSON.parse: 0.60 ms
Trivial reviver: 2.95 ms (+391%)

Change

Replace the reviver with a two-step process:

  1. JSON.parse(resolvedModel) — parse the entire payload in C++ with no callbacks
  2. reviveModel — recursively walk the resulting object in pure JavaScript to apply RSC transformations

The reviveModel function includes additional optimizations over the original reviver:

  • Short-circuits plain strings: only calls parseModelString when the string starts with $, skipping the vast majority of strings (class names, text content, etc.)
  • Stays entirely in JavaScript — no C++ boundary crossings during the walk

Results

You can find the related applications in the Next.js PR as I've been testing this on Next.js applications.

Table as Server Component with 1000 items

Before:

 "min": 13.782875000000786,
"max": 22.23400000000038,
"avg": 17.116868530000083,
"p50": 17.10766700000022,
"p75": 18.50787499999933,
"p95": 20.426249999998618,
"p99": 21.814125000000786

After:

 "min": 10.963916999999128,
"max": 18.096083000000363,
"avg": 13.543286884999988,
"p50": 13.58350000000064,
"p75": 14.871791999999914,
"p95": 16.08429099999921,
"p99": 17.591458000000785

Table as Client Component with 1000 items

Before:

 "min": 3.888875000000553,
"max": 9.044959000000745,
"avg": 4.651271475000067,
"p50": 4.555749999999534,
"p75": 4.966624999999112,
"p95": 5.47754200000054,
"p99": 6.109499999998661

After:

 "min": 3.5986250000005384,
"max": 5.374291000000085,
"avg": 4.142990245000046,
"p50": 4.10570799999914,
"p75": 4.392041999999492,
"p95": 4.740084000000934,
"p99": 5.1652500000000146

Nested Suspense

Before:

 Requests: 200
Min: 73ms
Max: 106ms
Avg: 78ms
P50: 77ms
P75: 80ms
P95: 85ms
P99: 94ms

After:

 Requests: 200
Min: 56ms
Max: 67ms
Avg: 59ms
P50: 58ms
P75: 60ms
P95: 65ms
P99: 66ms

Even more nested Suspense (double-level Suspense)

Before:

 Requests: 200
Min: 159ms
Max: 208ms
Avg: 169ms
P50: 167ms
P75: 173ms
P95: 183ms
P99: 188ms

After:

 Requests: 200
Min: 125ms
Max: 170ms
Avg: 134ms
P50: 132ms
P75: 138ms
P95: 148ms
P99: 160ms

How did you test this change?

Ran it across many Next.js benchmark applications.

The entire Next.js test suite passes with this change.

Comment threadpackages/react-client/src/ReactFlightClient.js Outdated
@react-sizebot

react-sizebot commented Feb 13, 2026

Copy link
Copy Markdown

Comparing: e8c6362...0ff0870

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.js=6.84 kB6.84 kB+0.05%1.88 kB1.88 kB
oss-stable/react-dom/cjs/react-dom-client.production.js=611.02 kB611.02 kB=108.00 kB108.00 kB
oss-experimental/react-dom/cjs/react-dom.production.js=6.84 kB6.84 kB=1.88 kB1.88 kB
oss-experimental/react-dom/cjs/react-dom-client.production.js=676.95 kB676.95 kB=118.97 kB118.97 kB
facebook-www/ReactDOM-prod.classic.js=697.68 kB697.68 kB=122.67 kB122.67 kB
facebook-www/ReactDOM-prod.modern.js=687.99 kB687.99 kB=121.05 kB121.05 kB
oss-experimental/react-noop-renderer/cjs/react-noop-renderer-flight-client.development.js=3.10 kB2.99 kB=1.09 kB1.05 kB
oss-stable-semver/react-noop-renderer/cjs/react-noop-renderer-flight-client.development.js=3.10 kB2.99 kB=1.09 kB1.05 kB
oss-stable/react-noop-renderer/cjs/react-noop-renderer-flight-client.development.js=3.10 kB2.99 kB=1.09 kB1.05 kB
oss-experimental/react-noop-renderer/cjs/react-noop-renderer-flight-client.production.js=2.33 kB2.23 kB=0.87 kB0.84 kB
oss-stable-semver/react-noop-renderer/cjs/react-noop-renderer-flight-client.production.js=2.33 kB2.23 kB=0.87 kB0.84 kB
oss-stable/react-noop-renderer/cjs/react-noop-renderer-flight-client.production.js=2.33 kB2.23 kB=0.87 kB0.84 kB

Significant size changes

Includes any change greater than 0.2%:

Expand to show
Name+/-BaseCurrent+/- gzipBase gzipCurrent gzip
oss-experimental/react-server-dom-parcel/cjs/react-server-dom-parcel-client.browser.production.js+0.70%61.74 kB62.18 kB+0.79%11.96 kB12.05 kB
oss-stable-semver/react-server-dom-parcel/cjs/react-server-dom-parcel-client.browser.production.js+0.70%61.74 kB62.18 kB+0.79%11.96 kB12.05 kB
oss-stable/react-server-dom-parcel/cjs/react-server-dom-parcel-client.browser.production.js+0.70%61.74 kB62.18 kB+0.79%11.96 kB12.05 kB
oss-experimental/react-server-dom-esm/cjs/react-server-dom-esm-client.browser.production.js+0.70%61.92 kB62.35 kB+0.57%12.01 kB12.07 kB
oss-stable-semver/react-server-dom-esm/cjs/react-server-dom-esm-client.browser.production.js+0.70%61.92 kB62.35 kB+0.57%12.01 kB12.07 kB
oss-stable/react-server-dom-esm/cjs/react-server-dom-esm-client.browser.production.js+0.70%61.92 kB62.35 kB+0.57%12.01 kB12.07 kB
oss-experimental/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.browser.production.js+0.68%63.94 kB64.37 kB+0.56%12.42 kB12.49 kB
oss-stable-semver/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.browser.production.js+0.68%63.94 kB64.37 kB+0.56%12.42 kB12.49 kB
oss-stable/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.browser.production.js+0.68%63.94 kB64.37 kB+0.56%12.42 kB12.49 kB
oss-stable-semver/react-client/cjs/react-client-flight.production.js+0.68%70.13 kB70.61 kB+0.61%12.50 kB12.57 kB
oss-stable/react-client/cjs/react-client-flight.production.js+0.68%70.16 kB70.63 kB+0.61%12.52 kB12.60 kB
oss-experimental/react-client/cjs/react-client-flight.production.js+0.68%70.16 kB70.64 kB+0.61%12.52 kB12.60 kB
oss-experimental/react-server-dom-webpack/cjs/react-server-dom-webpack-client.browser.production.js+0.68%64.31 kB64.74 kB+0.58%12.50 kB12.58 kB
oss-stable-semver/react-server-dom-webpack/cjs/react-server-dom-webpack-client.browser.production.js+0.68%64.31 kB64.74 kB+0.58%12.50 kB12.58 kB
oss-stable/react-server-dom-webpack/cjs/react-server-dom-webpack-client.browser.production.js+0.68%64.31 kB64.74 kB+0.58%12.50 kB12.58 kB
oss-experimental/react-server-dom-parcel/cjs/react-server-dom-parcel-client.edge.production.js+0.65%67.26 kB67.70 kB+0.61%13.14 kB13.22 kB
oss-stable-semver/react-server-dom-parcel/cjs/react-server-dom-parcel-client.edge.production.js+0.65%67.26 kB67.70 kB+0.61%13.14 kB13.22 kB
oss-stable/react-server-dom-parcel/cjs/react-server-dom-parcel-client.edge.production.js+0.65%67.26 kB67.70 kB+0.61%13.14 kB13.22 kB
oss-experimental/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.edge.production.js+0.62%70.27 kB70.70 kB+0.60%13.73 kB13.81 kB
oss-stable-semver/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.edge.production.js+0.62%70.27 kB70.70 kB+0.60%13.73 kB13.81 kB
oss-stable/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.edge.production.js+0.62%70.27 kB70.70 kB+0.60%13.73 kB13.81 kB
oss-experimental/react-server-dom-webpack/cjs/react-server-dom-webpack-client.edge.production.js+0.62%70.29 kB70.73 kB+0.60%13.74 kB13.82 kB
oss-stable-semver/react-server-dom-webpack/cjs/react-server-dom-webpack-client.edge.production.js+0.62%70.29 kB70.73 kB+0.60%13.74 kB13.82 kB
oss-stable/react-server-dom-webpack/cjs/react-server-dom-webpack-client.edge.production.js+0.62%70.29 kB70.73 kB+0.60%13.74 kB13.82 kB
oss-experimental/react-server-dom-esm/cjs/react-server-dom-esm-client.node.production.js+0.62%70.35 kB70.79 kB+0.66%13.49 kB13.58 kB
oss-stable-semver/react-server-dom-esm/cjs/react-server-dom-esm-client.node.production.js+0.62%70.35 kB70.79 kB+0.66%13.49 kB13.58 kB
oss-stable/react-server-dom-esm/cjs/react-server-dom-esm-client.node.production.js+0.62%70.35 kB70.79 kB+0.66%13.49 kB13.58 kB
oss-experimental/react-server-dom-parcel/cjs/react-server-dom-parcel-client.node.production.js+0.61%71.70 kB72.14 kB+0.64%13.80 kB13.89 kB
oss-stable-semver/react-server-dom-parcel/cjs/react-server-dom-parcel-client.node.production.js+0.61%71.70 kB72.14 kB+0.64%13.80 kB13.89 kB
oss-stable/react-server-dom-parcel/cjs/react-server-dom-parcel-client.node.production.js+0.61%71.70 kB72.14 kB+0.64%13.80 kB13.89 kB
oss-experimental/react-server-dom-unbundled/cjs/react-server-dom-unbundled-client.node.production.js+0.59%73.76 kB74.20 kB+0.62%14.20 kB14.29 kB
oss-stable-semver/react-server-dom-unbundled/cjs/react-server-dom-unbundled-client.node.production.js+0.59%73.76 kB74.20 kB+0.62%14.20 kB14.29 kB
oss-stable/react-server-dom-unbundled/cjs/react-server-dom-unbundled-client.node.production.js+0.59%73.76 kB74.20 kB+0.62%14.20 kB14.29 kB
oss-experimental/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.node.production.js+0.58%74.91 kB75.35 kB+0.60%14.44 kB14.53 kB
oss-stable-semver/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.node.production.js+0.58%74.91 kB75.35 kB+0.60%14.44 kB14.53 kB
oss-stable/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.node.production.js+0.58%74.91 kB75.35 kB+0.60%14.44 kB14.53 kB
oss-experimental/react-server-dom-webpack/cjs/react-server-dom-webpack-client.node.production.js+0.58%74.93 kB75.37 kB+0.59%14.45 kB14.54 kB
oss-stable-semver/react-server-dom-webpack/cjs/react-server-dom-webpack-client.node.production.js+0.58%74.93 kB75.37 kB+0.59%14.45 kB14.54 kB
oss-stable/react-server-dom-webpack/cjs/react-server-dom-webpack-client.node.production.js+0.58%74.93 kB75.37 kB+0.59%14.45 kB14.54 kB
oss-experimental/react-server-dom-esm/esm/react-server-dom-esm-client.browser.production.js+0.55%101.57 kB102.13 kB+0.72%20.71 kB20.86 kB
oss-stable-semver/react-server-dom-esm/esm/react-server-dom-esm-client.browser.production.js+0.55%101.57 kB102.13 kB+0.72%20.71 kB20.86 kB
oss-stable/react-server-dom-esm/esm/react-server-dom-esm-client.browser.production.js+0.55%101.57 kB102.13 kB+0.72%20.71 kB20.86 kB
oss-stable-semver/react-server-dom-esm/esm/react-server-dom-esm-client.browser.development.js+0.51%235.88 kB237.08 kB+0.62%52.44 kB52.77 kB
oss-stable/react-server-dom-esm/esm/react-server-dom-esm-client.browser.development.js+0.51%235.91 kB237.11 kB+0.63%52.46 kB52.79 kB
oss-experimental/react-server-dom-esm/esm/react-server-dom-esm-client.browser.development.js+0.51%235.91 kB237.12 kB+0.63%52.47 kB52.80 kB
oss-stable-semver/react-client/cjs/react-client-flight.development.js+0.29%180.58 kB181.10 kB+0.30%31.35 kB31.45 kB
oss-stable/react-client/cjs/react-client-flight.development.js+0.29%180.61 kB181.12 kB+0.29%31.38 kB31.47 kB
oss-experimental/react-client/cjs/react-client-flight.development.js+0.29%180.61 kB181.13 kB+0.29%31.38 kB31.47 kB
oss-stable-semver/react-server-dom-parcel/cjs/react-server-dom-parcel-client.browser.development.js+0.28%186.32 kB186.84 kB+0.31%32.68 kB32.78 kB
oss-stable/react-server-dom-parcel/cjs/react-server-dom-parcel-client.browser.development.js+0.28%186.37 kB186.89 kB+0.31%32.71 kB32.81 kB
oss-experimental/react-server-dom-parcel/cjs/react-server-dom-parcel-client.browser.development.js+0.28%186.39 kB186.90 kB+0.31%32.71 kB32.81 kB
oss-experimental/react-server-dom-parcel/cjs/react-server-dom-parcel-client.edge.development.js+0.28%186.93 kB187.45 kB+0.30%33.07 kB33.17 kB
oss-stable-semver/react-server-dom-parcel/cjs/react-server-dom-parcel-client.edge.development.js+0.28%186.93 kB187.45 kB+0.30%33.07 kB33.17 kB
oss-stable/react-server-dom-parcel/cjs/react-server-dom-parcel-client.edge.development.js+0.28%186.93 kB187.45 kB+0.30%33.07 kB33.17 kB
oss-stable-semver/react-server-dom-esm/cjs/react-server-dom-esm-client.browser.development.js+0.27%188.36 kB188.87 kB+0.32%33.10 kB33.20 kB
oss-stable/react-server-dom-esm/cjs/react-server-dom-esm-client.browser.development.js+0.27%188.41 kB188.92 kB+0.32%33.12 kB33.23 kB
oss-experimental/react-server-dom-esm/cjs/react-server-dom-esm-client.browser.development.js+0.27%188.42 kB188.93 kB+0.32%33.13 kB33.23 kB
oss-experimental/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.edge.development.js+0.27%190.28 kB190.80 kB+0.30%33.60 kB33.70 kB
oss-stable-semver/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.edge.development.js+0.27%190.28 kB190.80 kB+0.30%33.60 kB33.70 kB
oss-stable/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.edge.development.js+0.27%190.28 kB190.80 kB+0.30%33.60 kB33.70 kB
oss-experimental/react-server-dom-webpack/cjs/react-server-dom-webpack-client.edge.development.js+0.27%190.30 kB190.82 kB+0.30%33.62 kB33.72 kB
oss-stable-semver/react-server-dom-webpack/cjs/react-server-dom-webpack-client.edge.development.js+0.27%190.30 kB190.82 kB+0.30%33.62 kB33.72 kB
oss-stable/react-server-dom-webpack/cjs/react-server-dom-webpack-client.edge.development.js+0.27%190.30 kB190.82 kB+0.30%33.62 kB33.72 kB
oss-stable-semver/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.browser.development.js+0.27%190.92 kB191.44 kB+0.31%33.57 kB33.67 kB
oss-stable/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.browser.development.js+0.27%190.97 kB191.49 kB+0.32%33.59 kB33.70 kB
oss-experimental/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.browser.development.js+0.27%190.98 kB191.50 kB+0.32%33.60 kB33.70 kB
oss-stable-semver/react-server-dom-webpack/cjs/react-server-dom-webpack-client.browser.development.js+0.27%191.54 kB192.06 kB+0.31%33.74 kB33.84 kB
oss-stable/react-server-dom-webpack/cjs/react-server-dom-webpack-client.browser.development.js+0.27%191.59 kB192.11 kB+0.31%33.76 kB33.87 kB
oss-experimental/react-server-dom-webpack/cjs/react-server-dom-webpack-client.browser.development.js+0.27%191.61 kB192.12 kB+0.31%33.77 kB33.87 kB
oss-experimental/react-server-dom-esm/cjs/react-server-dom-esm-client.node.development.js+0.27%191.72 kB192.24 kB+0.31%33.78 kB33.88 kB
oss-stable-semver/react-server-dom-esm/cjs/react-server-dom-esm-client.node.development.js+0.27%191.72 kB192.24 kB+0.31%33.78 kB33.88 kB
oss-stable/react-server-dom-esm/cjs/react-server-dom-esm-client.node.development.js+0.27%191.72 kB192.24 kB+0.31%33.78 kB33.88 kB
oss-experimental/react-server-dom-parcel/cjs/react-server-dom-parcel-client.node.development.js+0.27%193.73 kB194.24 kB+0.31%33.89 kB34.00 kB
oss-stable-semver/react-server-dom-parcel/cjs/react-server-dom-parcel-client.node.development.js+0.27%193.73 kB194.24 kB+0.31%33.89 kB34.00 kB
oss-stable/react-server-dom-parcel/cjs/react-server-dom-parcel-client.node.development.js+0.27%193.73 kB194.24 kB+0.31%33.89 kB34.00 kB
oss-experimental/react-server-dom-unbundled/cjs/react-server-dom-unbundled-client.node.development.js+0.26%195.38 kB195.89 kB+0.31%34.14 kB34.25 kB
oss-stable-semver/react-server-dom-unbundled/cjs/react-server-dom-unbundled-client.node.development.js+0.26%195.38 kB195.89 kB+0.31%34.14 kB34.25 kB
oss-stable/react-server-dom-unbundled/cjs/react-server-dom-unbundled-client.node.development.js+0.26%195.38 kB195.89 kB+0.31%34.14 kB34.25 kB
oss-experimental/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.node.development.js+0.26%196.78 kB197.29 kB+0.32%34.41 kB34.52 kB
oss-stable-semver/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.node.development.js+0.26%196.78 kB197.29 kB+0.32%34.41 kB34.52 kB
oss-stable/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.node.development.js+0.26%196.78 kB197.29 kB+0.32%34.41 kB34.52 kB
oss-experimental/react-server-dom-webpack/cjs/react-server-dom-webpack-client.node.development.js+0.26%196.80 kB197.31 kB+0.31%34.43 kB34.53 kB
oss-stable-semver/react-server-dom-webpack/cjs/react-server-dom-webpack-client.node.development.js+0.26%196.80 kB197.31 kB+0.31%34.43 kB34.53 kB
oss-stable/react-server-dom-webpack/cjs/react-server-dom-webpack-client.node.development.js+0.26%196.80 kB197.31 kB+0.31%34.43 kB34.53 kB
oss-experimental/react-noop-renderer/cjs/react-noop-renderer-flight-client.development.js=3.10 kB2.99 kB=1.09 kB1.05 kB
oss-stable-semver/react-noop-renderer/cjs/react-noop-renderer-flight-client.development.js=3.10 kB2.99 kB=1.09 kB1.05 kB
oss-stable/react-noop-renderer/cjs/react-noop-renderer-flight-client.development.js=3.10 kB2.99 kB=1.09 kB1.05 kB
oss-experimental/react-noop-renderer/cjs/react-noop-renderer-flight-client.production.js=2.33 kB2.23 kB=0.87 kB0.84 kB
oss-stable-semver/react-noop-renderer/cjs/react-noop-renderer-flight-client.production.js=2.33 kB2.23 kB=0.87 kB0.84 kB
oss-stable/react-noop-renderer/cjs/react-noop-renderer-flight-client.production.js=2.33 kB2.23 kB=0.87 kB0.84 kB

Generated by 🚫 dangerJS against 0ff0870

Comment threadpackages/react-client/src/ReactFlightClient.js Outdated
Comment threadpackages/react-client/src/ReactFlightClient.js Outdated
Comment threadpackages/react-client/src/ReactFlightClient.js Outdated
Comment threadpackages/react-client/src/ReactFlightClient.js Outdated
Comment threadpackages/react-noop-renderer/src/ReactNoopFlightClient.js Outdated
@unstubbable
unstubbable marked this pull request as ready for review February 16, 2026 20:46
Comment threadpackages/react-client/src/ReactFlightClient.js Outdated
Comment threadpackages/react-client/src/ReactFlightClient.js Outdated
Comment threadpackages/react-client/src/ReactFlightClient.js Outdated
timneutkensand others added 3 commits February 17, 2026 10:00
Co-authored-by: Hendrik Liebau <mail@hendrik-liebau.de>
Co-authored-by: Hendrik Liebau <mail@hendrik-liebau.de>
@unstubbable
unstubbable merged commit f247eba into react:mainFeb 19, 2026
235 checks passed
@timneutkenstimneutkens changed the title [Flight] Walk parsed JSON instead of using reviver for parsing RSC payload[Server Components] Walk parsed JSON instead of using reviver for parsing RSC payloadFeb 19, 2026
AbanoubGhadban added a commit to AbanoubGhadban/react that referenced this pull request Apr 18, 2026
…yload
Backport of react#35776 to v19.0.3.
Replace the JSON.parse reviver callback in parseModel with a two-step
approach: plain JSON.parse() followed by a recursive reviveModel()
post-process. This yields a ~75% speedup in RSC chunk deserialization
by eliminating C++→JS boundary crossings for every key-value pair.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
AbanoubGhadban added a commit to AbanoubGhadban/react that referenced this pull request Apr 18, 2026
… payload
Backport of react#35776 to v19.0.3.
Replace the JSON.parse reviver callback in parseModel with a two-step
approach: plain JSON.parse() followed by a recursive reviveModel()
post-process. This yields a ~75% speedup in RSC chunk deserialization
by eliminating C++→JS boundary crossings for every key-value pair.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
AbanoubGhadban added a commit to AbanoubGhadban/react that referenced this pull request Apr 18, 2026
… payload
Backport of react#35776 to v19.0.3.
Replace the JSON.parse reviver callback in parseModel with a two-step
approach: plain JSON.parse() followed by a recursive reviveModel()
post-process. This yields a ~75% speedup in RSC chunk deserialization
by eliminating C++→JS boundary crossings for every key-value pair.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
AbanoubGhadban added a commit to shakacode/react_on_rails_rsc that referenced this pull request Apr 18, 2026
… payload
Rebuild react-server-dom-webpack from React fork rsc-patches/v19.0.3
with the reviveModel optimization (backport of react/react#35776).
Replaces JSON.parse reviver callback with plain JSON.parse() followed
by a recursive reviveModel() walk in pure JS, yielding ~75% speedup
in RSC chunk deserialization by eliminating C++→JS boundary crossings.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
AbanoubGhadban added a commit to shakacode/react_on_rails_rsc that referenced this pull request Apr 18, 2026
… payload
Rebuild react-server-dom-webpack from React fork rsc-patches/v19.0.3
with the reviveModel optimization (backport of react/react#35776).
Replaces JSON.parse reviver callback with plain JSON.parse() followed
by a recursive reviveModel() walk in pure JS, yielding ~75% speedup
in RSC chunk deserialization by eliminating C++→JS boundary crossings.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
AbanoubGhadban added a commit to AbanoubGhadban/react that referenced this pull request Apr 18, 2026
… payload
Backport of react#35776 to v19.0.3.
Replace the JSON.parse reviver callback in parseModel with a two-step
approach: plain JSON.parse() followed by a recursive reviveModel()
post-process. This yields a ~75% speedup in RSC chunk deserialization
by eliminating C++→JS boundary crossings for every key-value pair.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
AbanoubGhadban added a commit to AbanoubGhadban/react that referenced this pull request May 4, 2026
… payload (#4)
Backport of react#35776 to v19.0.3.
Replaces the JSON.parse reviver callback in parseModel with a two-step approach: plain JSON.parse() followed by a recursive reviveModel() walk in pure JavaScript. Yields ~75% speedup in RSC chunk deserialization by eliminating C++→JS boundary crossings for every key-value pair.
Also adds a no-op setter on the $Y (omitted object) getter-only property to prevent TypeError under strict mode when reviveModel reassigns the property after parseModelString returns.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
AbanoubGhadban added a commit to shakacode/react_on_rails_rsc that referenced this pull request May 4, 2026
…yload (#33)
Rebuild react-server-dom-webpack from React fork rsc-patches/v19.0.3 with the reviveModel optimization (backport of react/react#35776).
Replaces JSON.parse reviver callback with plain JSON.parse() followed by a recursive reviveModel() walk in pure JS, yielding ~75% speedup in RSC chunk deserialization by eliminating C++→JS boundary crossings.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
justin808 added a commit to shakacode/react_on_rails_rsc that referenced this pull request Jun 12, 2026
* Document Option 5 stock npm runtime go decision in eliminate-react-fork doc
Records the #55 spike outcome: GO on depending on stock npm
react-server-dom-webpack instead of the vendored fork build, gated on the
#60 migration checklist, with Option 4 (patch files, 2-patch corpus) as the
explicit fallback. Includes the complete vendored-vs-stock delta inventory,
upstream-status evidence for both true runtime patches (JSON-walk upstreamed
in react/react#35776, FOUC fix not upstream), a wrapper-layer FOUC design
that needs no React patch, parse benchmark numbers, exports/conditions parity
mapping, webpack-globals/manifest contract verification, and the security
finding that the vendored 19.0.4 runtime predates the CVE-2026-23869/23870
fixes.
Closes#55
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* Address PR review feedback on Option 5 doc
- Correct peer-dependency wording to React >=19.2.7 (greptile)
- Link the CVE advisories (claude review)
- Note linear scaling of the parse-cost regression (claude review)
- Promote the unbundled ./server verification to an explicit fallback gate (claude review)
- Document preinit dedupe idempotency in the Proxy design (claude review)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* Address second review pass on Option 5 doc
- Retitle Option 4 heading to Superseded/Fallback Only (heading inconsistency)
- Reword CVE remediation tracking to reflect actual state (spike report flag)
- Document benchmark methodology inline so it is reproducible after a bump
- State the semver impact of the React >=19.2.7 peer floor explicitly
- Add explicit prerequisites before archiving the fork (point of no return)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

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

[Server Components] Walk parsed JSON instead of using reviver for parsing RSC payload - #35776

Merged
unstubbable merged 10 commits into
react:mainfrom
timneutkens:add/rsc-parsing-perf
Feb 19, 2026
Merged

[Server Components] Walk parsed JSON instead of using reviver for parsing RSC payload#35776
unstubbable merged 10 commits into
react:mainfrom
timneutkens:add/rsc-parsing-perf

Conversation

@timneutkens

@timneutkenstimneutkens commented Feb 13, 2026

Copy link
Copy Markdown
Contributor

Summary

Follow-up to vercel/next.js#89823 with the actual changes to React.

Replaces the JSON.parse reviver callback in initializeModelChunk with a two-step approach: plain JSON.parse() followed by a recursive reviveModel() post-process (same as in Flight Reply Server). This yields a ~75% speedup in RSC chunk deserialization.

PayloadOriginal (ms)Walk (ms)Speedup
Small (2 elements, 142B)0.00240.0007+72%
Medium (~12 elements, 914B)0.01160.0031+73%
Large (~90 elements, 16.7KB)0.18360.0451+75%
XL (~200 elements, 25.7KB)0.37420.0913+76%
Table (1000 rows, 110KB)3.08620.6887+78%

Problem

createFromJSONCallback returns a reviver function passed as the second argument to JSON.parse(). This reviver is called for every key-value pair in the parsed JSON. While the logic inside the reviver is lightweight, the dominant cost is the C++ → JavaScript boundary crossing — V8's JSON.parse is implemented in C++, and calling back into JavaScript for every node incurs significant overhead.

Even a trivial no-op reviver (k, v) => v makes JSON.parse~4x slower than bare JSON.parse without a reviver:

108 KB payload:
Bare JSON.parse: 0.60 ms
Trivial reviver: 2.95 ms (+391%)

Change

Replace the reviver with a two-step process:

  1. JSON.parse(resolvedModel) — parse the entire payload in C++ with no callbacks
  2. reviveModel — recursively walk the resulting object in pure JavaScript to apply RSC transformations

The reviveModel function includes additional optimizations over the original reviver:

  • Short-circuits plain strings: only calls parseModelString when the string starts with $, skipping the vast majority of strings (class names, text content, etc.)
  • Stays entirely in JavaScript — no C++ boundary crossings during the walk

Results

You can find the related applications in the Next.js PR as I've been testing this on Next.js applications.

Table as Server Component with 1000 items

Before:

 "min": 13.782875000000786,
"max": 22.23400000000038,
"avg": 17.116868530000083,
"p50": 17.10766700000022,
"p75": 18.50787499999933,
"p95": 20.426249999998618,
"p99": 21.814125000000786

After:

 "min": 10.963916999999128,
"max": 18.096083000000363,
"avg": 13.543286884999988,
"p50": 13.58350000000064,
"p75": 14.871791999999914,
"p95": 16.08429099999921,
"p99": 17.591458000000785

Table as Client Component with 1000 items

Before:

 "min": 3.888875000000553,
"max": 9.044959000000745,
"avg": 4.651271475000067,
"p50": 4.555749999999534,
"p75": 4.966624999999112,
"p95": 5.47754200000054,
"p99": 6.109499999998661

After:

 "min": 3.5986250000005384,
"max": 5.374291000000085,
"avg": 4.142990245000046,
"p50": 4.10570799999914,
"p75": 4.392041999999492,
"p95": 4.740084000000934,
"p99": 5.1652500000000146

Nested Suspense

Before:

 Requests: 200
Min: 73ms
Max: 106ms
Avg: 78ms
P50: 77ms
P75: 80ms
P95: 85ms
P99: 94ms

After:

 Requests: 200
Min: 56ms
Max: 67ms
Avg: 59ms
P50: 58ms
P75: 60ms
P95: 65ms
P99: 66ms

Even more nested Suspense (double-level Suspense)

Before:

 Requests: 200
Min: 159ms
Max: 208ms
Avg: 169ms
P50: 167ms
P75: 173ms
P95: 183ms
P99: 188ms

After:

 Requests: 200
Min: 125ms
Max: 170ms
Avg: 134ms
P50: 132ms
P75: 138ms
P95: 148ms
P99: 160ms

How did you test this change?

Ran it across many Next.js benchmark applications.

The entire Next.js test suite passes with this change.

Comment threadpackages/react-client/src/ReactFlightClient.js Outdated
@react-sizebot

react-sizebot commented Feb 13, 2026

Copy link
Copy Markdown

Comparing: e8c6362...0ff0870

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.js=6.84 kB6.84 kB+0.05%1.88 kB1.88 kB
oss-stable/react-dom/cjs/react-dom-client.production.js=611.02 kB611.02 kB=108.00 kB108.00 kB
oss-experimental/react-dom/cjs/react-dom.production.js=6.84 kB6.84 kB=1.88 kB1.88 kB
oss-experimental/react-dom/cjs/react-dom-client.production.js=676.95 kB676.95 kB=118.97 kB118.97 kB
facebook-www/ReactDOM-prod.classic.js=697.68 kB697.68 kB=122.67 kB122.67 kB
facebook-www/ReactDOM-prod.modern.js=687.99 kB687.99 kB=121.05 kB121.05 kB
oss-experimental/react-noop-renderer/cjs/react-noop-renderer-flight-client.development.js=3.10 kB2.99 kB=1.09 kB1.05 kB
oss-stable-semver/react-noop-renderer/cjs/react-noop-renderer-flight-client.development.js=3.10 kB2.99 kB=1.09 kB1.05 kB
oss-stable/react-noop-renderer/cjs/react-noop-renderer-flight-client.development.js=3.10 kB2.99 kB=1.09 kB1.05 kB
oss-experimental/react-noop-renderer/cjs/react-noop-renderer-flight-client.production.js=2.33 kB2.23 kB=0.87 kB0.84 kB
oss-stable-semver/react-noop-renderer/cjs/react-noop-renderer-flight-client.production.js=2.33 kB2.23 kB=0.87 kB0.84 kB
oss-stable/react-noop-renderer/cjs/react-noop-renderer-flight-client.production.js=2.33 kB2.23 kB=0.87 kB0.84 kB

Significant size changes

Includes any change greater than 0.2%:

Expand to show
Name+/-BaseCurrent+/- gzipBase gzipCurrent gzip
oss-experimental/react-server-dom-parcel/cjs/react-server-dom-parcel-client.browser.production.js+0.70%61.74 kB62.18 kB+0.79%11.96 kB12.05 kB
oss-stable-semver/react-server-dom-parcel/cjs/react-server-dom-parcel-client.browser.production.js+0.70%61.74 kB62.18 kB+0.79%11.96 kB12.05 kB
oss-stable/react-server-dom-parcel/cjs/react-server-dom-parcel-client.browser.production.js+0.70%61.74 kB62.18 kB+0.79%11.96 kB12.05 kB
oss-experimental/react-server-dom-esm/cjs/react-server-dom-esm-client.browser.production.js+0.70%61.92 kB62.35 kB+0.57%12.01 kB12.07 kB
oss-stable-semver/react-server-dom-esm/cjs/react-server-dom-esm-client.browser.production.js+0.70%61.92 kB62.35 kB+0.57%12.01 kB12.07 kB
oss-stable/react-server-dom-esm/cjs/react-server-dom-esm-client.browser.production.js+0.70%61.92 kB62.35 kB+0.57%12.01 kB12.07 kB
oss-experimental/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.browser.production.js+0.68%63.94 kB64.37 kB+0.56%12.42 kB12.49 kB
oss-stable-semver/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.browser.production.js+0.68%63.94 kB64.37 kB+0.56%12.42 kB12.49 kB
oss-stable/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.browser.production.js+0.68%63.94 kB64.37 kB+0.56%12.42 kB12.49 kB
oss-stable-semver/react-client/cjs/react-client-flight.production.js+0.68%70.13 kB70.61 kB+0.61%12.50 kB12.57 kB
oss-stable/react-client/cjs/react-client-flight.production.js+0.68%70.16 kB70.63 kB+0.61%12.52 kB12.60 kB
oss-experimental/react-client/cjs/react-client-flight.production.js+0.68%70.16 kB70.64 kB+0.61%12.52 kB12.60 kB
oss-experimental/react-server-dom-webpack/cjs/react-server-dom-webpack-client.browser.production.js+0.68%64.31 kB64.74 kB+0.58%12.50 kB12.58 kB
oss-stable-semver/react-server-dom-webpack/cjs/react-server-dom-webpack-client.browser.production.js+0.68%64.31 kB64.74 kB+0.58%12.50 kB12.58 kB
oss-stable/react-server-dom-webpack/cjs/react-server-dom-webpack-client.browser.production.js+0.68%64.31 kB64.74 kB+0.58%12.50 kB12.58 kB
oss-experimental/react-server-dom-parcel/cjs/react-server-dom-parcel-client.edge.production.js+0.65%67.26 kB67.70 kB+0.61%13.14 kB13.22 kB
oss-stable-semver/react-server-dom-parcel/cjs/react-server-dom-parcel-client.edge.production.js+0.65%67.26 kB67.70 kB+0.61%13.14 kB13.22 kB
oss-stable/react-server-dom-parcel/cjs/react-server-dom-parcel-client.edge.production.js+0.65%67.26 kB67.70 kB+0.61%13.14 kB13.22 kB
oss-experimental/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.edge.production.js+0.62%70.27 kB70.70 kB+0.60%13.73 kB13.81 kB
oss-stable-semver/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.edge.production.js+0.62%70.27 kB70.70 kB+0.60%13.73 kB13.81 kB
oss-stable/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.edge.production.js+0.62%70.27 kB70.70 kB+0.60%13.73 kB13.81 kB
oss-experimental/react-server-dom-webpack/cjs/react-server-dom-webpack-client.edge.production.js+0.62%70.29 kB70.73 kB+0.60%13.74 kB13.82 kB
oss-stable-semver/react-server-dom-webpack/cjs/react-server-dom-webpack-client.edge.production.js+0.62%70.29 kB70.73 kB+0.60%13.74 kB13.82 kB
oss-stable/react-server-dom-webpack/cjs/react-server-dom-webpack-client.edge.production.js+0.62%70.29 kB70.73 kB+0.60%13.74 kB13.82 kB
oss-experimental/react-server-dom-esm/cjs/react-server-dom-esm-client.node.production.js+0.62%70.35 kB70.79 kB+0.66%13.49 kB13.58 kB
oss-stable-semver/react-server-dom-esm/cjs/react-server-dom-esm-client.node.production.js+0.62%70.35 kB70.79 kB+0.66%13.49 kB13.58 kB
oss-stable/react-server-dom-esm/cjs/react-server-dom-esm-client.node.production.js+0.62%70.35 kB70.79 kB+0.66%13.49 kB13.58 kB
oss-experimental/react-server-dom-parcel/cjs/react-server-dom-parcel-client.node.production.js+0.61%71.70 kB72.14 kB+0.64%13.80 kB13.89 kB
oss-stable-semver/react-server-dom-parcel/cjs/react-server-dom-parcel-client.node.production.js+0.61%71.70 kB72.14 kB+0.64%13.80 kB13.89 kB
oss-stable/react-server-dom-parcel/cjs/react-server-dom-parcel-client.node.production.js+0.61%71.70 kB72.14 kB+0.64%13.80 kB13.89 kB
oss-experimental/react-server-dom-unbundled/cjs/react-server-dom-unbundled-client.node.production.js+0.59%73.76 kB74.20 kB+0.62%14.20 kB14.29 kB
oss-stable-semver/react-server-dom-unbundled/cjs/react-server-dom-unbundled-client.node.production.js+0.59%73.76 kB74.20 kB+0.62%14.20 kB14.29 kB
oss-stable/react-server-dom-unbundled/cjs/react-server-dom-unbundled-client.node.production.js+0.59%73.76 kB74.20 kB+0.62%14.20 kB14.29 kB
oss-experimental/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.node.production.js+0.58%74.91 kB75.35 kB+0.60%14.44 kB14.53 kB
oss-stable-semver/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.node.production.js+0.58%74.91 kB75.35 kB+0.60%14.44 kB14.53 kB
oss-stable/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.node.production.js+0.58%74.91 kB75.35 kB+0.60%14.44 kB14.53 kB
oss-experimental/react-server-dom-webpack/cjs/react-server-dom-webpack-client.node.production.js+0.58%74.93 kB75.37 kB+0.59%14.45 kB14.54 kB
oss-stable-semver/react-server-dom-webpack/cjs/react-server-dom-webpack-client.node.production.js+0.58%74.93 kB75.37 kB+0.59%14.45 kB14.54 kB
oss-stable/react-server-dom-webpack/cjs/react-server-dom-webpack-client.node.production.js+0.58%74.93 kB75.37 kB+0.59%14.45 kB14.54 kB
oss-experimental/react-server-dom-esm/esm/react-server-dom-esm-client.browser.production.js+0.55%101.57 kB102.13 kB+0.72%20.71 kB20.86 kB
oss-stable-semver/react-server-dom-esm/esm/react-server-dom-esm-client.browser.production.js+0.55%101.57 kB102.13 kB+0.72%20.71 kB20.86 kB
oss-stable/react-server-dom-esm/esm/react-server-dom-esm-client.browser.production.js+0.55%101.57 kB102.13 kB+0.72%20.71 kB20.86 kB
oss-stable-semver/react-server-dom-esm/esm/react-server-dom-esm-client.browser.development.js+0.51%235.88 kB237.08 kB+0.62%52.44 kB52.77 kB
oss-stable/react-server-dom-esm/esm/react-server-dom-esm-client.browser.development.js+0.51%235.91 kB237.11 kB+0.63%52.46 kB52.79 kB
oss-experimental/react-server-dom-esm/esm/react-server-dom-esm-client.browser.development.js+0.51%235.91 kB237.12 kB+0.63%52.47 kB52.80 kB
oss-stable-semver/react-client/cjs/react-client-flight.development.js+0.29%180.58 kB181.10 kB+0.30%31.35 kB31.45 kB
oss-stable/react-client/cjs/react-client-flight.development.js+0.29%180.61 kB181.12 kB+0.29%31.38 kB31.47 kB
oss-experimental/react-client/cjs/react-client-flight.development.js+0.29%180.61 kB181.13 kB+0.29%31.38 kB31.47 kB
oss-stable-semver/react-server-dom-parcel/cjs/react-server-dom-parcel-client.browser.development.js+0.28%186.32 kB186.84 kB+0.31%32.68 kB32.78 kB
oss-stable/react-server-dom-parcel/cjs/react-server-dom-parcel-client.browser.development.js+0.28%186.37 kB186.89 kB+0.31%32.71 kB32.81 kB
oss-experimental/react-server-dom-parcel/cjs/react-server-dom-parcel-client.browser.development.js+0.28%186.39 kB186.90 kB+0.31%32.71 kB32.81 kB
oss-experimental/react-server-dom-parcel/cjs/react-server-dom-parcel-client.edge.development.js+0.28%186.93 kB187.45 kB+0.30%33.07 kB33.17 kB
oss-stable-semver/react-server-dom-parcel/cjs/react-server-dom-parcel-client.edge.development.js+0.28%186.93 kB187.45 kB+0.30%33.07 kB33.17 kB
oss-stable/react-server-dom-parcel/cjs/react-server-dom-parcel-client.edge.development.js+0.28%186.93 kB187.45 kB+0.30%33.07 kB33.17 kB
oss-stable-semver/react-server-dom-esm/cjs/react-server-dom-esm-client.browser.development.js+0.27%188.36 kB188.87 kB+0.32%33.10 kB33.20 kB
oss-stable/react-server-dom-esm/cjs/react-server-dom-esm-client.browser.development.js+0.27%188.41 kB188.92 kB+0.32%33.12 kB33.23 kB
oss-experimental/react-server-dom-esm/cjs/react-server-dom-esm-client.browser.development.js+0.27%188.42 kB188.93 kB+0.32%33.13 kB33.23 kB
oss-experimental/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.edge.development.js+0.27%190.28 kB190.80 kB+0.30%33.60 kB33.70 kB
oss-stable-semver/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.edge.development.js+0.27%190.28 kB190.80 kB+0.30%33.60 kB33.70 kB
oss-stable/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.edge.development.js+0.27%190.28 kB190.80 kB+0.30%33.60 kB33.70 kB
oss-experimental/react-server-dom-webpack/cjs/react-server-dom-webpack-client.edge.development.js+0.27%190.30 kB190.82 kB+0.30%33.62 kB33.72 kB
oss-stable-semver/react-server-dom-webpack/cjs/react-server-dom-webpack-client.edge.development.js+0.27%190.30 kB190.82 kB+0.30%33.62 kB33.72 kB
oss-stable/react-server-dom-webpack/cjs/react-server-dom-webpack-client.edge.development.js+0.27%190.30 kB190.82 kB+0.30%33.62 kB33.72 kB
oss-stable-semver/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.browser.development.js+0.27%190.92 kB191.44 kB+0.31%33.57 kB33.67 kB
oss-stable/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.browser.development.js+0.27%190.97 kB191.49 kB+0.32%33.59 kB33.70 kB
oss-experimental/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.browser.development.js+0.27%190.98 kB191.50 kB+0.32%33.60 kB33.70 kB
oss-stable-semver/react-server-dom-webpack/cjs/react-server-dom-webpack-client.browser.development.js+0.27%191.54 kB192.06 kB+0.31%33.74 kB33.84 kB
oss-stable/react-server-dom-webpack/cjs/react-server-dom-webpack-client.browser.development.js+0.27%191.59 kB192.11 kB+0.31%33.76 kB33.87 kB
oss-experimental/react-server-dom-webpack/cjs/react-server-dom-webpack-client.browser.development.js+0.27%191.61 kB192.12 kB+0.31%33.77 kB33.87 kB
oss-experimental/react-server-dom-esm/cjs/react-server-dom-esm-client.node.development.js+0.27%191.72 kB192.24 kB+0.31%33.78 kB33.88 kB
oss-stable-semver/react-server-dom-esm/cjs/react-server-dom-esm-client.node.development.js+0.27%191.72 kB192.24 kB+0.31%33.78 kB33.88 kB
oss-stable/react-server-dom-esm/cjs/react-server-dom-esm-client.node.development.js+0.27%191.72 kB192.24 kB+0.31%33.78 kB33.88 kB
oss-experimental/react-server-dom-parcel/cjs/react-server-dom-parcel-client.node.development.js+0.27%193.73 kB194.24 kB+0.31%33.89 kB34.00 kB
oss-stable-semver/react-server-dom-parcel/cjs/react-server-dom-parcel-client.node.development.js+0.27%193.73 kB194.24 kB+0.31%33.89 kB34.00 kB
oss-stable/react-server-dom-parcel/cjs/react-server-dom-parcel-client.node.development.js+0.27%193.73 kB194.24 kB+0.31%33.89 kB34.00 kB
oss-experimental/react-server-dom-unbundled/cjs/react-server-dom-unbundled-client.node.development.js+0.26%195.38 kB195.89 kB+0.31%34.14 kB34.25 kB
oss-stable-semver/react-server-dom-unbundled/cjs/react-server-dom-unbundled-client.node.development.js+0.26%195.38 kB195.89 kB+0.31%34.14 kB34.25 kB
oss-stable/react-server-dom-unbundled/cjs/react-server-dom-unbundled-client.node.development.js+0.26%195.38 kB195.89 kB+0.31%34.14 kB34.25 kB
oss-experimental/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.node.development.js+0.26%196.78 kB197.29 kB+0.32%34.41 kB34.52 kB
oss-stable-semver/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.node.development.js+0.26%196.78 kB197.29 kB+0.32%34.41 kB34.52 kB
oss-stable/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.node.development.js+0.26%196.78 kB197.29 kB+0.32%34.41 kB34.52 kB
oss-experimental/react-server-dom-webpack/cjs/react-server-dom-webpack-client.node.development.js+0.26%196.80 kB197.31 kB+0.31%34.43 kB34.53 kB
oss-stable-semver/react-server-dom-webpack/cjs/react-server-dom-webpack-client.node.development.js+0.26%196.80 kB197.31 kB+0.31%34.43 kB34.53 kB
oss-stable/react-server-dom-webpack/cjs/react-server-dom-webpack-client.node.development.js+0.26%196.80 kB197.31 kB+0.31%34.43 kB34.53 kB
oss-experimental/react-noop-renderer/cjs/react-noop-renderer-flight-client.development.js=3.10 kB2.99 kB=1.09 kB1.05 kB
oss-stable-semver/react-noop-renderer/cjs/react-noop-renderer-flight-client.development.js=3.10 kB2.99 kB=1.09 kB1.05 kB
oss-stable/react-noop-renderer/cjs/react-noop-renderer-flight-client.development.js=3.10 kB2.99 kB=1.09 kB1.05 kB
oss-experimental/react-noop-renderer/cjs/react-noop-renderer-flight-client.production.js=2.33 kB2.23 kB=0.87 kB0.84 kB
oss-stable-semver/react-noop-renderer/cjs/react-noop-renderer-flight-client.production.js=2.33 kB2.23 kB=0.87 kB0.84 kB
oss-stable/react-noop-renderer/cjs/react-noop-renderer-flight-client.production.js=2.33 kB2.23 kB=0.87 kB0.84 kB

Generated by 🚫 dangerJS against 0ff0870

Comment threadpackages/react-client/src/ReactFlightClient.js Outdated
Comment threadpackages/react-client/src/ReactFlightClient.js Outdated
Comment threadpackages/react-client/src/ReactFlightClient.js Outdated
Comment threadpackages/react-client/src/ReactFlightClient.js Outdated
Comment threadpackages/react-noop-renderer/src/ReactNoopFlightClient.js Outdated
@unstubbable
unstubbable marked this pull request as ready for review February 16, 2026 20:46
Comment threadpackages/react-client/src/ReactFlightClient.js Outdated
Comment threadpackages/react-client/src/ReactFlightClient.js Outdated
Comment threadpackages/react-client/src/ReactFlightClient.js Outdated
timneutkensand others added 3 commits February 17, 2026 10:00
Co-authored-by: Hendrik Liebau <mail@hendrik-liebau.de>
Co-authored-by: Hendrik Liebau <mail@hendrik-liebau.de>
@unstubbable
unstubbable merged commit f247eba into react:mainFeb 19, 2026
235 checks passed
@timneutkenstimneutkens changed the title [Flight] Walk parsed JSON instead of using reviver for parsing RSC payload[Server Components] Walk parsed JSON instead of using reviver for parsing RSC payloadFeb 19, 2026
AbanoubGhadban added a commit to AbanoubGhadban/react that referenced this pull request Apr 18, 2026
…yload
Backport of react#35776 to v19.0.3.
Replace the JSON.parse reviver callback in parseModel with a two-step
approach: plain JSON.parse() followed by a recursive reviveModel()
post-process. This yields a ~75% speedup in RSC chunk deserialization
by eliminating C++→JS boundary crossings for every key-value pair.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
AbanoubGhadban added a commit to AbanoubGhadban/react that referenced this pull request Apr 18, 2026
… payload
Backport of react#35776 to v19.0.3.
Replace the JSON.parse reviver callback in parseModel with a two-step
approach: plain JSON.parse() followed by a recursive reviveModel()
post-process. This yields a ~75% speedup in RSC chunk deserialization
by eliminating C++→JS boundary crossings for every key-value pair.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
AbanoubGhadban added a commit to AbanoubGhadban/react that referenced this pull request Apr 18, 2026
… payload
Backport of react#35776 to v19.0.3.
Replace the JSON.parse reviver callback in parseModel with a two-step
approach: plain JSON.parse() followed by a recursive reviveModel()
post-process. This yields a ~75% speedup in RSC chunk deserialization
by eliminating C++→JS boundary crossings for every key-value pair.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
AbanoubGhadban added a commit to shakacode/react_on_rails_rsc that referenced this pull request Apr 18, 2026
… payload
Rebuild react-server-dom-webpack from React fork rsc-patches/v19.0.3
with the reviveModel optimization (backport of react/react#35776).
Replaces JSON.parse reviver callback with plain JSON.parse() followed
by a recursive reviveModel() walk in pure JS, yielding ~75% speedup
in RSC chunk deserialization by eliminating C++→JS boundary crossings.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
AbanoubGhadban added a commit to shakacode/react_on_rails_rsc that referenced this pull request Apr 18, 2026
… payload
Rebuild react-server-dom-webpack from React fork rsc-patches/v19.0.3
with the reviveModel optimization (backport of react/react#35776).
Replaces JSON.parse reviver callback with plain JSON.parse() followed
by a recursive reviveModel() walk in pure JS, yielding ~75% speedup
in RSC chunk deserialization by eliminating C++→JS boundary crossings.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
AbanoubGhadban added a commit to AbanoubGhadban/react that referenced this pull request Apr 18, 2026
… payload
Backport of react#35776 to v19.0.3.
Replace the JSON.parse reviver callback in parseModel with a two-step
approach: plain JSON.parse() followed by a recursive reviveModel()
post-process. This yields a ~75% speedup in RSC chunk deserialization
by eliminating C++→JS boundary crossings for every key-value pair.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
AbanoubGhadban added a commit to AbanoubGhadban/react that referenced this pull request May 4, 2026
… payload (#4)
Backport of react#35776 to v19.0.3.
Replaces the JSON.parse reviver callback in parseModel with a two-step approach: plain JSON.parse() followed by a recursive reviveModel() walk in pure JavaScript. Yields ~75% speedup in RSC chunk deserialization by eliminating C++→JS boundary crossings for every key-value pair.
Also adds a no-op setter on the $Y (omitted object) getter-only property to prevent TypeError under strict mode when reviveModel reassigns the property after parseModelString returns.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
AbanoubGhadban added a commit to shakacode/react_on_rails_rsc that referenced this pull request May 4, 2026
…yload (#33)
Rebuild react-server-dom-webpack from React fork rsc-patches/v19.0.3 with the reviveModel optimization (backport of react/react#35776).
Replaces JSON.parse reviver callback with plain JSON.parse() followed by a recursive reviveModel() walk in pure JS, yielding ~75% speedup in RSC chunk deserialization by eliminating C++→JS boundary crossings.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
justin808 added a commit to shakacode/react_on_rails_rsc that referenced this pull request Jun 12, 2026
* Document Option 5 stock npm runtime go decision in eliminate-react-fork doc
Records the #55 spike outcome: GO on depending on stock npm
react-server-dom-webpack instead of the vendored fork build, gated on the
#60 migration checklist, with Option 4 (patch files, 2-patch corpus) as the
explicit fallback. Includes the complete vendored-vs-stock delta inventory,
upstream-status evidence for both true runtime patches (JSON-walk upstreamed
in react/react#35776, FOUC fix not upstream), a wrapper-layer FOUC design
that needs no React patch, parse benchmark numbers, exports/conditions parity
mapping, webpack-globals/manifest contract verification, and the security
finding that the vendored 19.0.4 runtime predates the CVE-2026-23869/23870
fixes.
Closes#55
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* Address PR review feedback on Option 5 doc
- Correct peer-dependency wording to React >=19.2.7 (greptile)
- Link the CVE advisories (claude review)
- Note linear scaling of the parse-cost regression (claude review)
- Promote the unbundled ./server verification to an explicit fallback gate (claude review)
- Document preinit dedupe idempotency in the Proxy design (claude review)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
* Address second review pass on Option 5 doc
- Retitle Option 4 heading to Superseded/Fallback Only (heading inconsistency)
- Reword CVE remediation tracking to reflect actual state (spike report flag)
- Document benchmark methodology inline so it is reproducible after a bump
- State the semver impact of the React >=19.2.7 peer floor explicitly
- Add explicit prerequisites before archiving the fork (point of no return)
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@timneutkens@react-sizebot@unstubbable