Make WordPress Core

Changeset 62368


Ignore:
Timestamp:
05/16/2026 05:03:42 AM (less than one hour ago)
Author:
westonruter
Message:

Script Loader: Warn when classic scripts with module dependencies lack footer/defer.

A classic script with module_dependencies may be evaluated before the script modules import map is printed if it loads blocking in the document head, causing a "Failed to resolve module specifier" error on dynamic imports.

  • Trigger _doing_it_wrong() from _wp_scripts_add_args_data() when a classic script provides module_dependencies without setting in_footer to true or using a defer loading strategy, and document this requirement in the wp_register_script() and wp_enqueue_script() docblocks.
  • Remove the module_dependencies arg from the wp-codemirror script registration in favor of passing the espree module URL directly through wp_get_code_editor_settings(). This avoids registering espree as a publicly-available script module when it is only ever used internally as a private implementation detail of the code editor.
  • Add a console.warn() in wp.codeEditor.initialize() when invoked before DOMContentLoaded, so developers are alerted if the function is called too early for the import map to have been parsed.
  • Add PHPStan types which were missing when module_dependencies were initially introduced.
  • Harden WP_Scripts::add_data() against non-string strategy values being passed to sprintf().

Developed in https://github.com/WordPress/wordpress-develop/pull/11788

Follow-up to r61587.

Props khokansardar, westonruter, jonsurrell, jorbin.
See #61500, #64238.
Fixes #65165.

Location:
trunk
Files:
10 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/js/_enqueues/lib/codemirror/javascript-lint.js

    r61800 r62368  
    3131 * @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."
    3232 * @property {'implied'} [strict] - "This option requires the code to run in ECMAScript 5's strict mode."
     33 * @property {string} [espreeModuleUrl] - The URL to the espree script module.
    3334 */
    3435
     
    4344 */
    4445async function validator( text, options ) {
     46    if ( ! options.espreeModuleUrl ) {
     47        return [];
     48    }
     49
    4550    const errors = /** @type {CodeMirrorLintError[]} */ [];
    4651    try {
    47         const espree = await import( /* webpackIgnore: true */ 'espree' );
     52        const espree = await import( /* webpackIgnore: true */ options.espreeModuleUrl );
    4853        espree.parse( text, {
    4954            ...getEspreeOptions( options ),
  • trunk/src/js/_enqueues/wp/code-editor.js

    r61800 r62368  
    22 * @output wp-admin/js/code-editor.js
    33 */
     4
     5/* global console */
    46
    57/* eslint-env es2020 */
     
    413415     */
    414416    wp.codeEditor.initialize = function initialize( textarea, settings ) {
     417        if ( document.readyState === 'loading' ) {
     418            console.warn( 'wp.codeEditor.initialize() ran too early. Invoke this function in a `DOMContentLoaded` event listener.' );
     419        }
     420
    415421        let $textarea;
    416422        if ( 'string' === typeof textarea ) {
  • trunk/src/wp-includes/class-wp-scripts.php

    r62178 r62368  
    886886                        /* translators: 1: $strategy, 2: $handle */
    887887                        __( 'Invalid strategy `%1$s` defined for `%2$s` during script registration.' ),
    888                         $value,
     888                        is_string( $value ) ? $value : gettype( $value ),
    889889                        $handle
    890890                    ),
     
    898898                        /* translators: 1: $strategy, 2: $handle */
    899899                        __( 'Cannot supply a strategy `%1$s` for script `%2$s` because it is an alias (it lacks a `src` value).' ),
    900                         $value,
     900                        is_string( $value ) ? $value : gettype( $value ),
    901901                        $handle
    902902                    ),
  • trunk/src/wp-includes/functions.wp-scripts.php

    r61587 r62368  
    7272 * Adds the data for the recognized args and warns for unrecognized args.
    7373 *
     74 * @see wp_enqueue_script()
     75 * @see wp_register_script()
     76 *
    7477 * @ignore
    7578 * @since 7.0.0
     
    7881 * @param string     $handle     Script handle.
    7982 * @param array      $args       Array of extra args for the script.
    80  */
    81 function _wp_scripts_add_args_data( WP_Scripts $wp_scripts, string $handle, array $args ) {
     83 *
     84 * @phpstan-param non-empty-string $handle
     85 * @phpstan-param array{
     86 *     in_footer?: bool,
     87 *     strategy?: 'async'|'defer',
     88 *     fetchpriority?: 'low'|'auto'|'high',
     89 *     module_dependencies?: array<non-empty-string|array{ id: non-empty-string, ... }>,
     90 * } $args
     91 */
     92function _wp_scripts_add_args_data( WP_Scripts $wp_scripts, string $handle, array $args ): void {
    8293    $allowed_keys = array( 'strategy', 'in_footer', 'fetchpriority', 'module_dependencies' );
    8394    $unknown_keys = array_diff( array_keys( $args ), $allowed_keys );
    8495    if ( ! empty( $unknown_keys ) ) {
    8596        $trace         = debug_backtrace( DEBUG_BACKTRACE_IGNORE_ARGS, 2 );
    86         $function_name = ( $trace[1]['class'] ?? '' ) . ( $trace[1]['type'] ?? '' ) . $trace[1]['function'];
     97        $function_name = ( $trace[1]['class'] ?? '' ) . ( $trace[1]['type'] ?? '' ) . ( $trace[1]['function'] ?? __FUNCTION__ );
    8798        _doing_it_wrong(
    8899            $function_name,
     
    98109    }
    99110
    100     if ( ! empty( $args['in_footer'] ) ) {
     111    $in_footer = ! empty( $args['in_footer'] );
     112    if ( $in_footer ) {
    101113        $wp_scripts->add_data( $handle, 'group', 1 );
    102114    }
     
    109121    if ( ! empty( $args['module_dependencies'] ) ) {
    110122        $wp_scripts->add_data( $handle, 'module_dependencies', $args['module_dependencies'] );
     123
     124        /*
     125         * A classic script with module dependencies must either be printed in the
     126         * footer or use the 'defer' loading strategy. Otherwise, the script may be
     127         * evaluated before the script modules import map is printed, causing
     128         * dynamic imports to fail with a "Failed to resolve module specifier" error.
     129         */
     130        $is_deferred = 'defer' === ( $args['strategy'] ?? null );
     131        if ( ! $in_footer && ! $is_deferred ) {
     132            $trace         = debug_backtrace( DEBUG_BACKTRACE_IGNORE_ARGS, 2 );
     133            $function_name = ( $trace[1]['class'] ?? '' ) . ( $trace[1]['type'] ?? '' ) . ( $trace[1]['function'] ?? __FUNCTION__ );
     134            _doing_it_wrong(
     135                $function_name,
     136                sprintf(
     137                    /* translators: 1: 'module_dependencies', 2: Script handle, 3: 'in_footer', 4: 'strategy', 5: 'defer'. */
     138                    __( '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.' ),
     139                    '<code>module_dependencies</code>',
     140                    $handle,
     141                    '<code>in_footer</code>',
     142                    '<code>strategy</code>',
     143                    '<code>defer</code>'
     144                ),
     145                '7.0.0'
     146            );
     147        }
    111148    }
    112149}
     
    205242 * @since 7.0.0 The $module_dependencies parameter of type string[] was added to the $args parameter of type array.
    206243 *
    207  * @param string                                                              $handle Name of the script. Should be unique.
    208  * @param string|false                                                        $src    Full URL of the script, or path of the script relative to the WordPress root directory.
    209  *                                                                                    If source is set to false, script is an alias of other scripts it depends on.
    210  * @param string[]                                                            $deps   Optional. An array of registered script handles this script depends on. Default empty array.
    211  * @param string|bool|null                                                    $ver    Optional. String specifying script version number, if it has one, which is added to the URL
    212  *                                                                                    as a query string for cache busting purposes. If version is set to false, a version
    213  *                                                                                    number is automatically added equal to current installed WordPress version.
    214  *                                                                                    If set to null, no version is added.
    215  * @param array<string, string|bool|array<string|array<string, string>>>|bool $args   {
     244 * @param string           $handle Name of the script. Should be unique.
     245 * @param string|false     $src    Full URL of the script, or path of the script relative to the WordPress root directory.
     246 *                                 If source is set to false, script is an alias of other scripts it depends on.
     247 * @param string[]         $deps   Optional. An array of registered script handles this script depends on. Default empty array.
     248 * @param string|bool|null $ver    Optional. String specifying script version number, if it has one, which is added to the URL
     249 *                                 as a query string for cache busting purposes. If version is set to false, a version
     250 *                                 number is automatically added equal to current installed WordPress version.
     251 *                                 If set to null, no version is added.
     252 * @param array|bool      $args   {
    216253 *     Optional. An array of extra args for the script. Default empty array.
    217254 *     Otherwise, it may be a boolean in which case it determines whether the script is printed in the footer. Default false.
    218255 *
    219  *     @type string                              $strategy            Optional. If provided, may be either 'defer' or 'async'.
    220  *     @type bool                                $in_footer           Optional. Whether to print the script in the footer. Default 'false'.
    221  *     @type string                              $fetchpriority       Optional. The fetch priority for the script. Default 'auto'.
    222  *     @type array<string|array<string, string>> $module_dependencies Optional. IDs for module dependencies loaded via dynamic import. Default empty array.
     256 *     @type string $strategy            Optional. If provided, may be either 'defer' or 'async'.
     257 *     @type bool   $in_footer           Optional. Whether to print the script in the footer. Default 'false'.
     258 *     @type string $fetchpriority       Optional. The fetch priority for the script. Default 'auto'.
     259 *     @type array  $module_dependencies Optional. IDs for module dependencies loaded via dynamic import. Default empty array.
    223260 *                                                                    For the full data format, see the `$deps` param of {@see wp_register_script_module()}.
     261 *                                                                    When provided, the script must either be printed in the footer (with
     262 *                                                                    `in_footer` set to true) or use a deferred loading `strategy` (`defer`),
     263 *                                                                    so that the script modules import map is printed before the script
     264 *                                                                    is evaluated. Otherwise dynamic imports may fail to resolve.
    224265 * }
    225266 * @return bool Whether the script has been registered. True on success, false on failure.
     267 *
     268 * @phpstan-param non-empty-string $handle
     269 * @phpstan-param non-empty-string|false $src
     270 * @phpstan-param non-empty-string[] $deps
     271 * @phpstan-param array{
     272 *     in_footer?: bool,
     273 *     strategy?: 'async'|'defer',
     274 *     fetchpriority?: 'low'|'auto'|'high',
     275 *     module_dependencies?: array<non-empty-string|array{ id: non-empty-string, ... }>,
     276 * }|bool $args
    226277 */
    227278function wp_register_script( $handle, $src, $deps = array(), $ver = false, $args = array() ) {
     
    387438 * @since 7.0.0 The $module_dependencies parameter of type string[] was added to the $args parameter of type array.
    388439 *
    389  * @param string                                                              $handle Name of the script. Should be unique.
    390  * @param string                                                              $src    Full URL of the script, or path of the script relative to the WordPress root directory.
    391  *                                                                                    Default empty.
    392  * @param string[]                                                            $deps   Optional. An array of registered script handles this script depends on. Default empty array.
    393  * @param string|bool|null                                                    $ver    Optional. String specifying script version number, if it has one, which is added to the URL
    394  *                                                                                    as a query string for cache busting purposes. If version is set to false, a version
    395  *                                                                                    number is automatically added equal to current installed WordPress version.
    396  *                                                                                    If set to null, no version is added.
    397  * @param array<string, string|bool|array<string|array<string, string>>>|bool $args {
     440 * @param string           $handle Name of the script. Should be unique.
     441 * @param string           $src    Full URL of the script, or path of the script relative to the WordPress root directory.
     442 *                                 Default empty.
     443 * @param string[]         $deps   Optional. An array of registered script handles this script depends on. Default empty array.
     444 * @param string|bool|null $ver    Optional. String specifying script version number, if it has one, which is added to the URL
     445 *                                 as a query string for cache busting purposes. If version is set to false, a version
     446 *                                 number is automatically added equal to current installed WordPress version.
     447 *                                 If set to null, no version is added.
     448 * @param array|bool $args {
    398449 *     Optional. An array of extra args for the script. Default empty array.
    399450 *     Otherwise, it may be a boolean in which case it determines whether the script is printed in the footer. Default false.
    400451 *
    401  *     @type string                              $strategy            Optional. If provided, may be either 'defer' or 'async'.
    402  *     @type bool                                $in_footer           Optional. Whether to print the script in the footer. Default 'false'.
    403  *     @type string                              $fetchpriority       Optional. The fetch priority for the script. Default 'auto'.
    404  *     @type array<string|array<string, string>> $module_dependencies Optional. IDs for module dependencies loaded via dynamic import. Default empty array.
    405  *                                                                    For the full data format, see the `$deps` param of {@see wp_register_script_module()}.
     452 *     @type string $strategy            Optional. If provided, may be either 'defer' or 'async'.
     453 *     @type bool   $in_footer           Optional. Whether to print the script in the footer. Default 'false'.
     454 *     @type string $fetchpriority       Optional. The fetch priority for the script. Default 'auto'.
     455 *     @type array  $module_dependencies Optional. IDs for module dependencies loaded via dynamic import. Default empty array.
     456 *                                       For the full data format, see the `$deps` param of {@see wp_register_script_module()}.
     457 *                                       When provided, the script must either be printed in the footer (with
     458 *                                       `in_footer` set to true) or use a deferred loading `strategy` (`defer`),
     459 *                                       so that the script modules import map is printed before the script
     460 *                                       is evaluated. Otherwise dynamic imports may fail to resolve.
    406461 * }
     462 *
     463 * @phpstan-param non-empty-string $handle
     464 * @phpstan-param string $src
     465 * @phpstan-param non-empty-string[] $deps
     466 * @phpstan-param array{
     467 *     in_footer?: bool,
     468 *     strategy?: 'async'|'defer',
     469 *     fetchpriority?: 'low'|'auto'|'high',
     470 *     module_dependencies?: array<non-empty-string|array{ id: non-empty-string, ... }>,
     471 * }|bool $args
    407472 */
    408473function wp_enqueue_script( $handle, $src = '', $deps = array(), $ver = false, $args = array() ) {
     
    412477
    413478    if ( $src || ! empty( $args ) ) {
     479        /** @var array{ 0: non-empty-string, 1?: string } $_handle */
    414480        $_handle = explode( '?', $handle );
    415481        if ( ! is_array( $args ) ) {
  • trunk/src/wp-includes/general-template.php

    r62036 r62368  
    41564156        ),
    41574157        'jshint'     => array(
    4158             'esversion' => 11,
    4159             'module'    => str_ends_with( $args['file'] ?? '', '.mjs' ),
     4158            'esversion'       => 11,
     4159            'module'          => str_ends_with( $args['file'] ?? '', '.mjs' ),
     4160
     4161            // This script module URL is intentionally referenced here instead of registering an espree script module
     4162            // in wp_default_script_modules(). This is a first stab at a core-only private module.
     4163            'espreeModuleUrl' => add_query_arg( 'ver', '9.6.1', includes_url( 'js/codemirror/espree.min.js' ) ),
    41604164
    41614165            // The following JSHint *linting rule* options are copied from
     
    41644168            // are honored by the Espree-based integration, but these linting-rule options are not interpreted by Espree
    41654169            // and are kept only for compatibility/documentation with the original JSHint configuration.
    4166             'boss'      => true,
    4167             'curly'     => true,
    4168             'eqeqeq'    => true,
    4169             'eqnull'    => true,
    4170             'expr'      => true,
    4171             'immed'     => true,
    4172             'noarg'     => true,
    4173             'nonbsp'    => true,
    4174             'quotmark'  => 'single',
    4175             'undef'     => true,
    4176             'unused'    => true,
    4177             'browser'   => true,
    4178             'globals'   => array(
     4170            'boss'            => true,
     4171            'curly'           => true,
     4172            'eqeqeq'          => true,
     4173            'eqnull'          => true,
     4174            'expr'            => true,
     4175            'immed'           => true,
     4176            'noarg'           => true,
     4177            'nonbsp'          => true,
     4178            'quotmark'        => 'single',
     4179            'undef'           => true,
     4180            'unused'          => true,
     4181            'browser'         => true,
     4182            'globals'         => array(
    41794183                '_'                 => false,
    41804184                'Backbone'          => false,
  • trunk/src/wp-includes/script-loader.php

    r62188 r62368  
    12011201
    12021202    $scripts->add( 'wp-codemirror', '/wp-includes/js/codemirror/codemirror.min.js', array(), '5.65.20' );
    1203     did_action( 'init' ) && $scripts->add_data( 'wp-codemirror', 'module_dependencies', array( 'espree' ) );
    12041203    $scripts->add( 'csslint', '/wp-includes/js/codemirror/csslint.js', array(), '1.0.5' );
    1205     $scripts->add( 'esprima', '/wp-includes/js/codemirror/esprima.js', array(), '4.0.1' ); // Deprecated. Use 'espree' script module.
     1204    $scripts->add( 'esprima', '/wp-includes/js/codemirror/esprima.js', array(), '4.0.1' ); // Deprecated.
    12061205    $scripts->add( 'jshint', '/wp-includes/js/codemirror/fakejshint.js', array( 'esprima' ), '2.9.5' ); // Deprecated.
    12071206    $scripts->add( 'jsonlint', '/wp-includes/js/codemirror/jsonlint.js', array(), '1.6.3' );
  • trunk/src/wp-includes/script-modules.php

    r62278 r62368  
    220220        wp_register_script_module( $script_module_id, $path, $module_deps, $script_module_data['version'], $args );
    221221    }
    222 
    223     wp_register_script_module(
    224         'espree',
    225         includes_url( 'js/codemirror/espree.min.js' ),
    226         array(),
    227         '9.6.1'
    228     );
    229222}
    230223
  • trunk/tests/phpunit/includes/abstract-testcase.php

    r61604 r62368  
    1919    protected $caught_deprecated       = array();
    2020    protected $expected_doing_it_wrong = array();
    21     protected $caught_doing_it_wrong   = array();
     21
     22    /** @var non-empty-string[] */
     23    protected $caught_doing_it_wrong = array();
    2224
    2325    protected static $hooks_saved = array();
  • trunk/tests/phpunit/tests/dependencies/scripts.php

    r61927 r62368  
    99 * @covers ::wp_add_inline_script
    1010 * @covers ::wp_set_script_translations
     11 *
     12 * @phpstan-type ScriptArgs array{
     13 *     in_footer?: bool,
     14 *     strategy?: 'async'|'defer',
     15 *     fetchpriority?: 'low'|'auto'|'high',
     16 *     module_dependencies?: array<non-empty-string|array{ id: non-empty-string, ... }>,
     17 * }
     18 * @phpstan-type WpEnqueueScriptArgs array{
     19 *     0: non-empty-string, // $handle
     20 *     1?: non-empty-string, // $src
     21 *     2?: non-empty-string[], // $deps
     22 *     3?: null|bool|string, // $version
     23 *     4?: ScriptArgs,
     24 * }
    1125 */
    1226class Tests_Dependencies_Scripts extends WP_UnitTestCase {
     
    13931407                'expected' => true,
    13941408                'stored'   => array( 'valid', array( 'id' => 'valid2' ) ),
     1409            ),
     1410        );
     1411    }
     1412
     1413    /**
     1414     * Tests that registering a script with `module_dependencies` triggers `_doing_it_wrong`
     1415     * when the script is not printed in the footer and does not use the `defer` strategy.
     1416     *
     1417     * @ticket 65165
     1418     *
     1419     * @covers ::wp_register_script
     1420     * @covers ::wp_enqueue_script
     1421     * @covers ::_wp_scripts_add_args_data
     1422     *
     1423     * @dataProvider data_module_dependencies_require_footer_or_defer
     1424     *
     1425     * @param callable-string $function_name Function name to call.
     1426     * @param array           $args          Arguments to pass to the function.
     1427     * @param bool            $should_warn   Whether the call is expected to trigger a `_doing_it_wrong` warning.
     1428     *
     1429     * @phpstan-param WpEnqueueScriptArgs $args
     1430     */
     1431    public function test_module_dependencies_require_footer_or_defer( string $function_name, array $args, bool $should_warn ): void {
     1432        if ( $should_warn ) {
     1433            $this->setExpectedIncorrectUsage( $function_name );
     1434        }
     1435
     1436        call_user_func_array( $function_name, $args );
     1437
     1438        if ( $should_warn ) {
     1439            $this->assertStringContainsString(
     1440                'module_dependencies',
     1441                $this->caught_doing_it_wrong[ $function_name ],
     1442                'The _doing_it_wrong message should reference module_dependencies.'
     1443            );
     1444            $this->assertStringContainsString(
     1445                'in_footer',
     1446                $this->caught_doing_it_wrong[ $function_name ],
     1447                'The _doing_it_wrong message should reference the in_footer requirement.'
     1448            );
     1449            $this->assertStringContainsString(
     1450                'defer',
     1451                $this->caught_doing_it_wrong[ $function_name ],
     1452                'The _doing_it_wrong message should reference the defer strategy.'
     1453            );
     1454        } else {
     1455            $this->assertArrayNotHasKey(
     1456                $function_name,
     1457                $this->caught_doing_it_wrong,
     1458                'No _doing_it_wrong warning should be triggered when in_footer is true or strategy is defer.'
     1459            );
     1460        }
     1461    }
     1462
     1463    /**
     1464     * Data provider for {@see self::test_module_dependencies_require_footer_or_defer()}.
     1465     *
     1466     * @phpstan-return array<string, array{
     1467     *     function_name: callable-string,
     1468     *     args: WpEnqueueScriptArgs,
     1469     *     should_warn: bool,
     1470     * }>
     1471     */
     1472    public function data_module_dependencies_require_footer_or_defer(): array {
     1473        $base_args = array(
     1474            '/script.js',
     1475            array(),
     1476            null,
     1477        );
     1478
     1479        return array(
     1480            'register_blocking_warns'            => array(
     1481                'function_name' => 'wp_register_script',
     1482                'args'          => array_merge(
     1483                    array( 'module-deps-blocking-register' ),
     1484                    $base_args,
     1485                    array(
     1486                        array(
     1487                            'module_dependencies' => array( 'foo' ),
     1488                        ),
     1489                    )
     1490                ),
     1491                'should_warn'   => true,
     1492            ),
     1493            'enqueue_blocking_warns'             => array(
     1494                'function_name' => 'wp_enqueue_script',
     1495                'args'          => array_merge(
     1496                    array( 'module-deps-blocking-enqueue' ),
     1497                    $base_args,
     1498                    array(
     1499                        array(
     1500                            'module_dependencies' => array( 'foo' ),
     1501                        ),
     1502                    )
     1503                ),
     1504                'should_warn'   => true,
     1505            ),
     1506            'register_async_warns'               => array(
     1507                'function_name' => 'wp_register_script',
     1508                'args'          => array_merge(
     1509                    array( 'module-deps-async-register' ),
     1510                    $base_args,
     1511                    array(
     1512                        array(
     1513                            'module_dependencies' => array( 'foo' ),
     1514                            'strategy'            => 'async',
     1515                        ),
     1516                    )
     1517                ),
     1518                'should_warn'   => true,
     1519            ),
     1520            'enqueue_async_warns'                => array(
     1521                'function_name' => 'wp_enqueue_script',
     1522                'args'          => array_merge(
     1523                    array( 'module-deps-async-enqueue' ),
     1524                    $base_args,
     1525                    array(
     1526                        array(
     1527                            'module_dependencies' => array( 'foo' ),
     1528                            'strategy'            => 'async',
     1529                        ),
     1530                    )
     1531                ),
     1532                'should_warn'   => true,
     1533            ),
     1534            'register_in_footer_does_not_warn'   => array(
     1535                'function_name' => 'wp_register_script',
     1536                'args'          => array_merge(
     1537                    array( 'module-deps-footer-register' ),
     1538                    $base_args,
     1539                    array(
     1540                        array(
     1541                            'module_dependencies' => array( 'foo' ),
     1542                            'in_footer'           => true,
     1543                        ),
     1544                    )
     1545                ),
     1546                'should_warn'   => false,
     1547            ),
     1548            'enqueue_in_footer_does_not_warn'    => array(
     1549                'function_name' => 'wp_enqueue_script',
     1550                'args'          => array_merge(
     1551                    array( 'module-deps-footer-enqueue' ),
     1552                    $base_args,
     1553                    array(
     1554                        array(
     1555                            'module_dependencies' => array( 'foo' ),
     1556                            'in_footer'           => true,
     1557                        ),
     1558                    )
     1559                ),
     1560                'should_warn'   => false,
     1561            ),
     1562            'register_defer_does_not_warn'       => array(
     1563                'function_name' => 'wp_register_script',
     1564                'args'          => array_merge(
     1565                    array( 'module-deps-defer-register' ),
     1566                    $base_args,
     1567                    array(
     1568                        array(
     1569                            'module_dependencies' => array( 'foo' ),
     1570                            'strategy'            => 'defer',
     1571                        ),
     1572                    )
     1573                ),
     1574                'should_warn'   => false,
     1575            ),
     1576            'enqueue_defer_does_not_warn'        => array(
     1577                'function_name' => 'wp_enqueue_script',
     1578                'args'          => array_merge(
     1579                    array( 'module-deps-defer-enqueue' ),
     1580                    $base_args,
     1581                    array(
     1582                        array(
     1583                            'module_dependencies' => array( 'foo' ),
     1584                            'strategy'            => 'defer',
     1585                        ),
     1586                    )
     1587                ),
     1588                'should_warn'   => false,
     1589            ),
     1590            'register_footer_and_defer_no_warn'  => array(
     1591                'function_name' => 'wp_register_script',
     1592                'args'          => array_merge(
     1593                    array( 'module-deps-footer-defer-register' ),
     1594                    $base_args,
     1595                    array(
     1596                        array(
     1597                            'module_dependencies' => array( 'foo' ),
     1598                            'in_footer'           => true,
     1599                            'strategy'            => 'defer',
     1600                        ),
     1601                    )
     1602                ),
     1603                'should_warn'   => false,
     1604            ),
     1605            'register_no_module_deps_no_warn'    => array(
     1606                'function_name' => 'wp_register_script',
     1607                'args'          => array_merge(
     1608                    array( 'no-module-deps-register' ),
     1609                    $base_args,
     1610                    array( array() )
     1611                ),
     1612                'should_warn'   => false,
     1613            ),
     1614            'register_empty_module_deps_no_warn' => array(
     1615                'function_name' => 'wp_register_script',
     1616                'args'          => array_merge(
     1617                    array( 'empty-module-deps-register' ),
     1618                    $base_args,
     1619                    array(
     1620                        array(
     1621                            'module_dependencies' => array(),
     1622                        ),
     1623                    )
     1624                ),
     1625                'should_warn'   => false,
    13951626            ),
    13961627        );
     
    31703401                'browser',
    31713402                'globals',
     3403                'espreeModuleUrl',
    31723404            ),
    31733405            array_keys( $wp_enqueue_code_editor['jshint'] )
     
    32533485                'browser',
    32543486                'globals',
     3487                'espreeModuleUrl',
    32553488            ),
    32563489            array_keys( $wp_enqueue_code_editor['jshint'] )
     
    33503583                'browser',
    33513584                'globals',
     3585                'espreeModuleUrl',
    33523586            ),
    33533587            array_keys( $wp_enqueue_code_editor['jshint'] )
     
    34443678                'browser',
    34453679                'globals',
     3680                'espreeModuleUrl',
    34463681            ),
    34473682            array_keys( $wp_enqueue_code_editor['jshint'] )
  • trunk/tests/phpunit/tests/script-modules/wpScriptModules.php

    r62278 r62368  
    20422042            false,
    20432043            array(
     2044                'strategy'            => 'defer',
    20442045                'module_dependencies' => array(
    20452046                    'example',
     
    21102111            false,
    21112112            array(
     2113                'in_footer'           => true,
    21122114                'module_dependencies' => array( 'classic-transitive-dependency' ),
    21132115            )
     
    21192121            false,
    21202122            array(
     2123                'in_footer'           => true,
    21212124                'module_dependencies' => array( 'not-enqueued' ),
    21222125            )
     
    21542157            null,
    21552158            array(
     2159                'strategy'            => 'defer',
    21562160                'module_dependencies' => array( 'does-not-exist' ),
    21572161            )
Note: See TracChangeset for help on using the changeset viewer.