Skip to content

Add Inlined React Runtime check for React 19 incompatibilities#1380

Open
gunjanjaswal wants to merge 2 commits into
WordPress:trunkfrom
gunjanjaswal:add/inlined-react-runtime-check
Open

Add Inlined React Runtime check for React 19 incompatibilities#1380
gunjanjaswal wants to merge 2 commits into
WordPress:trunkfrom
gunjanjaswal:add/inlined-react-runtime-check

Conversation

@gunjanjaswal

@gunjanjaswal gunjanjaswal commented Jun 29, 2026

Copy link
Copy Markdown

Closes #1356.

This adds a check (inlined_react_runtime) for plugins that bundle their own copy of the React JSX runtime. WordPress is going to React 19 at some point, and the usual reason a plugin breaks across that jump isn't some exotic API, it's that the build inlined react/jsx-runtime into the bundle instead of loading it from WordPress. React 19 changed the shape of the element object, so anything an old bundled runtime creates gets rejected. The plugin runs fine today and then falls over the day WordPress updates, so the point is to catch it ahead of time.

The detection is pretty crude, honestly: it greps the plugin's JS for Symbol.for('react.element'), which only shows up when a pre-19 runtime got bundled in. React 19 switched that marker to react.transitional.element, so anyone externalizing the runtime properly won't trip it. And if the runtime is externalized there's nothing to warn about, so it stays quiet when it spots window.ReactJSXRuntime in the file or react-jsx-runtime listed in the matching *.asset.php. On top of that it flags a few APIs that got dropped in 19 (unmountComponentAtNode, findDOMNode, ReactCurrentOwner). Everything's a warning, nothing errors out. It's wired into Default_Check_Repository with the usual docs and changelog entries.

Inlined_React_Runtime_Check_Tests covers both sides: the -with-errors fixture throws two warnings (inlined_jsx_runtime on index.js, react_removed_api on legacy.js), and the -without-errors one stays clean because the runtime's externalized there, once through index.asset.php and once through window.ReactJSXRuntime. I'm not married to the category or severity if you'd rather scope it differently.

Open WordPress Playground Preview

Adds a static check that scans a plugin's JavaScript files for a bundled,
outdated React runtime that breaks once WordPress upgrades to React 19.

The primary, high-confidence signal is `Symbol.for( 'react.element' )`, which
is only emitted by an inlined pre-React 19 JSX runtime (React 19 uses the
`react.transitional.element` marker). The warning is suppressed when the
runtime is externalized, detected via a `window.ReactJSXRuntime` reference or a
`react-jsx-runtime` dependency in the sibling `*.asset.php` file. Usage of React
APIs removed in React 19 (unmountComponentAtNode, findDOMNode, ReactCurrentOwner)
is reported as a secondary signal.

Registers the check, adds PHPUnit tests with passing/failing fixtures, and
documents it in docs/checks.md and the changelog.

Fixes WordPress#1356
@github-actions

Copy link
Copy Markdown

The following accounts have interacted with this PR and/or linked issues. I will continue to update these lists as activity occurs. You can also manually ask me to refresh this list by adding the props-bot label.

If you're merging code through a pull request on GitHub, copy and paste the following into the bottom of the merge commit message.

Co-authored-by: gunjanjaswal <gunjanjaswal@git.wordpress.org>
Co-authored-by: jonathanbossenger <psykro@git.wordpress.org>

To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook.

PHPMD flagged $matched as an undefined variable in look_for_removed_react_apis
since it was only created via the by-reference argument. Initialize it first.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Enhancement: Add a check to warn about React 19 incompatibilities / bundled outdated React

1 participant