Forms: Fix import map ordering for wp-build boot script#47824
Forms: Fix import map ordering for wp-build boot script#47824
Conversation
In wp-admin, _wp_footer_scripts and print_import_map both hook into
admin_print_footer_scripts at priority 10, but _wp_footer_scripts is
registered first. This causes the inline import("@wordpress/boot") call
(attached via wp_add_inline_script to a classic script) to execute before
the import map is available, resulting in "Failed to resolve module
specifier '@wordpress/boot'".
The fix intercepts the inline script at admin_enqueue_scripts time,
removes it from the classic script handle, and re-emits it as a
<script type="module"> at admin_print_footer_scripts priority 11
(after the import map).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
Are you an Automattician? Please test your changes on all WordPress.com environments to help mitigate accidental explosions.
Interested in more tips and information?
|
|
Thank you for your PR! When contributing to Jetpack, we have a few suggestions that can help us test and review your patch:
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:
If you have questions about anything, reach out in #jetpack-developers for guidance! |
… improve tests - Add page guard so the fix only runs on the Forms admin page - Use wp_print_inline_script_tag instead of raw echo for proper escaping - Add setUp to reset wp_scripts before each test - Add test verifying the fix does not run on other admin pages Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
Pull request overview
This PR fixes a wp-admin hook ordering issue that can cause wp-build pages (Jetpack Forms dashboard) to execute an inline import("@wordpress/boot") before WordPress prints the import map, leading to “Failed to resolve module specifier” errors.
Changes:
- Add a dashboard-level hook to move the inline
@wordpress/bootimport from a classic script’s inlineafterblock into a module script printed after the import map. - Add PHP unit tests covering the boot import-map ordering behavior and no-op scenarios.
- Add a changelog fragment describing the fix.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
| projects/packages/forms/src/dashboard/class-dashboard.php | Implements the runtime fix by extracting the inline boot import and re-printing it as a module script later in the footer. |
| projects/packages/forms/tests/php/dashboard/Dashboard_Boot_Import_Map_Test.php | Adds tests validating the inline-script extraction/re-emission behavior and guard conditions. |
| projects/packages/forms/changelog/fix-event-calendar-cfm | Adds a changelog entry for the wp-admin import map ordering fix. |
| $current_screen = get_current_screen(); | ||
| $is_forms_page = ( | ||
| ( isset( $_GET['page'] ) && self::FORMS_WPBUILD_ADMIN_SLUG === $_GET['page'] ) || // phpcs:ignore WordPress.Security.NonceVerification.Recommended | ||
| ( $current_screen && 'jetpack-forms-responses' === $current_screen->id ) |
There was a problem hiding this comment.
fix_boot_import_map_ordering() calls get_current_screen() unconditionally inside the admin_enqueue_scripts callback. In this repo’s WorDBless-based unit tests (see Dashboard::is_jetpack_forms_admin_page() which guards get_current_screen()), get_current_screen() can be undefined, which will cause a fatal when the hook fires. Guard with function_exists( 'get_current_screen' ) (or avoid calling it entirely and rely on self::get_admin_query_page()), and if you keep the screen check, use the correct screen id (jetpack_page_ . self::FORMS_WPBUILD_ADMIN_SLUG) rather than 'jetpack-forms-responses' so the condition works in wp-admin.
| $current_screen = get_current_screen(); | |
| $is_forms_page = ( | |
| ( isset( $_GET['page'] ) && self::FORMS_WPBUILD_ADMIN_SLUG === $_GET['page'] ) || // phpcs:ignore WordPress.Security.NonceVerification.Recommended | |
| ( $current_screen && 'jetpack-forms-responses' === $current_screen->id ) | |
| $current_screen = function_exists( 'get_current_screen' ) ? get_current_screen() : null; | |
| $is_forms_page = ( | |
| ( isset( $_GET['page'] ) && self::FORMS_WPBUILD_ADMIN_SLUG === $_GET['page'] ) || // phpcs:ignore WordPress.Security.NonceVerification.Recommended | |
| ( $current_screen && 'jetpack_page_' . self::FORMS_WPBUILD_ADMIN_SLUG === $current_screen->id ) |
|
@claude can you review this PR as well? |
|
Claude finished @enejb's task in 2m 7s —— View job PR Review
The approach is sound and directly addresses a real WordPress core hook ordering limitation. Here are my findings: Bug: Wrong screen ID (dead code)
( $current_screen && 'jetpack-forms-responses' === $current_screen->id )This condition can never be true. For the 'jetpack_page_' . self::FORMS_WPBUILD_ADMIN_SLUG,The Bug: Missing
|
| $current_screen = get_current_screen(); | ||
| $is_forms_page = ( | ||
| ( isset( $_GET['page'] ) && self::FORMS_WPBUILD_ADMIN_SLUG === $_GET['page'] ) || // phpcs:ignore WordPress.Security.NonceVerification.Recommended | ||
| ( $current_screen && 'jetpack-forms-responses' === $current_screen->id ) |
There was a problem hiding this comment.
We shouldn't be checking this part at all since it doesn't apply for this case.
- Replace inline get_current_screen() + $_GET check with the existing is_jetpack_forms_admin_page() helper which already handles the function_exists guard and correct screen ID format - Add test for preserving other inline scripts on the same handle - Use set_current_screen() in tests instead of $_GET['page'] Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Code Coverage SummaryCoverage changed in 1 file.
|
|
Closing in favour of #47823 |
Fixes FORMS-667
See also potential upstream fix:
Proposed changes
TypeError: Failed to resolve module specifier '@wordpress/boot'on the Jetpack Forms wp-build admin page._wp_footer_scripts(classic scripts) andprint_import_map(script modules) both hook intoadmin_print_footer_scriptsat priority 10, but_wp_footer_scriptsis registered first. The inlineimport("@wordpress/boot")call — attached to a classic script viawp_add_inline_script— executes before the import map is printed, so the browser cannot resolve the bare specifier.admin_enqueue_scriptstime, removes it from the classic script handle, and re-emits it as a<script type="module">atadmin_print_footer_scriptspriority 11 (after the import map).Other information
Related product discussion/links
See p1774633136941859-slack-C086RGTJT1D
Does this pull request change what data or activity we track or use?
No.
Testing instructions
jetpack_forms_alphafilter must returntrue).TypeError: Failed to resolve module specifier '@wordpress/boot'in the browser console.