Make WordPress Core


Ignore:
Timestamp:
02/04/2026 01:41:25 AM (2 months ago)
Author:
westonruter
Message:

Script Loader: Allow classic scripts to depend on script modules.

This allows classic scripts to declare dependencies on script modules by passing module_dependencies in the $args param for wp_register_script() or wp_enqueue_script(). The WP_Script_Modules::get_import_map() method is updated to traverse the dependency tree of all enqueued classic scripts to find any associated script module dependencies and include them in the importmap, enabling dynamic imports of modules within classic scripts.

A _wp_scripts_add_args_data() helper function is introduced to consolidate argument validation and processing for wp_register_script() and wp_enqueue_script(), reducing code duplication. This function validates that the $args array only contains recognized keys (strategy, in_footer, fetchpriority, module_dependencies) and triggers a _doing_it_wrong() notice for any unrecognized keys. Similarly, WP_Scripts::add_data() is updated to do early type checking for the data passed to $args. The script modules in module_dependencies may be referenced by a module ID string or by an array that has an id key, following the same pattern as dependencies in WP_Script_Modules.

When a script module is added to the module_dependencies for a classic script, but it does not exist at the time the importmap is printed, a _doing_it_wrong() notice is emitted.

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

Follow-up to [61323].

Props sirreal, westonruter.
See #64229.
Fixes #61500.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/tests/phpunit/tests/dependencies/scripts.php

    r61539 r61587  
    107107
    108108    /**
     109     * Tests that scripts trigger _doing_it_wrong for unrecognized keys in the $args array.
     110     *
     111     * @ticket 63486
     112     *
     113     * @covers ::wp_register_script
     114     * @covers ::wp_enqueue_script
     115     * @covers ::_wp_scripts_add_args_data
     116     *
     117     * @dataProvider data_unrecognized_keys_in_args
     118     *
     119     * @param string $function_name Function name to call.
     120     * @param array  $args          Arguments to pass to the function.
     121     * @param string $expected_msg  Expected error message substring.
     122     */
     123    public function test_unrecognized_keys_in_args( string $function_name, array $args, string $expected_msg ) {
     124        $this->setExpectedIncorrectUsage( $function_name );
     125
     126        call_user_func_array( $function_name, $args );
     127
     128        $this->assertStringContainsString(
     129            $expected_msg,
     130            $this->caught_doing_it_wrong[ $function_name ]
     131        );
     132    }
     133
     134    /**
     135     * Data provider for test_unrecognized_keys_in_args.
     136     *
     137     * @return array<string, array{function_name: string, args: array, expected_msg: string}>
     138     */
     139    public function data_unrecognized_keys_in_args(): array {
     140        return array(
     141            'register_script' => array(
     142                'function_name' => 'wp_register_script',
     143                'args'          => array(
     144                    'unrecognized-key-register',
     145                    '/script.js',
     146                    array(),
     147                    null,
     148                    array(
     149                        'unrecognized_key' => 'value',
     150                        'another_bad_key'  => 'value',
     151                    ),
     152                ),
     153                'expected_msg'  => 'Unrecognized key(s) in the $args param: unrecognized_key, another_bad_key. Supported keys: strategy, in_footer, fetchpriority, module_dependencies',
     154            ),
     155            'enqueue_script'  => array(
     156                'function_name' => 'wp_enqueue_script',
     157                'args'          => array(
     158                    'unrecognized-key-enqueue',
     159                    '/script.js',
     160                    array(),
     161                    null,
     162                    array(
     163                        'strategy'            => 'defer',
     164                        'in_footer'           => true,
     165                        'fetchpriority'       => 'high',
     166                        'module_dependencies' => array( 'foo' ),
     167                        'invalid_key'         => 'bar',
     168                    ),
     169                ),
     170                'expected_msg'  => 'Unrecognized key(s) in the $args param: invalid_key. Supported keys: strategy, in_footer, fetchpriority, module_dependencies',
     171            ),
     172        );
     173    }
     174
     175    /**
    109176     * Test versioning
    110177     *
     
    12761343        wp_register_script( 'alias', false, array(), null, array( 'fetchpriority' => 'low' ) );
    12771344        $this->assertArrayNotHasKey( 'fetchpriority', wp_scripts()->registered['alias']->extra );
     1345    }
     1346
     1347    /**
     1348     * Tests validation of module_dependencies in WP_Scripts::add_data().
     1349     *
     1350     * @ticket 61500
     1351     *
     1352     * @covers WP_Scripts::add_data
     1353     *
     1354     * @dataProvider data_add_data_module_dependencies_validation
     1355     *
     1356     * @param mixed      $data     Data to add.
     1357     * @param string     $message  Expected error message.
     1358     * @param bool       $expected Expected return value.
     1359     * @param array|null $stored   Expected stored value.
     1360     */
     1361    public function test_add_data_module_dependencies_validation( $data, string $message, bool $expected, ?array $stored ) {
     1362        wp_register_script( 'test-script', '/test.js' );
     1363
     1364        $expected_incorrect_usage = 'WP_Scripts::add_data';
     1365        $this->setExpectedIncorrectUsage( $expected_incorrect_usage );
     1366
     1367        $this->assertSame( $expected, wp_scripts()->add_data( 'test-script', 'module_dependencies', $data ) );
     1368        $this->assertStringContainsString( $message, $this->caught_doing_it_wrong[ $expected_incorrect_usage ] );
     1369
     1370        if ( null === $stored ) {
     1371            $this->assertFalse( wp_scripts()->get_data( 'test-script', 'module_dependencies' ) );
     1372        } else {
     1373            $this->assertSame( $stored, wp_scripts()->get_data( 'test-script', 'module_dependencies' ) );
     1374        }
     1375    }
     1376
     1377    /**
     1378     * Data provider.
     1379     *
     1380     * @return array<string, array{data: mixed, message: string, expected: bool, stored: array<string|array<string, string>>|null}>
     1381     */
     1382    public function data_add_data_module_dependencies_validation(): array {
     1383        return array(
     1384            'non-array' => array(
     1385                'data'     => 'not-an-array',
     1386                'message'  => 'The value for "module_dependencies" must be an array',
     1387                'expected' => false,
     1388                'stored'   => null,
     1389            ),
     1390            'bad-items' => array(
     1391                'data'     => array( 'valid', 123, true, array(), array( 'id' => 'valid2' ) ),
     1392                'message'  => 'has one or more of its script module dependencies ("module_dependencies") which are invalid',
     1393                'expected' => true,
     1394                'stored'   => array( 'valid', array( 'id' => 'valid2' ) ),
     1395            ),
     1396        );
    12781397    }
    12791398
Note: See TracChangeset for help on using the changeset viewer.