diff --git a/src/js/_enqueues/lib/codemirror/javascript-lint.js b/src/js/_enqueues/lib/codemirror/javascript-lint.js index 592d077b80914..2c96798a20ae3 100644 --- a/src/js/_enqueues/lib/codemirror/javascript-lint.js +++ b/src/js/_enqueues/lib/codemirror/javascript-lint.js @@ -30,6 +30,7 @@ import CodeMirror from 'codemirror'; * @property {boolean} [es3] - "This option tells JSHint that your code needs to adhere to ECMAScript 3 specification. Use this option if you need your program to be executable in older browsers—such as Internet Explorer 6/7/8/9—and other legacy JavaScript environments." * @property {boolean} [module] - "This option informs JSHint that the input code describes an ECMAScript 6 module. All module code is interpreted as strict mode code." * @property {'implied'} [strict] - "This option requires the code to run in ECMAScript 5's strict mode." + * @property {string} [espreeModuleUrl] - The URL to the espree script module. */ /** @@ -42,9 +43,13 @@ import CodeMirror from 'codemirror'; * @returns {Promise} */ async function validator( text, options ) { + if ( ! options.espreeModuleUrl ) { + return []; + } + const errors = /** @type {CodeMirrorLintError[]} */ []; try { - const espree = await import( /* webpackIgnore: true */ 'espree' ); + const espree = await import( /* webpackIgnore: true */ options.espreeModuleUrl ); espree.parse( text, { ...getEspreeOptions( options ), loc: true, diff --git a/src/js/_enqueues/wp/code-editor.js b/src/js/_enqueues/wp/code-editor.js index 86d5e03254166..ed8be9d6a5580 100644 --- a/src/js/_enqueues/wp/code-editor.js +++ b/src/js/_enqueues/wp/code-editor.js @@ -2,6 +2,8 @@ * @output wp-admin/js/code-editor.js */ +/* global console */ + /* eslint-env es2020 */ if ( 'undefined' === typeof window.wp ) { @@ -412,6 +414,10 @@ if ( 'undefined' === typeof window.wp.codeEditor ) { * @return {CodeEditorInstance} Instance. */ wp.codeEditor.initialize = function initialize( textarea, settings ) { + if ( document.readyState === 'loading' ) { + console.warn( 'wp.codeEditor.initialize() ran too early. Invoke this function in a `DOMContentLoaded` event listener.' ); + } + let $textarea; if ( 'string' === typeof textarea ) { $textarea = $( '#' + textarea ); diff --git a/src/wp-includes/class-wp-scripts.php b/src/wp-includes/class-wp-scripts.php index cb37b2b653877..6f633d465bb2c 100644 --- a/src/wp-includes/class-wp-scripts.php +++ b/src/wp-includes/class-wp-scripts.php @@ -885,7 +885,7 @@ public function add_data( $handle, $key, $value ) { sprintf( /* translators: 1: $strategy, 2: $handle */ __( 'Invalid strategy `%1$s` defined for `%2$s` during script registration.' ), - $value, + is_string( $value ) ? $value : gettype( $value ), $handle ), '6.3.0' @@ -897,7 +897,7 @@ public function add_data( $handle, $key, $value ) { sprintf( /* translators: 1: $strategy, 2: $handle */ __( 'Cannot supply a strategy `%1$s` for script `%2$s` because it is an alias (it lacks a `src` value).' ), - $value, + is_string( $value ) ? $value : gettype( $value ), $handle ), '6.3.0' diff --git a/src/wp-includes/functions.wp-scripts.php b/src/wp-includes/functions.wp-scripts.php index 59e4e54a1a1ad..5e9589252124b 100644 --- a/src/wp-includes/functions.wp-scripts.php +++ b/src/wp-includes/functions.wp-scripts.php @@ -71,19 +71,30 @@ function _wp_scripts_maybe_doing_it_wrong( $function_name, $handle = '' ) { /** * Adds the data for the recognized args and warns for unrecognized args. * + * @see wp_enqueue_script() + * @see wp_register_script() + * * @ignore * @since 7.0.0 * * @param WP_Scripts $wp_scripts WP_Scripts instance. * @param string $handle Script handle. * @param array $args Array of extra args for the script. + * + * @phpstan-param non-empty-string $handle + * @phpstan-param array{ + * in_footer?: bool, + * strategy?: 'async'|'defer', + * fetchpriority?: 'low'|'auto'|'high', + * module_dependencies?: array, + * } $args */ -function _wp_scripts_add_args_data( WP_Scripts $wp_scripts, string $handle, array $args ) { +function _wp_scripts_add_args_data( WP_Scripts $wp_scripts, string $handle, array $args ): void { $allowed_keys = array( 'strategy', 'in_footer', 'fetchpriority', 'module_dependencies' ); $unknown_keys = array_diff( array_keys( $args ), $allowed_keys ); if ( ! empty( $unknown_keys ) ) { $trace = debug_backtrace( DEBUG_BACKTRACE_IGNORE_ARGS, 2 ); - $function_name = ( $trace[1]['class'] ?? '' ) . ( $trace[1]['type'] ?? '' ) . $trace[1]['function']; + $function_name = ( $trace[1]['class'] ?? '' ) . ( $trace[1]['type'] ?? '' ) . ( $trace[1]['function'] ?? __FUNCTION__ ); _doing_it_wrong( $function_name, sprintf( @@ -97,7 +108,8 @@ function _wp_scripts_add_args_data( WP_Scripts $wp_scripts, string $handle, arra ); } - if ( ! empty( $args['in_footer'] ) ) { + $in_footer = ! empty( $args['in_footer'] ); + if ( $in_footer ) { $wp_scripts->add_data( $handle, 'group', 1 ); } if ( ! empty( $args['strategy'] ) ) { @@ -108,6 +120,31 @@ function _wp_scripts_add_args_data( WP_Scripts $wp_scripts, string $handle, arra } if ( ! empty( $args['module_dependencies'] ) ) { $wp_scripts->add_data( $handle, 'module_dependencies', $args['module_dependencies'] ); + + /* + * A classic script with module dependencies must either be printed in the + * footer or use the 'defer' loading strategy. Otherwise, the script may be + * evaluated before the script modules import map is printed, causing + * dynamic imports to fail with a "Failed to resolve module specifier" error. + */ + $is_deferred = 'defer' === ( $args['strategy'] ?? null ); + if ( ! $in_footer && ! $is_deferred ) { + $trace = debug_backtrace( DEBUG_BACKTRACE_IGNORE_ARGS, 2 ); + $function_name = ( $trace[1]['class'] ?? '' ) . ( $trace[1]['type'] ?? '' ) . ( $trace[1]['function'] ?? __FUNCTION__ ); + _doing_it_wrong( + $function_name, + sprintf( + /* translators: 1: 'module_dependencies', 2: Script handle, 3: 'in_footer', 4: 'strategy', 5: 'defer'. */ + __( 'When the %1$s arg is provided, the "%2$s" script must either be printed in the footer (%3$s set to true) or use a deferred loading %4$s (%5$s) so that the import map is printed before the script is evaluated.' ), + 'module_dependencies', + $handle, + 'in_footer', + 'strategy', + 'defer' + ), + '7.0.0' + ); + } } } @@ -204,25 +241,39 @@ function wp_add_inline_script( $handle, $data, $position = 'after' ) { * @since 6.9.0 The $fetchpriority parameter of type string was added to the $args parameter of type array. * @since 7.0.0 The $module_dependencies parameter of type string[] was added to the $args parameter of type array. * - * @param string $handle Name of the script. Should be unique. - * @param string|false $src Full URL of the script, or path of the script relative to the WordPress root directory. - * If source is set to false, script is an alias of other scripts it depends on. - * @param string[] $deps Optional. An array of registered script handles this script depends on. Default empty array. - * @param string|bool|null $ver Optional. String specifying script version number, if it has one, which is added to the URL - * as a query string for cache busting purposes. If version is set to false, a version - * number is automatically added equal to current installed WordPress version. - * If set to null, no version is added. - * @param array>>|bool $args { + * @param string $handle Name of the script. Should be unique. + * @param string|false $src Full URL of the script, or path of the script relative to the WordPress root directory. + * If source is set to false, script is an alias of other scripts it depends on. + * @param string[] $deps Optional. An array of registered script handles this script depends on. Default empty array. + * @param string|bool|null $ver Optional. String specifying script version number, if it has one, which is added to the URL + * as a query string for cache busting purposes. If version is set to false, a version + * number is automatically added equal to current installed WordPress version. + * If set to null, no version is added. + * @param array|bool $args { * Optional. An array of extra args for the script. Default empty array. * Otherwise, it may be a boolean in which case it determines whether the script is printed in the footer. Default false. * - * @type string $strategy Optional. If provided, may be either 'defer' or 'async'. - * @type bool $in_footer Optional. Whether to print the script in the footer. Default 'false'. - * @type string $fetchpriority Optional. The fetch priority for the script. Default 'auto'. - * @type array> $module_dependencies Optional. IDs for module dependencies loaded via dynamic import. Default empty array. + * @type string $strategy Optional. If provided, may be either 'defer' or 'async'. + * @type bool $in_footer Optional. Whether to print the script in the footer. Default 'false'. + * @type string $fetchpriority Optional. The fetch priority for the script. Default 'auto'. + * @type array $module_dependencies Optional. IDs for module dependencies loaded via dynamic import. Default empty array. * For the full data format, see the `$deps` param of {@see wp_register_script_module()}. + * When provided, the script must either be printed in the footer (with + * `in_footer` set to true) or use a deferred loading `strategy` (`defer`), + * so that the script modules import map is printed before the script + * is evaluated. Otherwise dynamic imports may fail to resolve. * } * @return bool Whether the script has been registered. True on success, false on failure. + * + * @phpstan-param non-empty-string $handle + * @phpstan-param non-empty-string|false $src + * @phpstan-param non-empty-string[] $deps + * @phpstan-param array{ + * in_footer?: bool, + * strategy?: 'async'|'defer', + * fetchpriority?: 'low'|'auto'|'high', + * module_dependencies?: array, + * }|bool $args */ function wp_register_script( $handle, $src, $deps = array(), $ver = false, $args = array() ) { if ( ! is_array( $args ) ) { @@ -386,24 +437,38 @@ function wp_deregister_script( $handle ) { * @since 6.9.0 The $fetchpriority parameter of type string was added to the $args parameter of type array. * @since 7.0.0 The $module_dependencies parameter of type string[] was added to the $args parameter of type array. * - * @param string $handle Name of the script. Should be unique. - * @param string $src Full URL of the script, or path of the script relative to the WordPress root directory. - * Default empty. - * @param string[] $deps Optional. An array of registered script handles this script depends on. Default empty array. - * @param string|bool|null $ver Optional. String specifying script version number, if it has one, which is added to the URL - * as a query string for cache busting purposes. If version is set to false, a version - * number is automatically added equal to current installed WordPress version. - * If set to null, no version is added. - * @param array>>|bool $args { + * @param string $handle Name of the script. Should be unique. + * @param string $src Full URL of the script, or path of the script relative to the WordPress root directory. + * Default empty. + * @param string[] $deps Optional. An array of registered script handles this script depends on. Default empty array. + * @param string|bool|null $ver Optional. String specifying script version number, if it has one, which is added to the URL + * as a query string for cache busting purposes. If version is set to false, a version + * number is automatically added equal to current installed WordPress version. + * If set to null, no version is added. + * @param array|bool $args { * Optional. An array of extra args for the script. Default empty array. * Otherwise, it may be a boolean in which case it determines whether the script is printed in the footer. Default false. * - * @type string $strategy Optional. If provided, may be either 'defer' or 'async'. - * @type bool $in_footer Optional. Whether to print the script in the footer. Default 'false'. - * @type string $fetchpriority Optional. The fetch priority for the script. Default 'auto'. - * @type array> $module_dependencies Optional. IDs for module dependencies loaded via dynamic import. Default empty array. - * For the full data format, see the `$deps` param of {@see wp_register_script_module()}. + * @type string $strategy Optional. If provided, may be either 'defer' or 'async'. + * @type bool $in_footer Optional. Whether to print the script in the footer. Default 'false'. + * @type string $fetchpriority Optional. The fetch priority for the script. Default 'auto'. + * @type array $module_dependencies Optional. IDs for module dependencies loaded via dynamic import. Default empty array. + * For the full data format, see the `$deps` param of {@see wp_register_script_module()}. + * When provided, the script must either be printed in the footer (with + * `in_footer` set to true) or use a deferred loading `strategy` (`defer`), + * so that the script modules import map is printed before the script + * is evaluated. Otherwise dynamic imports may fail to resolve. * } + * + * @phpstan-param non-empty-string $handle + * @phpstan-param string $src + * @phpstan-param non-empty-string[] $deps + * @phpstan-param array{ + * in_footer?: bool, + * strategy?: 'async'|'defer', + * fetchpriority?: 'low'|'auto'|'high', + * module_dependencies?: array, + * }|bool $args */ function wp_enqueue_script( $handle, $src = '', $deps = array(), $ver = false, $args = array() ) { _wp_scripts_maybe_doing_it_wrong( __FUNCTION__, $handle ); @@ -411,6 +476,7 @@ function wp_enqueue_script( $handle, $src = '', $deps = array(), $ver = false, $ $wp_scripts = wp_scripts(); if ( $src || ! empty( $args ) ) { + /** @var array{ 0: non-empty-string, 1?: string } $_handle */ $_handle = explode( '?', $handle ); if ( ! is_array( $args ) ) { $args = array( diff --git a/src/wp-includes/general-template.php b/src/wp-includes/general-template.php index 47e2aeb2ebb05..34233c35b0cc3 100644 --- a/src/wp-includes/general-template.php +++ b/src/wp-includes/general-template.php @@ -4155,27 +4155,31 @@ function wp_get_code_editor_settings( $args ) { 'outline-none' => true, ), 'jshint' => array( - 'esversion' => 11, - 'module' => str_ends_with( $args['file'] ?? '', '.mjs' ), + 'esversion' => 11, + 'module' => str_ends_with( $args['file'] ?? '', '.mjs' ), + + // This script module URL is intentionally referenced here instead of registering an espree script module + // in wp_default_script_modules(). This is a first stab at a core-only private module. + 'espreeModuleUrl' => add_query_arg( 'ver', '9.6.1', includes_url( 'js/codemirror/espree.min.js' ) ), // The following JSHint *linting rule* options are copied from // . // Parsing-related options such as `esversion` (and, in other contexts, `es5`, `es3`, `module`, `strict`) // are honored by the Espree-based integration, but these linting-rule options are not interpreted by Espree // and are kept only for compatibility/documentation with the original JSHint configuration. - 'boss' => true, - 'curly' => true, - 'eqeqeq' => true, - 'eqnull' => true, - 'expr' => true, - 'immed' => true, - 'noarg' => true, - 'nonbsp' => true, - 'quotmark' => 'single', - 'undef' => true, - 'unused' => true, - 'browser' => true, - 'globals' => array( + 'boss' => true, + 'curly' => true, + 'eqeqeq' => true, + 'eqnull' => true, + 'expr' => true, + 'immed' => true, + 'noarg' => true, + 'nonbsp' => true, + 'quotmark' => 'single', + 'undef' => true, + 'unused' => true, + 'browser' => true, + 'globals' => array( '_' => false, 'Backbone' => false, 'jQuery' => false, diff --git a/src/wp-includes/script-loader.php b/src/wp-includes/script-loader.php index 42d42b3f8781d..f4fad38f3eefe 100644 --- a/src/wp-includes/script-loader.php +++ b/src/wp-includes/script-loader.php @@ -1200,9 +1200,8 @@ function wp_default_scripts( $scripts ) { ); $scripts->add( 'wp-codemirror', '/wp-includes/js/codemirror/codemirror.min.js', array(), '5.65.20' ); - did_action( 'init' ) && $scripts->add_data( 'wp-codemirror', 'module_dependencies', array( 'espree' ) ); $scripts->add( 'csslint', '/wp-includes/js/codemirror/csslint.js', array(), '1.0.5' ); - $scripts->add( 'esprima', '/wp-includes/js/codemirror/esprima.js', array(), '4.0.1' ); // Deprecated. Use 'espree' script module. + $scripts->add( 'esprima', '/wp-includes/js/codemirror/esprima.js', array(), '4.0.1' ); // Deprecated. $scripts->add( 'jshint', '/wp-includes/js/codemirror/fakejshint.js', array( 'esprima' ), '2.9.5' ); // Deprecated. $scripts->add( 'jsonlint', '/wp-includes/js/codemirror/jsonlint.js', array(), '1.6.3' ); $scripts->add( 'htmlhint', '/wp-includes/js/codemirror/htmlhint.js', array(), '1.8.0' ); diff --git a/src/wp-includes/script-modules.php b/src/wp-includes/script-modules.php index b3a89fdf71844..32863a6a8ab00 100644 --- a/src/wp-includes/script-modules.php +++ b/src/wp-includes/script-modules.php @@ -219,13 +219,6 @@ function wp_default_script_modules() { $module_deps = $script_module_data['module_dependencies'] ?? array(); wp_register_script_module( $script_module_id, $path, $module_deps, $script_module_data['version'], $args ); } - - wp_register_script_module( - 'espree', - includes_url( 'js/codemirror/espree.min.js' ), - array(), - '9.6.1' - ); } /** diff --git a/tests/phpunit/includes/abstract-testcase.php b/tests/phpunit/includes/abstract-testcase.php index 3a5d52b0706a9..b8e8598362ec5 100644 --- a/tests/phpunit/includes/abstract-testcase.php +++ b/tests/phpunit/includes/abstract-testcase.php @@ -18,7 +18,9 @@ abstract class WP_UnitTestCase_Base extends PHPUnit_Adapter_TestCase { protected $expected_deprecated = array(); protected $caught_deprecated = array(); protected $expected_doing_it_wrong = array(); - protected $caught_doing_it_wrong = array(); + + /** @var non-empty-string[] */ + protected $caught_doing_it_wrong = array(); protected static $hooks_saved = array(); protected static $ignore_files; diff --git a/tests/phpunit/tests/dependencies/scripts.php b/tests/phpunit/tests/dependencies/scripts.php index 5f1c30fe4cf47..41c9673915b93 100644 --- a/tests/phpunit/tests/dependencies/scripts.php +++ b/tests/phpunit/tests/dependencies/scripts.php @@ -8,6 +8,20 @@ * @covers ::wp_script_add_data * @covers ::wp_add_inline_script * @covers ::wp_set_script_translations + * + * @phpstan-type ScriptArgs array{ + * in_footer?: bool, + * strategy?: 'async'|'defer', + * fetchpriority?: 'low'|'auto'|'high', + * module_dependencies?: array, + * } + * @phpstan-type WpEnqueueScriptArgs array{ + * 0: non-empty-string, // $handle + * 1?: non-empty-string, // $src + * 2?: non-empty-string[], // $deps + * 3?: null|bool|string, // $version + * 4?: ScriptArgs, + * } */ class Tests_Dependencies_Scripts extends WP_UnitTestCase { @@ -1396,6 +1410,223 @@ public function data_add_data_module_dependencies_validation(): array { ); } + /** + * Tests that registering a script with `module_dependencies` triggers `_doing_it_wrong` + * when the script is not printed in the footer and does not use the `defer` strategy. + * + * @ticket 65165 + * + * @covers ::wp_register_script + * @covers ::wp_enqueue_script + * @covers ::_wp_scripts_add_args_data + * + * @dataProvider data_module_dependencies_require_footer_or_defer + * + * @param callable-string $function_name Function name to call. + * @param array $args Arguments to pass to the function. + * @param bool $should_warn Whether the call is expected to trigger a `_doing_it_wrong` warning. + * + * @phpstan-param WpEnqueueScriptArgs $args + */ + public function test_module_dependencies_require_footer_or_defer( string $function_name, array $args, bool $should_warn ): void { + if ( $should_warn ) { + $this->setExpectedIncorrectUsage( $function_name ); + } + + call_user_func_array( $function_name, $args ); + + if ( $should_warn ) { + $this->assertStringContainsString( + 'module_dependencies', + $this->caught_doing_it_wrong[ $function_name ], + 'The _doing_it_wrong message should reference module_dependencies.' + ); + $this->assertStringContainsString( + 'in_footer', + $this->caught_doing_it_wrong[ $function_name ], + 'The _doing_it_wrong message should reference the in_footer requirement.' + ); + $this->assertStringContainsString( + 'defer', + $this->caught_doing_it_wrong[ $function_name ], + 'The _doing_it_wrong message should reference the defer strategy.' + ); + } else { + $this->assertArrayNotHasKey( + $function_name, + $this->caught_doing_it_wrong, + 'No _doing_it_wrong warning should be triggered when in_footer is true or strategy is defer.' + ); + } + } + + /** + * Data provider for {@see self::test_module_dependencies_require_footer_or_defer()}. + * + * @phpstan-return array + */ + public function data_module_dependencies_require_footer_or_defer(): array { + $base_args = array( + '/script.js', + array(), + null, + ); + + return array( + 'register_blocking_warns' => array( + 'function_name' => 'wp_register_script', + 'args' => array_merge( + array( 'module-deps-blocking-register' ), + $base_args, + array( + array( + 'module_dependencies' => array( 'foo' ), + ), + ) + ), + 'should_warn' => true, + ), + 'enqueue_blocking_warns' => array( + 'function_name' => 'wp_enqueue_script', + 'args' => array_merge( + array( 'module-deps-blocking-enqueue' ), + $base_args, + array( + array( + 'module_dependencies' => array( 'foo' ), + ), + ) + ), + 'should_warn' => true, + ), + 'register_async_warns' => array( + 'function_name' => 'wp_register_script', + 'args' => array_merge( + array( 'module-deps-async-register' ), + $base_args, + array( + array( + 'module_dependencies' => array( 'foo' ), + 'strategy' => 'async', + ), + ) + ), + 'should_warn' => true, + ), + 'enqueue_async_warns' => array( + 'function_name' => 'wp_enqueue_script', + 'args' => array_merge( + array( 'module-deps-async-enqueue' ), + $base_args, + array( + array( + 'module_dependencies' => array( 'foo' ), + 'strategy' => 'async', + ), + ) + ), + 'should_warn' => true, + ), + 'register_in_footer_does_not_warn' => array( + 'function_name' => 'wp_register_script', + 'args' => array_merge( + array( 'module-deps-footer-register' ), + $base_args, + array( + array( + 'module_dependencies' => array( 'foo' ), + 'in_footer' => true, + ), + ) + ), + 'should_warn' => false, + ), + 'enqueue_in_footer_does_not_warn' => array( + 'function_name' => 'wp_enqueue_script', + 'args' => array_merge( + array( 'module-deps-footer-enqueue' ), + $base_args, + array( + array( + 'module_dependencies' => array( 'foo' ), + 'in_footer' => true, + ), + ) + ), + 'should_warn' => false, + ), + 'register_defer_does_not_warn' => array( + 'function_name' => 'wp_register_script', + 'args' => array_merge( + array( 'module-deps-defer-register' ), + $base_args, + array( + array( + 'module_dependencies' => array( 'foo' ), + 'strategy' => 'defer', + ), + ) + ), + 'should_warn' => false, + ), + 'enqueue_defer_does_not_warn' => array( + 'function_name' => 'wp_enqueue_script', + 'args' => array_merge( + array( 'module-deps-defer-enqueue' ), + $base_args, + array( + array( + 'module_dependencies' => array( 'foo' ), + 'strategy' => 'defer', + ), + ) + ), + 'should_warn' => false, + ), + 'register_footer_and_defer_no_warn' => array( + 'function_name' => 'wp_register_script', + 'args' => array_merge( + array( 'module-deps-footer-defer-register' ), + $base_args, + array( + array( + 'module_dependencies' => array( 'foo' ), + 'in_footer' => true, + 'strategy' => 'defer', + ), + ) + ), + 'should_warn' => false, + ), + 'register_no_module_deps_no_warn' => array( + 'function_name' => 'wp_register_script', + 'args' => array_merge( + array( 'no-module-deps-register' ), + $base_args, + array( array() ) + ), + 'should_warn' => false, + ), + 'register_empty_module_deps_no_warn' => array( + 'function_name' => 'wp_register_script', + 'args' => array_merge( + array( 'empty-module-deps-register' ), + $base_args, + array( + array( + 'module_dependencies' => array(), + ), + ) + ), + 'should_warn' => false, + ), + ); + } + /** * Data provider. * @@ -3169,6 +3400,7 @@ public function test_wp_enqueue_code_editor_when_php_file_will_be_passed() { 'unused', 'browser', 'globals', + 'espreeModuleUrl', ), array_keys( $wp_enqueue_code_editor['jshint'] ) ); @@ -3252,6 +3484,7 @@ public function test_wp_enqueue_code_editor_when_generated_array_by_compact_will 'unused', 'browser', 'globals', + 'espreeModuleUrl', ), array_keys( $wp_enqueue_code_editor['jshint'] ) ); @@ -3349,6 +3582,7 @@ public function test_wp_enqueue_code_editor_when_generated_array_by_array_merge_ 'unused', 'browser', 'globals', + 'espreeModuleUrl', ), array_keys( $wp_enqueue_code_editor['jshint'] ) ); @@ -3443,6 +3677,7 @@ public function test_wp_enqueue_code_editor_when_simple_array_will_be_passed() { 'unused', 'browser', 'globals', + 'espreeModuleUrl', ), array_keys( $wp_enqueue_code_editor['jshint'] ) ); diff --git a/tests/phpunit/tests/script-modules/wpScriptModules.php b/tests/phpunit/tests/script-modules/wpScriptModules.php index 330736431dffd..09b5a91e2896f 100644 --- a/tests/phpunit/tests/script-modules/wpScriptModules.php +++ b/tests/phpunit/tests/script-modules/wpScriptModules.php @@ -2041,6 +2041,7 @@ public function test_included_module_appears_in_importmap() { array( 'classic-dependency' ), false, array( + 'strategy' => 'defer', 'module_dependencies' => array( 'example', array( @@ -2109,6 +2110,7 @@ public function test_import_map_includes_dependencies_of_classic_scripts_recursi array(), false, array( + 'in_footer' => true, 'module_dependencies' => array( 'classic-transitive-dependency' ), ) ); @@ -2118,6 +2120,7 @@ public function test_import_map_includes_dependencies_of_classic_scripts_recursi array( 'classic-transitive-dep' ), false, array( + 'in_footer' => true, 'module_dependencies' => array( 'not-enqueued' ), ) ); @@ -2153,6 +2156,7 @@ public function test_wp_scripts_doing_it_wrong_for_missing_script_module_depende array(), null, array( + 'strategy' => 'defer', 'module_dependencies' => array( 'does-not-exist' ), ) );