diff --git a/src/wp-includes/build/pages/font-library/page-wp-admin.php b/src/wp-includes/build/pages/font-library/page-wp-admin.php index 4d41be02ae892..0ad2dcd3c720f 100644 --- a/src/wp-includes/build/pages/font-library/page-wp-admin.php +++ b/src/wp-includes/build/pages/font-library/page-wp-admin.php @@ -153,12 +153,35 @@ function wp_font_library_wp_admin_enqueue_scripts( $hook_suffix ) { // 2. It initializes the boot module as an inline script. wp_register_script( 'font-library-wp-admin-prerequisites', '', $asset['dependencies'], $asset['version'], true ); - // Add inline script to initialize the app using initSinglePage (no menuItems) + /* + * Add inline script to initialize the app using initSinglePage (no menuItems). + * The dynamic import is deferred until DOMContentLoaded so that all classic + * script dependencies of @wordpress/boot (wp-private-apis, wp-components, + * wp-theme, etc.) have finished parsing and executing before the boot module + * evaluates. Otherwise, a modulepreloaded @wordpress/boot can win the race + * against the classic-script-printing pass on fast CDN-fronted hosts in + * Chrome, evaluating before wp.theme.privateApis is defined and throwing + * "Cannot unlock an undefined object". See #65103. + */ + $init_js_function = <<<'JS' +( mountId, routes ) => { + const run = async () => { + const mod = await import( "@wordpress/boot" ); + mod.initSinglePage( { mountId, routes } ); + }; + if ( document.readyState === "loading" ) { + document.addEventListener( "DOMContentLoaded", run ); + } else { + run(); + } +} +JS; wp_add_inline_script( 'font-library-wp-admin-prerequisites', sprintf( - 'import("@wordpress/boot").then(mod => mod.initSinglePage({mountId: "%s", routes: %s}));', - 'font-library-wp-admin-app', + '( %s )( %s, %s );', + $init_js_function, + wp_json_encode( 'font-library-wp-admin-app', JSON_HEX_TAG | JSON_UNESCAPED_SLASHES ), wp_json_encode( $routes, JSON_HEX_TAG | JSON_UNESCAPED_SLASHES ) ) ); diff --git a/src/wp-includes/build/pages/font-library/page.php b/src/wp-includes/build/pages/font-library/page.php index e2849c954ba37..93bb426ae8f84 100644 --- a/src/wp-includes/build/pages/font-library/page.php +++ b/src/wp-includes/build/pages/font-library/page.php @@ -159,17 +159,40 @@ function wp_font_library_render_page() { // 2. It initializes the boot module as an inline script. wp_register_script( 'font-library-prerequisites', '', $asset['dependencies'], $asset['version'], true ); - // Add inline script to initialize the app - $init_modules = []; + /* + * Add inline script to initialize the app. + * The dynamic import is deferred until DOMContentLoaded so that all classic + * script dependencies of @wordpress/boot (wp-private-apis, wp-components, + * wp-theme, etc.) have finished parsing and executing before the boot module + * evaluates. Otherwise, a modulepreloaded @wordpress/boot can win the race + * against the classic-script-printing pass on fast CDN-fronted hosts in + * Chrome, evaluating before wp.theme.privateApis is defined and throwing + * "Cannot unlock an undefined object". See #65103. + */ + $init_modules = []; + $init_js_function = <<<'JS' +( mountId, menuItems, routes, initModules, dashboardLink ) => { + const run = async () => { + const mod = await import( "@wordpress/boot" ); + mod.init( { mountId, menuItems, routes, initModules, dashboardLink } ); + }; + if ( document.readyState === "loading" ) { + document.addEventListener( "DOMContentLoaded", run ); + } else { + run(); + } +} +JS; wp_add_inline_script( 'font-library-prerequisites', sprintf( - 'import("@wordpress/boot").then(mod => mod.init({mountId: "%s", menuItems: %s, routes: %s, initModules: %s, dashboardLink: "%s"}));', - 'font-library-app', + '( %s )( %s, %s, %s, %s, %s );', + $init_js_function, + wp_json_encode( 'font-library-app', JSON_HEX_TAG | JSON_UNESCAPED_SLASHES ), wp_json_encode( $menu_items, JSON_HEX_TAG | JSON_UNESCAPED_SLASHES ), wp_json_encode( $routes, JSON_HEX_TAG | JSON_UNESCAPED_SLASHES ), wp_json_encode( $init_modules, JSON_HEX_TAG | JSON_UNESCAPED_SLASHES ), - esc_url( admin_url( '/' ) ) + wp_json_encode( admin_url( '/' ), JSON_HEX_TAG | JSON_UNESCAPED_SLASHES ) ) ); diff --git a/src/wp-includes/build/pages/options-connectors/page-wp-admin.php b/src/wp-includes/build/pages/options-connectors/page-wp-admin.php index 3f3048b8fb98b..4a9c19cf573a4 100644 --- a/src/wp-includes/build/pages/options-connectors/page-wp-admin.php +++ b/src/wp-includes/build/pages/options-connectors/page-wp-admin.php @@ -153,12 +153,35 @@ function wp_options_connectors_wp_admin_enqueue_scripts( $hook_suffix ) { // 2. It initializes the boot module as an inline script. wp_register_script( 'options-connectors-wp-admin-prerequisites', '', $asset['dependencies'], $asset['version'], true ); - // Add inline script to initialize the app using initSinglePage (no menuItems) + /* + * Add inline script to initialize the app using initSinglePage (no menuItems). + * The dynamic import is deferred until DOMContentLoaded so that all classic + * script dependencies of @wordpress/boot (wp-private-apis, wp-components, + * wp-theme, etc.) have finished parsing and executing before the boot module + * evaluates. Otherwise, a modulepreloaded @wordpress/boot can win the race + * against the classic-script-printing pass on fast CDN-fronted hosts in + * Chrome, evaluating before wp.theme.privateApis is defined and throwing + * "Cannot unlock an undefined object". See #65103. + */ + $init_js_function = <<<'JS' +( mountId, routes ) => { + const run = async () => { + const mod = await import( "@wordpress/boot" ); + mod.initSinglePage( { mountId, routes } ); + }; + if ( document.readyState === "loading" ) { + document.addEventListener( "DOMContentLoaded", run ); + } else { + run(); + } +} +JS; wp_add_inline_script( 'options-connectors-wp-admin-prerequisites', sprintf( - 'import("@wordpress/boot").then(mod => mod.initSinglePage({mountId: "%s", routes: %s}));', - 'options-connectors-wp-admin-app', + '( %s )( %s, %s );', + $init_js_function, + wp_json_encode( 'options-connectors-wp-admin-app', JSON_HEX_TAG | JSON_UNESCAPED_SLASHES ), wp_json_encode( $routes, JSON_HEX_TAG | JSON_UNESCAPED_SLASHES ) ) ); diff --git a/src/wp-includes/build/pages/options-connectors/page.php b/src/wp-includes/build/pages/options-connectors/page.php index 6009dbb2570a9..c5d70c4e41b27 100644 --- a/src/wp-includes/build/pages/options-connectors/page.php +++ b/src/wp-includes/build/pages/options-connectors/page.php @@ -159,17 +159,40 @@ function wp_options_connectors_render_page() { // 2. It initializes the boot module as an inline script. wp_register_script( 'options-connectors-prerequisites', '', $asset['dependencies'], $asset['version'], true ); - // Add inline script to initialize the app - $init_modules = []; + /* + * Add inline script to initialize the app. + * The dynamic import is deferred until DOMContentLoaded so that all classic + * script dependencies of @wordpress/boot (wp-private-apis, wp-components, + * wp-theme, etc.) have finished parsing and executing before the boot module + * evaluates. Otherwise, a modulepreloaded @wordpress/boot can win the race + * against the classic-script-printing pass on fast CDN-fronted hosts in + * Chrome, evaluating before wp.theme.privateApis is defined and throwing + * "Cannot unlock an undefined object". See #65103. + */ + $init_modules = []; + $init_js_function = <<<'JS' +( mountId, menuItems, routes, initModules, dashboardLink ) => { + const run = async () => { + const mod = await import( "@wordpress/boot" ); + mod.init( { mountId, menuItems, routes, initModules, dashboardLink } ); + }; + if ( document.readyState === "loading" ) { + document.addEventListener( "DOMContentLoaded", run ); + } else { + run(); + } +} +JS; wp_add_inline_script( 'options-connectors-prerequisites', sprintf( - 'import("@wordpress/boot").then(mod => mod.init({mountId: "%s", menuItems: %s, routes: %s, initModules: %s, dashboardLink: "%s"}));', - 'options-connectors-app', + '( %s )( %s, %s, %s, %s, %s );', + $init_js_function, + wp_json_encode( 'options-connectors-app', JSON_HEX_TAG | JSON_UNESCAPED_SLASHES ), wp_json_encode( $menu_items, JSON_HEX_TAG | JSON_UNESCAPED_SLASHES ), wp_json_encode( $routes, JSON_HEX_TAG | JSON_UNESCAPED_SLASHES ), wp_json_encode( $init_modules, JSON_HEX_TAG | JSON_UNESCAPED_SLASHES ), - esc_url( admin_url( '/' ) ) + wp_json_encode( admin_url( '/' ), JSON_HEX_TAG | JSON_UNESCAPED_SLASHES ) ) );