Skip to content

WP Build Polyfills: Inline keyedReducer for @wordpress/notices 5.45+#48743

Merged
CGastrell merged 4 commits into
trunkfrom
change/fix-polyfills-wp-monorepo-upgrade
May 18, 2026
Merged

WP Build Polyfills: Inline keyedReducer for @wordpress/notices 5.45+#48743
CGastrell merged 4 commits into
trunkfrom
change/fix-polyfills-wp-monorepo-upgrade

Conversation

@CGastrell

Copy link
Copy Markdown
Contributor

Fixes runtime breakage observed in the #48405 smoke test (#48405 (comment)).

Proposed changes

  • Add a webpack loader (wp-data-keyed-reducer-loader.js) that rewrites import { keyedReducer } from '@wordpress/data' inside @wordpress/notices' bundled store/reducer.{mjs,cjs} to import from a local copy of the helper.
  • Ship the helper at src/internal/keyed-reducer.js (byte-identical to upstream's @wordpress/data 10.45.0 keyedReducer).
  • Add a regression test that builds the polyfill and asserts (a) the bundle never reaches for wp.data.keyedReducer and (b) the bundled core/notices reducer behaves correctly with a stubbed window.wp.data that omits keyedReducer.

The fix is a no-op against today's pinned @wordpress/notices 5.44.0 (its bundled reducer uses an internal on-sub-key helper instead) — the loader's test only matches the file the upstream refactor moves the import into. Other @wordpress/data symbols (createReduxStore, register, useDispatch, useSelect) continue to be externalized through the standard @wordpress/dependency-extraction-webpack-plugin path so the notices store keeps registering in the shared window.wp.data registry.

Root cause

@wordpress/data 10.45.0 added keyedReducer as a public export and Gutenberg consolidated the duplicated copies previously maintained in @wordpress/core-data and @wordpress/notices (WordPress/gutenberg#77364). @wordpress/notices 5.45.0's store/reducer now does:

import { keyedReducer } from '@wordpress/data';

wp-build-polyfills' IIFE bundle for @wordpress/notices externalizes @wordpress/data to the runtime window.wp.data global so the notices store registers in the shared registry. WordPress Core today still ships @wordpress/data below 10.45.0, so the bundled wp.data.keyedReducer(...) call at module load throws "n(...).keyedReducer is not a function" — and once the IIFE has thrown, window.wp.notices is left unassigned, so the boot module's downstream <SnackbarNotices /> render trips on "can't access property "SnackbarNotices", r is undefined".

A Rule.resolve.alias mapping for @wordpress/data doesn't help: the DEP plugin's externals callback short-circuits the request before module resolution, so per-rule alias entries for @wordpress/data are bypassed. Rewriting the import in source (this PR's loader) is the only path that survives the externals pipeline.

Why not pin @wordpress/notices to 5.44

Renovate would re-bump it next week and the same failure mode would recur. Inlining keyedReducer is robust against future minor-version bumps of @wordpress/notices for the same regression class.

Related product discussion/links

Does this pull request change what data or activity we track or use?

No.

Testing instructions

  1. Check out this branch.
  2. Adopt PR Update wordpress monorepo #48405's lockfile snapshot (so @wordpress/notices resolves to 5.45.0): on the branch, fetch pnpm-lock.yaml from Update wordpress monorepo #48405's HEAD (commit 67217d91) into the worktree root, then pnpm install --prefer-offline.
  3. pnpm jetpack build packages/wp-build-polyfills.
  4. cd projects/packages/wp-build-polyfills && pnpm test — all 12 tests should pass.
  5. Optional manual check: grep keyedReducer build/scripts/notices/index.js. The reducer call should reference an inlined local export, not the wp.data external.

To reproduce the failure without the fix, comment out the wpDataKeyedReducerRule line from webpack.config.js, rebuild, and re-run the tests — the regression test "must produce a notices reducer that works without wp.data.keyedReducer" fails with a TypeError from inside the vm-evaluated bundle.

After this lands, #48405 should rebase / re-run its smoke test on advanced-krill.jurassic.ninja (or successor) and the Forms admin page should load cleanly.

@github-actions

github-actions Bot commented May 12, 2026

Copy link
Copy Markdown
Contributor

Are you an Automattician? Please test your changes on all WordPress.com environments to help mitigate accidental explosions.

  • To test on WoA, go to the Plugins menu on a WoA dev site. Click on the "Upload" button and follow the upgrade flow to be able to upload, install, and activate the Jetpack Beta plugin. Once the plugin is active, go to Jetpack > Jetpack Beta, select your plugin (Jetpack or WordPress.com Site Helper), and enable the change/fix-polyfills-wp-monorepo-upgrade branch.
  • To test on Simple, run the following command on your sandbox:
bin/jetpack-downloader test jetpack change/fix-polyfills-wp-monorepo-upgrade
bin/jetpack-downloader test jetpack-mu-wpcom-plugin change/fix-polyfills-wp-monorepo-upgrade

Interested in more tips and information?

  • In your local development environment, use the jetpack rsync command to sync your changes to a WoA dev blog.
  • Read more about our development workflow here: PCYsg-eg0-p2
  • Figure out when your changes will be shipped to customers here: PCYsg-eg5-p2

@github-actions

github-actions Bot commented May 12, 2026

Copy link
Copy Markdown
Contributor

Thank you for your PR!

When contributing to Jetpack, we have a few suggestions that can help us test and review your patch:

  • ✅ Include a description of your PR changes.
  • ✅ Add a "[Status]" label (In Progress, Needs Review, ...).
  • ✅ Add testing instructions.
  • ✅ Specify whether this PR includes any changes to data or privacy.
  • ✅ Add changelog entries to affected projects

This comment will be updated as you work on your PR and make changes. If you think that some of those checks are not needed for your PR, please explain why you think so. Thanks for cooperation 🤖


Follow this PR Review Process:

  1. Ensure all required checks appearing at the bottom of this PR are passing.
  2. Make sure to test your changes on all platforms that it applies to. You're responsible for the quality of the code you ship.
  3. You can use GitHub's Reviewers functionality to request a review.
  4. When it's reviewed and merged, you will be pinged in Slack to deploy the changes to WordPress.com simple once the build is done.

If you have questions about anything, reach out in #jetpack-developers for guidance!


Jetpack plugin:

The Jetpack plugin has different release cadences depending on the platform:

  • WordPress.com Simple releases happen as soon as you deploy your changes after merging this PR (PCYsg-Jjm-p2).
  • WoA releases happen weekly.
  • Releases to self-hosted sites happen monthly:
    • Scheduled release: June 2, 2026
    • Code freeze: June 1, 2026

If you have any questions about the release process, please ask in the #jetpack-releases channel on Slack.


Backup plugin:

No scheduled milestone found for this plugin.

If you have any questions about the release process, please ask in the #jetpack-releases channel on Slack.


Videopress plugin:

No scheduled milestone found for this plugin.

If you have any questions about the release process, please ask in the #jetpack-releases channel on Slack.


Mu Wpcom plugin:

  • Next scheduled release: WordPress.com Simple releases happen semi-continuously (PCYsg-Jjm-p2)

If you have any questions about the release process, please ask in the #jetpack-releases channel on Slack.


Wpcomsh plugin:

  • Next scheduled release: Atomic deploys happen twice daily on weekdays (p9o2xV-2EN-p2)

If you have any questions about the release process, please ask in the #jetpack-releases channel on Slack.

@CGastrell CGastrell marked this pull request as ready for review May 12, 2026 21:27
@jp-launch-control

jp-launch-control Bot commented May 12, 2026

Copy link
Copy Markdown

Code Coverage Summary

This PR did not change code coverage!

That could be good or bad, depending on the situation. Everything covered before, and still is? Great! Nothing was covered before? Not so great. 🤷

Full summary · PHP report · JS report

@CGastrell

Copy link
Copy Markdown
Contributor Author

Thanks for the second-opinion review — applied all three nits in 1796e43418f.

What changed:

  • NIT 1 — Broaden loader rule path (option a). The webpack rule's test regex now matches both @wordpress/notices/build*/store/reducer.{mjs,cjs} and @wordpress/core-data/build*/queried-data/reducer.{mjs,cjs}. The polyfill doesn't currently bundle core-data, so this is preventive — a future polyfill addition that pulls in core-data would otherwise have silently re-hit the same bug. Picked (a) over (b) (drop path test entirely + lean on the loader's own bail-out) for the smaller perf cost and the explicit, greppable allow-list. Added a comment next to the rule documenting the contract (defensive loader + restricted path test) and the migration path for future additions.

  • NIT 2 — Production-minified bundle. Ran pnpm run build-production and grepped the resulting build/scripts/notices/index.js for any residual keyedReducer reference: zero hits. Minifier (terser) collapses the local shim's exports into anonymous closures and renames window["wp"]["data"].X accesses through aliased locals.

    Extended the regression test (tests/js/keyed-reducer-inlined.test.js) so it now runs the same three assertions (no wp.data.keyedReducer static reference, no stray keyedReducer token, working reducer under a stubbed wp.data) against both the dev and production bundles. The production block spawns a fresh webpack-cli invocation with NODE_ENV=production into a sibling tree (build-prod-test/) via a new WP_BUILD_POLYFILLS_OUTPUT_BASE env var on the webpack config, so it doesn't clobber build/. build-prod-test/ is gitignored.

  • NIT 3a — CI coverage. The package previously had no test-js composer script, which meant the tests.yml matrix's composer run "$TEST_SCRIPT" step skipped the regression test entirely on PRs touching this package (the loop only runs scripts that are declared in composer.json). Added test-js as pnpm run build && pnpm run test so a CI build matrix run on this PR (and future ones touching the package) will actually exercise the regression test. Locally verified: composer run test-js → 15 tests pass, 0 fail.

  • NIT 3b — Changelog. Expanded the entry to (1) link the upstream consolidation PR (Data: Export and consolidate 'onSubKey' helper WordPress/gutenberg#77364), (2) name the workaround framing explicitly so the next reader doesn't mistake this for a permanent solution, and (3) flag the loader rule's currently-scoped path list (notices + core-data) so future polyfill additions know to extend it.

Nothing intentionally skipped.

New HEAD: 1796e43418f9125558a216a82ab0c24b5215d4c1

Notes:

  • The lockfile currently pins @wordpress/notices to 5.44.0 (which still uses the local onSubKey and not keyedReducer), so the loader bails out as a no-op against today's resolved tree and the regression test exercises a clean-by-construction bundle. The fix lands the moment the lockfile floats @wordpress/notices to ≥ 5.45.0 (or core-data to ≥ 7.45.0). That dep bump is explicitly out of scope here.
  • ESLint + Prettier clean; husky pre-commit ran.

@github-actions github-actions Bot added [Plugin] Backup A plugin that allows users to save every change and get back online quickly with one-click restores. [Plugin] Jetpack Issues about the Jetpack plugin. https://wordpress.org/plugins/jetpack/ [Plugin] mu wpcom jetpack-mu-wpcom plugin [Plugin] VideoPress A standalone plugin to add high-quality VideoPress videos to your site. [Plugin] Wpcomsh labels May 13, 2026
dhasilva
dhasilva previously approved these changes May 13, 2026

@dhasilva dhasilva left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. At first I thought "why not bundle wordpress/data?", but that is not possible because it is a registry, so I get now why the PR only extracted the keyed-reducer.

It is a good idea to flag this upstream, this kind of shared functionality should probably live in some other package to avoid this kind of problem.

@CGastrell CGastrell force-pushed the change/fix-polyfills-wp-monorepo-upgrade branch from 6182de1 to 8aded42 Compare May 13, 2026 11:34
CGastrell and others added 4 commits May 18, 2026 10:20
@wordpress/notices >= 5.45.0 imports keyedReducer from @wordpress/data,
which only added that export in @wordpress/data 10.45.0 (Gutenberg
consolidation, WordPress/gutenberg#77364). The polyfill externalizes
@wordpress/data to the runtime window.wp.data global so the notices
store registers in the shared registry. On sites that still ship an
older @wordpress/data (current WordPress Core), the bundled call to
window.wp.data.keyedReducer threw at load time, which cascaded into a
SnackbarNotices undefined error in the @wordpress/boot polyfill module.

Add a webpack loader that rewrites the keyedReducer named import in
the @wordpress/notices reducer source to a local copy bundled with
the polyfill, leaving every other @wordpress/data symbol externalized
as before. A custom loader rather than a Rule.resolve.alias is needed
because @wordpress/dependency-extraction-webpack-plugin externalizes
the request before module resolution, bypassing per-rule aliases.
…e regression test

Address second-opinion review nits on the wp-data keyedReducer inlining fix:

- Broaden the loader rule test regex to also match @wordpress/core-data
  queried-data reducer paths so a future polyfill addition that pulls
  in core-data does not silently re-hit the same bug. Document the
  contract (defensive loader + restricted path test) in a comment next
  to the rule.
- Extend the regression test to run against BOTH dev and production
  (minified) bundle output. The production block runs a fresh webpack
  build into a sibling tree via WP_BUILD_POLYFILLS_OUTPUT_BASE so it
  does not clobber build/, then asserts no static wp.data.keyedReducer
  reference and no stray keyedReducer token survives minification.
- Add a test-js composer script (build-then-test) so the CI matrix in
  .github/workflows/tests.yml actually runs this regression test for
  PRs touching the package.
- Expand the changelog entry: link the upstream consolidation PR
  (WordPress/gutenberg#77364), frame the loader as a workaround pending
  a longer-term decision, and note that future polyfill additions
  importing keyedReducer from @wordpress/data need to extend the rule
  and test.

Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>
The previous commit added a `test-js` script and bumped the package
reference SHA in `projects/packages/wp-build-polyfills/composer.json`,
which left the five plugin composer.lock files (backup, jetpack,
mu-wpcom-plugin, videopress, wpcomsh) out of sync.
@CGastrell CGastrell force-pushed the change/fix-polyfills-wp-monorepo-upgrade branch from 772715f to db10d55 Compare May 18, 2026 13:21
@CGastrell CGastrell merged commit 11ae5a2 into trunk May 18, 2026
71 of 72 checks passed
@CGastrell CGastrell deleted the change/fix-polyfills-wp-monorepo-upgrade branch May 18, 2026 13:47
yuliyan pushed a commit that referenced this pull request May 20, 2026
…48743)

* WP Build Polyfills: Inline keyedReducer for @wordpress/notices 5.45+

@wordpress/notices >= 5.45.0 imports keyedReducer from @wordpress/data,
which only added that export in @wordpress/data 10.45.0 (Gutenberg
consolidation, WordPress/gutenberg#77364). The polyfill externalizes
@wordpress/data to the runtime window.wp.data global so the notices
store registers in the shared registry. On sites that still ship an
older @wordpress/data (current WordPress Core), the bundled call to
window.wp.data.keyedReducer threw at load time, which cascaded into a
SnackbarNotices undefined error in the @wordpress/boot polyfill module.

Add a webpack loader that rewrites the keyedReducer named import in
the @wordpress/notices reducer source to a local copy bundled with
the polyfill, leaving every other @wordpress/data symbol externalized
as before. A custom loader rather than a Rule.resolve.alias is needed
because @wordpress/dependency-extraction-webpack-plugin externalizes
the request before module resolution, bypassing per-rule aliases.

* wp-build-polyfills: broaden keyedReducer loader rule + production-mode regression test

Address second-opinion review nits on the wp-data keyedReducer inlining fix:

- Broaden the loader rule test regex to also match @wordpress/core-data
  queried-data reducer paths so a future polyfill addition that pulls
  in core-data does not silently re-hit the same bug. Document the
  contract (defensive loader + restricted path test) in a comment next
  to the rule.
- Extend the regression test to run against BOTH dev and production
  (minified) bundle output. The production block runs a fresh webpack
  build into a sibling tree via WP_BUILD_POLYFILLS_OUTPUT_BASE so it
  does not clobber build/, then asserts no static wp.data.keyedReducer
  reference and no stray keyedReducer token survives minification.
- Add a test-js composer script (build-then-test) so the CI matrix in
  .github/workflows/tests.yml actually runs this regression test for
  PRs touching the package.
- Expand the changelog entry: link the upstream consolidation PR
  (WordPress/gutenberg#77364), frame the loader as a workaround pending
  a longer-term decision, and note that future polyfill additions
  importing keyedReducer from @wordpress/data need to extend the rule
  and test.

Co-Authored-By: Claude Opus 4.7 (1M context) <[email protected]>

* wp-build-polyfills: regenerate consumer composer.lock files

The previous commit added a `test-js` script and bumped the package
reference SHA in `projects/packages/wp-build-polyfills/composer.json`,
which left the five plugin composer.lock files (backup, jetpack,
mu-wpcom-plugin, videopress, wpcomsh) out of sync.

* Add changelog entries for regenerated composer.lock files

---------

Co-authored-by: Claude Opus 4.7 (1M context) <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

[Package] Wp Build Polyfills [Plugin] Backup A plugin that allows users to save every change and get back online quickly with one-click restores. [Plugin] Jetpack Issues about the Jetpack plugin. https://wordpress.org/plugins/jetpack/ [Plugin] mu wpcom jetpack-mu-wpcom plugin [Plugin] VideoPress A standalone plugin to add high-quality VideoPress videos to your site. [Plugin] Wpcomsh [Tests] Includes Tests

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants