Skip to content

[Perf Tracks] Prevent crash when accessing $$typeof#35679

Merged
eps1lon merged 4 commits into
react:mainfrom
eps1lon:sebbie/02-03-_perf_tracks_skip_diffing_html-like_objects
Feb 3, 2026
Merged

[Perf Tracks] Prevent crash when accessing $$typeof#35679
eps1lon merged 4 commits into
react:mainfrom
eps1lon:sebbie/02-03-_perf_tracks_skip_diffing_html-like_objects

Conversation

@eps1lon

@eps1lon eps1lon commented Feb 3, 2026

Copy link
Copy Markdown
Collaborator

Alternate to #34840

Fixes #34840
Closes #34840

Summary

Guards dotting into $$typeof unconditionally. The try-catch proposed in #34840 feels too heavy.

Original plan was to skip diffing DOM nodes entirely since they're mutable boxes anyway. That felt like too much of a stretch unless we move the check to the host config. However, that wouldn't fix the linked issue. The linked issue is caused by having a cross-origin window in props not the iframe. Perf tracks wouldn't diff contentWindow since it's not enumerable.

The proposed implementation is host agnostic and feels like a better fit overall. And it guards against cases where accessing an unknown $$typeof property would also throw.

Test plan

@meta-cla meta-cla Bot added the CLA Signed label Feb 3, 2026
@github-actions github-actions Bot added the React Core Team Opened by a member of the React Core Team label Feb 3, 2026
Comment thread packages/shared/ReactPerformanceTrackProperties.js
@react-sizebot

react-sizebot commented Feb 3, 2026

Copy link
Copy Markdown

Comparing: d4a325d...45ac560

Critical size changes

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

Name +/- Base Current +/- gzip Base gzip Current gzip
oss-stable/react-dom/cjs/react-dom.production.js = 6.84 kB 6.84 kB +0.05% 1.88 kB 1.88 kB
oss-stable/react-dom/cjs/react-dom-client.production.js = 609.91 kB 609.58 kB = 107.85 kB 107.80 kB
oss-experimental/react-dom/cjs/react-dom.production.js = 6.84 kB 6.84 kB +0.05% 1.88 kB 1.88 kB
oss-experimental/react-dom/cjs/react-dom-client.production.js = 675.84 kB 675.51 kB = 118.81 kB 118.75 kB
facebook-www/ReactDOM-prod.classic.js = 695.47 kB 695.14 kB = 122.24 kB 122.19 kB
facebook-www/ReactDOM-prod.modern.js = 685.85 kB 685.52 kB = 120.63 kB 120.59 kB
oss-experimental/react-noop-renderer/cjs/react-noop-renderer-flight-client.production.js = 2.32 kB 2.09 kB = 0.87 kB 0.78 kB
oss-stable-semver/react-noop-renderer/cjs/react-noop-renderer-flight-client.production.js = 2.32 kB 2.09 kB = 0.87 kB 0.78 kB
oss-stable/react-noop-renderer/cjs/react-noop-renderer-flight-client.production.js = 2.32 kB 2.09 kB = 0.87 kB 0.78 kB
oss-experimental/react-noop-renderer/cjs/react-noop-renderer-flight-client.development.js = 3.08 kB 2.51 kB = 1.08 kB 0.86 kB
oss-stable-semver/react-noop-renderer/cjs/react-noop-renderer-flight-client.development.js = 3.08 kB 2.51 kB = 1.08 kB 0.86 kB
oss-stable/react-noop-renderer/cjs/react-noop-renderer-flight-client.development.js = 3.08 kB 2.51 kB = 1.08 kB 0.86 kB

Significant size changes

Includes any change greater than 0.2%:

Expand to show
Name +/- Base Current +/- gzip Base gzip Current gzip
oss-experimental/react-server-dom-parcel/cjs/react-server-dom-parcel-client.browser.development.js = 184.50 kB 183.67 kB = 32.39 kB 32.07 kB
oss-stable/react-server-dom-parcel/cjs/react-server-dom-parcel-client.browser.development.js = 184.49 kB 183.66 kB = 32.39 kB 32.07 kB
oss-stable-semver/react-server-dom-parcel/cjs/react-server-dom-parcel-client.browser.development.js = 184.44 kB 183.61 kB = 32.37 kB 32.04 kB
oss-experimental/react-server-dom-parcel/cjs/react-server-dom-parcel-client.edge.development.js = 185.10 kB 184.26 kB = 32.76 kB 32.49 kB
oss-stable-semver/react-server-dom-parcel/cjs/react-server-dom-parcel-client.edge.development.js = 185.10 kB 184.26 kB = 32.76 kB 32.49 kB
oss-stable/react-server-dom-parcel/cjs/react-server-dom-parcel-client.edge.development.js = 185.10 kB 184.26 kB = 32.76 kB 32.49 kB
oss-experimental/react-server-dom-esm/esm/react-server-dom-esm-client.browser.development.js = 232.86 kB 231.75 kB = 51.60 kB 51.20 kB
oss-stable/react-server-dom-esm/esm/react-server-dom-esm-client.browser.development.js = 232.85 kB 231.74 kB = 51.59 kB 51.19 kB
oss-stable-semver/react-server-dom-esm/esm/react-server-dom-esm-client.browser.development.js = 232.83 kB 231.72 kB = 51.57 kB 51.17 kB
oss-experimental/react-server-dom-webpack/cjs/react-server-dom-webpack-client.browser.development.js = 189.72 kB 188.77 kB = 33.45 kB 33.13 kB
oss-stable/react-server-dom-webpack/cjs/react-server-dom-webpack-client.browser.development.js = 189.71 kB 188.75 kB = 33.45 kB 33.12 kB
oss-stable-semver/react-server-dom-webpack/cjs/react-server-dom-webpack-client.browser.development.js = 189.66 kB 188.70 kB = 33.42 kB 33.10 kB
oss-experimental/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.browser.development.js = 189.10 kB 188.14 kB = 33.29 kB 32.97 kB
oss-stable/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.browser.development.js = 189.08 kB 188.13 kB = 33.28 kB 32.96 kB
oss-stable-semver/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.browser.development.js = 189.03 kB 188.08 kB = 33.26 kB 32.94 kB
oss-experimental/react-server-dom-esm/cjs/react-server-dom-esm-client.browser.development.js = 186.53 kB 185.53 kB = 32.81 kB 32.48 kB
oss-stable/react-server-dom-esm/cjs/react-server-dom-esm-client.browser.development.js = 186.52 kB 185.52 kB = 32.81 kB 32.48 kB
oss-stable-semver/react-server-dom-esm/cjs/react-server-dom-esm-client.browser.development.js = 186.47 kB 185.47 kB = 32.79 kB 32.45 kB
oss-experimental/react-server-dom-webpack/cjs/react-server-dom-webpack-client.edge.development.js = 188.47 kB 187.43 kB = 33.30 kB 33.00 kB
oss-stable-semver/react-server-dom-webpack/cjs/react-server-dom-webpack-client.edge.development.js = 188.47 kB 187.43 kB = 33.30 kB 33.00 kB
oss-stable/react-server-dom-webpack/cjs/react-server-dom-webpack-client.edge.development.js = 188.47 kB 187.43 kB = 33.30 kB 33.00 kB
oss-experimental/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.edge.development.js = 188.45 kB 187.41 kB = 33.28 kB 32.98 kB
oss-stable-semver/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.edge.development.js = 188.45 kB 187.41 kB = 33.28 kB 32.98 kB
oss-stable/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.edge.development.js = 188.45 kB 187.41 kB = 33.28 kB 32.98 kB
oss-experimental/react-server-dom-webpack/cjs/react-server-dom-webpack-client.node.development.js = 194.77 kB 193.48 kB = 34.08 kB 33.73 kB
oss-stable-semver/react-server-dom-webpack/cjs/react-server-dom-webpack-client.node.development.js = 194.77 kB 193.48 kB = 34.08 kB 33.73 kB
oss-stable/react-server-dom-webpack/cjs/react-server-dom-webpack-client.node.development.js = 194.77 kB 193.48 kB = 34.08 kB 33.73 kB
oss-experimental/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.node.development.js = 194.75 kB 193.46 kB = 34.06 kB 33.71 kB
oss-stable-semver/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.node.development.js = 194.75 kB 193.46 kB = 34.06 kB 33.71 kB
oss-stable/react-server-dom-turbopack/cjs/react-server-dom-turbopack-client.node.development.js = 194.75 kB 193.46 kB = 34.06 kB 33.71 kB
oss-experimental/react-server-dom-unbundled/cjs/react-server-dom-unbundled-client.node.development.js = 193.35 kB 192.06 kB = 33.79 kB 33.45 kB
oss-stable-semver/react-server-dom-unbundled/cjs/react-server-dom-unbundled-client.node.development.js = 193.35 kB 192.06 kB = 33.79 kB 33.45 kB
oss-stable/react-server-dom-unbundled/cjs/react-server-dom-unbundled-client.node.development.js = 193.35 kB 192.06 kB = 33.79 kB 33.45 kB
oss-experimental/react-server-dom-parcel/cjs/react-server-dom-parcel-client.node.development.js = 191.70 kB 190.41 kB = 33.54 kB 33.19 kB
oss-stable-semver/react-server-dom-parcel/cjs/react-server-dom-parcel-client.node.development.js = 191.70 kB 190.41 kB = 33.54 kB 33.19 kB
oss-stable/react-server-dom-parcel/cjs/react-server-dom-parcel-client.node.development.js = 191.70 kB 190.41 kB = 33.54 kB 33.19 kB
oss-experimental/react-server-dom-esm/cjs/react-server-dom-esm-client.node.development.js = 189.82 kB 188.51 kB = 33.43 kB 33.08 kB
oss-stable-semver/react-server-dom-esm/cjs/react-server-dom-esm-client.node.development.js = 189.82 kB 188.51 kB = 33.43 kB 33.08 kB
oss-stable/react-server-dom-esm/cjs/react-server-dom-esm-client.node.development.js = 189.82 kB 188.51 kB = 33.43 kB 33.08 kB
test_utils/ReactAllWarnings.js = 67.70 kB 66.76 kB = 17.05 kB 16.83 kB
oss-experimental/react-noop-renderer/cjs/react-noop-renderer-flight-client.production.js = 2.32 kB 2.09 kB = 0.87 kB 0.78 kB
oss-stable-semver/react-noop-renderer/cjs/react-noop-renderer-flight-client.production.js = 2.32 kB 2.09 kB = 0.87 kB 0.78 kB
oss-stable/react-noop-renderer/cjs/react-noop-renderer-flight-client.production.js = 2.32 kB 2.09 kB = 0.87 kB 0.78 kB
oss-experimental/react-noop-renderer/cjs/react-noop-renderer-flight-client.development.js = 3.08 kB 2.51 kB = 1.08 kB 0.86 kB
oss-stable-semver/react-noop-renderer/cjs/react-noop-renderer-flight-client.development.js = 3.08 kB 2.51 kB = 1.08 kB 0.86 kB
oss-stable/react-noop-renderer/cjs/react-noop-renderer-flight-client.development.js = 3.08 kB 2.51 kB = 1.08 kB 0.86 kB

Generated by 🚫 dangerJS against 45ac560

@eps1lon
eps1lon force-pushed the sebbie/02-03-_perf_tracks_skip_diffing_html-like_objects branch 3 times, most recently from 9f43236 to f435c5c Compare February 3, 2026 10:58
@eps1lon
eps1lon force-pushed the sebbie/02-03-_perf_tracks_skip_diffing_html-like_objects branch from f435c5c to 736819e Compare February 3, 2026 10:59
@eps1lon
eps1lon force-pushed the sebbie/02-03-_perf_tracks_skip_diffing_html-like_objects branch from 736819e to 45ac560 Compare February 3, 2026 11:00
@eps1lon
eps1lon requested a review from hoxyq February 3, 2026 11:07
@eps1lon
eps1lon marked this pull request as ready for review February 3, 2026 11:07
@eps1lon
eps1lon merged commit 6853d7a into react:main Feb 3, 2026
237 checks passed
@eps1lon
eps1lon deleted the sebbie/02-03-_perf_tracks_skip_diffing_html-like_objects branch February 3, 2026 16:54
github-actions Bot pushed a commit to code/lib-react that referenced this pull request Feb 9, 2026
github-actions Bot pushed a commit to code/lib-react that referenced this pull request Feb 9, 2026
mbret added a commit to mbret/oboku that referenced this pull request Jul 25, 2026
…n frames

React 19.2's dev-only performance track deep-walks changed props and
throws a SecurityError when it reaches the reader iframe's cross-origin
window, crashing the commit (react/react#34840). Guard the prop
walkers so unreadable values log as [inaccessible] instead of throwing.

Fixed upstream by react/react#35679 (19.3 canary only); remove with
`pnpm patch-remove react-dom@19.2.8` once on a release containing it.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
mbret added a commit to mbret/oboku that referenced this pull request Jul 25, 2026
* feat: upgrade @prose-reader/* to 1.332.0 (#503)

* feat: upgrade @prose-reader/* to 1.332.0

Bump every @prose-reader/* dependency from 1.324.0 to 1.332.0 across web,
api and archive-metadata, and migrate the web reader to the breaking API
changes shipped in that range.

Reader lifecycle (prose #229/#230/#231):
- createReader() now takes the manifest (and optional cfi) at construction
  and mount(containerElement) is a one-shot DOM attachment; reader.load()
  is gone. useCreateReader now creates + mounts + destroys the reader in a
  single effect (destroy() is the true inverse of create + mount, so the
  effect is strict-mode safe), and useLoadReader is removed.
- The restored reading location (cfi) is read through a live ref so later
  progress writes flowing back into the book query never destroy/recreate
  the reader.
- reader.state$ ("idle"|"ready") is replaced by reader.mounted$; the book
  loading overlay now keys off !mounted.

Pin react/react-dom to 19.1.8 in the web app only:
- react-dom 19.2 dev builds recursively read component props and access
  $$typeof on every object, throwing SecurityError on our gapi cross-origin
  iframe (react/react#34840). The uncaught
  throw aborts passive-effect mounts (dead reader quick-menu) and corrupts
  the work loop (crash on back navigation). Prod is unaffected; dev is
  unusable.
- 19.1.x predates the offending logger and the web app uses no 19.2-only
  APIs. admin/landing stay on 19.2.x (@Mantine 9.4 needs useEffectEvent),
  so the pin is web-only, held together by resolve.dedupe in vite.config.
- Documented in AGENTS.md with removal steps for when the react bug is fixed.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* refactor(reader): read book once via enabled gate instead of useLiveRef

The enabled predicate already stops observing after the first result, so
progress-sync writes to the same book document never change the value.
Drop the redundant useLiveRef, read bookOnce directly, and name the
enabled predicate to state the intent.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* chore: unpin apps/web react and bump react to 19.2.7 project-wide

apps/web was pinned to react 19.1.8 to dodge a dev-only React 19.2 logger
crash with the gapi iframe. The pin diverged web from the rest of the repo
and left @types on 19.2.x, creating a runtime/types skew. Align everything
to the latest 19.2.7 (react/react-dom) and 19.2.17 (@types/react) across
web, admin and landing.

Remove the now-unneeded scaffolding: the vite resolve.dedupe entry and the
AGENTS.md "React version pin" section. The dev-only reader crash returns at
parity with develop/master; production is unaffected (logger is dev-only).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>

* chore(deps): bump @nestjs/platform-express to 11.1.28 to fix multer DoS (#507)

Updates @nestjs/platform-express 11.1.27 -> 11.1.28, which pulls multer
2.1.1 -> 2.2.0 (multer is consumed only by platform-express). Resolves the
two multer denial-of-service advisories on the API file-upload path:

- GHSA-72gw-mp4g-v24j (high): DoS via deeply nested field names
- GHSA-3p4h-7m6x-2hcm (moderate): DoS via incomplete cleanup of aborted uploads


Claude-Session: https://claude.ai/code/session_01WKoPAepDc2xhSFFDhHTHe5

Co-authored-by: Claude <noreply@anthropic.com>

* fix: lock

* fix: biome

* fix: types

* feat: migrate to pnpm

* fix: dedupe

* fix(deps): patch react-dom 19.2.8 dev perf-track crash on cross-origin frames

React 19.2's dev-only performance track deep-walks changed props and
throws a SecurityError when it reaches the reader iframe's cross-origin
window, crashing the commit (react/react#34840). Guard the prop
walkers so unreadable values log as [inaccessible] instead of throwing.

Fixed upstream by react/react#35679 (19.3 canary only); remove with
`pnpm patch-remove react-dom@19.2.8` once on a release containing it.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* fix(dev-proxy): stop 502 bursts from unreachable IPv6 host.docker.internal peer

Docker Desktop writes both IPv4 and IPv6 host-gateway entries, so nginx
expands host.docker.internal into two peers; the IPv6 one is unreachable
from the IPv4-only compose network and its failure accounting could mark
the whole implicit upstream down (no live upstreams -> 502 bursts during
replication). An explicit upstream with max_fails=0 lets a failed connect
fall through to the reachable address instead of disabling the group.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* fix(vercel): bootstrap pnpm 11 in install command to match lockfile

Vercel's lockfile heuristic picks pnpm 9, which can't read patchedDependencies
from pnpm-workspace.yaml and fails with ERR_PNPM_LOCKFILE_CONFIG_MISMATCH.
The bootstrapped pnpm 11 defers to the packageManager pin in package.json.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* fix(vercel): invoke bootstrapped pnpm by absolute path

Vercel prepends its detected pnpm 9 to PATH, shadowing the npm-installed
pnpm 11, so the install still hit ERR_PNPM_LOCKFILE_CONFIG_MISMATCH.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Bug: react-dom-client.development.js tries to read $$typeof on iframe object

3 participants