Skip to content

WP Build Polyfills: own the screen-ID alias ordering in one place - #52583

Merged
CGastrell merged 4 commits into
trunkfrom
update/jetpack-2689-wp-build-screen-id-helper
Sep 23, 2026
Merged

CGastrell merged 4 commits into
trunkfrom
update/jetpack-2689-wp-build-screen-id-helper

Conversation

@CGastrell

@CGastrell CGastrell commented Sep 21, 2026 •

Copy link
Copy Markdown
Contributor

Fixes JETPACK-2689

Proposed changes

  • Adds WP_Build_Screen_Id::load_with_alias() to packages/wp-build-polyfills. It takes the consumer's alias callback, its restore callback, and a callable that loads wp-build's generated file, and owns nothing but their order:
add_action( 'admin_enqueue_scripts', $alias );
$load_wp_build();
add_action( 'admin_enqueue_scripts', $restore );
  • Nine packages — Activity Log, Backup, My Jetpack, Newsletter, Podcast, Publicize, Search, SEO, VideoPress — now route their load through it from one private wrapper method.

Why the ordering and nothing else

The alias exists because wp-build's generated enqueue callback is gated on $screen->id matching the page's build-time slug. Aliasing without restoring leaves every later hook reading a screen that does not exist — JITM builds its message path from it on admin_notices.

Five of the nine shipped with no restore at all and nobody noticed, because nothing on the page looks wrong. That is an ordering failure, so the ordering is what this centralizes.

The screen-ID swap itself never broke, so it stays in each package, byte-identical to trunk. No hunk in this PR touches an alias_screen_id_for_wp_build() or restore_screen_id_after_wp_build() body, and each package's existing round-trip test passes unmodified — which is the check that they really are untouched.

The trade-off, stated plainly

Each package grows ~31 lines to centralize three. That is because AGENTS.md requires a method_exists() guard and a working fallback when calling a newly added shared-package method: the jetpack-autoloader picks the highest version of each package independently, so a newer consumer can run against an older wp-build-polyfills. JETPACK-2649 was this exact race in production. Dropping the fallback is worse than it sounds — with no alias the generated check never fires, while is_wp_build_dashboard_active() still returns true because build/ exists, so the page renders empty.

A first draft also shared the swap itself. That added ~400 lines and removed no duplication, since the guard forced the original implementation to stay at all nine call sites as a fallback. This version is the half that pays for itself.

Out of scope: plugins/boost and the Jetpack plugin's AI page keep the old pattern — both have work in flight from other people. Worth migrating once that lands.

Related product discussion/links

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

No. Internal refactor; ten patch/changed changelog entries, no dependent-plugin entries.

Testing instructions

Run here:

  • jetpack test php packages/wp-build-polyfills — passes. Two tests: hook priority, and that the generated check sees the aliased ID while anything after the restore sees the real one. The second fails if the two add_action() calls are reordered.
  • jetpack test php packages/seo — passes, with the round-trip test unmodified.
  • jetpack test php packages/search — passes. Dashboard_Wp_Build_Test::test_maybe_load_wp_build_aliases_the_screen_only_for_the_generated_check drives the real maybe_load_wp_build() against a stub build file. It fails if either hook is dropped, if the two are hooked out of order, or if both move off the default priority.
  • The agent that wrote this ran jetpack test php and jetpack phan across all ten packages; Phan is clean on all ten and PHPCS is clean on every touched file.

Known unrelated failure: packages/podcast's tests/php/blocks/Podcast_Episode_Block_Test.php fails 14 tests on this branch. It fails identically without this change, and this PR touches only class-admin-page.php in that package. Not introduced here, not fixed here.

To check the behaviour by hand, on any site with a wp-build dashboard: open it and confirm the page still loads its scripts, then confirm get_current_screen()->id reads the real screen ID in an admin_notices callback rather than the build-time slug.

🤖 Generated with Claude Code

…ld dashboards

Nine packages (Activity Log, Backup, My Jetpack, Newsletter, Podcast,
Publicize, Search, SEO, VideoPress) each carried their own copy of the
three-line sequence that hooks a wp-build dashboard's screen-ID alias
before its generated enqueue check and the restore after. Getting the
restore dropped, or the two hooked out of order, is the actual bug
history here (JETPACK-2689): five of the nine originally shipped
alias-with-no-restore, invisibly breaking JITM's message path and
Core's pagenow.

Add WP_Build_Screen_Id::load_with_alias() to wp-build-polyfills. It
takes each package's own alias/restore callables and owns only their
order, so a new call site can't reproduce that ordering bug. Each
package's alias_screen_id_for_wp_build() / restore_screen_id_after_wp_build()
are unchanged from trunk - the screen-ID swap itself never broke, so
there is nothing to centralize there.

Each package's orchestration call site is guarded with method_exists()
and falls back to the original three-line sequence per AGENTS.md,
since the jetpack-autoloader can still serve an older
wp-build-polyfills without the helper (JETPACK-2649 was this exact
autoloader race in production).

Boost and the Jetpack plugin's AI page keep the old pattern; someone
else is already working in them.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@CGastrell
CGastrell requested a review from a team as a code owner September 21, 2026 21:48
@CGastrell CGastrell added the [Status] Needs Review This PR is ready for review. label Sep 21, 2026
@CGastrell CGastrell self-assigned this Sep 21, 2026
@github-actions

github-actions Bot commented Sep 21, 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 update/jetpack-2689-wp-build-screen-id-helper branch.
  • To test on Simple, run the following command on your sandbox:
bin/jetpack-downloader test jetpack update/jetpack-2689-wp-build-screen-id-helper
bin/jetpack-downloader test jetpack-mu-wpcom-plugin update/jetpack-2689-wp-build-screen-id-helper

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

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!

@jp-launch-control

jp-launch-control Bot commented Sep 21, 2026 •

Copy link
Copy Markdown

Code Coverage Summary

Coverage changed in 9 files. Only the first 5 are listed here.

File Coverage Δ% Δ Uncovered
projects/packages/activity-log/src/class-jetpack-activity-log.php 68/102 (66.67%) 0.36% 3 ❤️‍🩹
projects/packages/backup/src/class-jetpack-backup.php 432/512 (84.38%) -0.29% 3 ❤️‍🩹
projects/packages/my-jetpack/src/class-initializer.php 381/461 (82.65%) -0.28% 3 ❤️‍🩹
projects/packages/newsletter/src/class-settings.php 152/254 (59.84%) 0.42% 3 ❤️‍🩹
projects/packages/podcast/src/class-admin-page.php 86/124 (69.35%) 0.06% 3 ❤️‍🩹

1 file is newly checked for coverage.

File Coverage
projects/packages/wp-build-polyfills/src/class-wp-build-screen-id.php 3/3 (100.00%) 💚

Full summary · PHP report · JS report

The version-skew rationale was copy-pasted verbatim into all nine
consumers. Each site keeps a one-line local reason instead.

wp-build-polyfills adds a public class and method, so its entry is
minor/added, matching the package's precedent for a new helper.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@CGastrell

Copy link
Copy Markdown
Contributor Author

Reviewed at standard depth. No blockers. Three suggestions; two are fixed in f33cc26.

Fixed

  1. The wp-build-polyfills changelog entry was patch/changed, but this PR adds a public class and a public static method. Now minor/added, matching the package's own precedent — 0.3.0 and 0.4.0 both used Added for a new public helper. The nine consumer entries stay patch/changed.

  2. The four-line version-skew rationale was copy-pasted verbatim into all nine consumers — AGENTS.md § Comments, "a block that would survive copy-paste verbatim into another file". Each site now keeps a one-line local reason. The require_wp_build_with_screen_alias() docblock in my-jetpack and search also duplicated a three-line summary; both now match the other seven. Net −29 lines, no behavior change.

Left open

  1. @see WP_Build_Screen_Id::load_with_alias() in backup, newsletter, publicize and videopress uses a short name those four files never import — they reference the class by inline FQN, matching how each already references WP_Build_Polyfills. The @see therefore resolves against the file's own namespace and points at nothing. Nothing in the repo checks @see targets, so this only costs an IDE click-through. Worth folding in next time those files are touched.

Also checked and clear: the method_exists() guard (::class does not autoload; method_exists() returns false rather than fataling), the closure-scope change around require_once $build_index in my-jetpack and search, hook ordering in all nine, the untouched round-trip tests, and the out-of-scope list — git grep confirms only plugins/boost and the Jetpack AI page remain on the old pattern.

— Terminator

@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.

Reviewed at thorough depth. The refactor preserves behaviour: at all nine sites the helper hooks the same alias and restore callables, in the same order and at the same default priority, from the same admin_menu callback as trunk. Each package's generated page-wp-admin.php enqueue callback is still the only thing hooked inside the window. I have three small suggestions, none of them blocking.

Verdict: Minor issues, can merge after addressing.

Tests: jp test php passes for wp-build-polyfills and all nine consumers. That includes Podcast, whose 213 tests all passed here. jp phan is clean on all ten packages, and PHPCS is clean on the changed files. As a check on the new test, I reordered and dropped hooks in load_with_alias(), and every variant failed test_generated_check_sees_only_the_aliased_id.

Version skew: all nine packages require wp-build-polyfills. The jetpack-autoloader picks a version for each class separately, so an older copy can't hide a class it doesn't ship. That makes the method_exists() guards extra caution rather than a requirement here. They're harmless, though, and they follow AGENTS.md.

Findings: see inline comments.

Generated by Claude.

Comment thread projects/packages/wp-build-polyfills/src/class-wp-build-screen-id.php Outdated
Comment thread projects/packages/search/src/dashboard/class-dashboard.php
Comment thread projects/packages/wp-build-polyfills/tests/php/WP_Build_Screen_Id_Test.php Outdated
Core prints pagenow in admin-header.php before admin_enqueue_scripts
fires, so the alias never reaches it. JITM is the only casualty.

Search had no test reaching maybe_load_wp_build(), which turned the
coverage check red. A wp_build_index() seam, beside the existing
render-function seam, lets a test load a stub build file.

The registration test only failed when the restore was dropped, which
the behavioural test also catches. Removed with its three spies.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@CGastrell

Copy link
Copy Markdown
Contributor Author

All three addressed in 24299f5.

  1. pagenow — confirmed, Core prints it at admin-header.php:107, before admin_enqueue_scripts at :123. Your wording applied, and the PR description had the same claim.
  2. Search coverage — added a wp_build_index() seam beside the existing render-function seam, plus an ordering test. It kills all four of your mutations.
  3. Registration test — reproduced your result and removed it, with its three spies.

Thanks for the mutation run.

— Terminator

@CGastrell
CGastrell merged commit 4b27742 into trunk Sep 23, 2026
120 checks passed
@CGastrell
CGastrell deleted the update/jetpack-2689-wp-build-screen-id-helper branch September 23, 2026 17:57
@github-actions github-actions Bot removed the [Status] Needs Review This PR is ready for review. label Sep 23, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants