Changeset 61019
- Timestamp:
- 10/21/2025 11:30:43 AM (4 months ago)
- Location:
- trunk
- Files:
-
- 6 edited
-
src/wp-includes/blocks.php (modified) (1 diff)
-
src/wp-includes/interactivity-api/class-wp-interactivity-api.php (modified) (2 diffs)
-
src/wp-includes/script-modules.php (modified) (1 diff)
-
tests/phpunit/tests/blocks/register.php (modified) (1 diff)
-
tests/phpunit/tests/interactivity-api/wpInteractivityAPI.php (modified) (3 diffs)
-
tests/phpunit/tests/script-modules/wpScriptModules.php (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/wp-includes/blocks.php
r60999 r61019 176 176 $module_version = isset( $module_asset['version'] ) ? $module_asset['version'] : $block_version; 177 177 178 // Blocks using the Interactivity API are server-side rendered, so they are by design not in the critical rendering path and should be deprioritized. 178 $supports_interactivity_true = isset( $metadata['supports']['interactivity'] ) && true === $metadata['supports']['interactivity']; 179 $is_interactive = $supports_interactivity_true || ( isset( $metadata['supports']['interactivity']['interactive'] ) && true === $metadata['supports']['interactivity']['interactive'] ); 180 $supports_client_navigation = $supports_interactivity_true || ( isset( $metadata['supports']['interactivity']['clientNavigation'] ) && true === $metadata['supports']['interactivity']['clientNavigation'] ); 181 179 182 $args = array(); 180 if ( 181 ( isset( $metadata['supports']['interactivity'] ) && true === $metadata['supports']['interactivity'] ) ||182 ( isset( $metadata['supports']['interactivity']['interactive'] ) && true === $metadata['supports']['interactivity']['interactive'] )183 ) {183 184 // Blocks using the Interactivity API are server-side rendered, so they are 185 // by design not in the critical rendering path and should be deprioritized. 186 if ( $is_interactive ) { 184 187 $args['fetchpriority'] = 'low'; 185 188 $args['in_footer'] = true; 189 } 190 191 // Blocks using the Interactivity API that support client-side navigation 192 // must be marked as such in their script modules. 193 if ( $is_interactive && $supports_client_navigation ) { 194 wp_interactivity()->add_client_navigation_support_to_script_module( $module_id ); 186 195 } 187 196 -
trunk/src/wp-includes/interactivity-api/class-wp-interactivity-api.php
r60953 r61019 87 87 88 88 /** 89 * Set of script modules that can be loaded after client-side navigation. 90 * 91 * @since 6.9.0 92 * @var array<string, true> 93 */ 94 private $script_modules_that_can_load_on_client_navigation = array(); 95 96 /** 89 97 * Stack of namespaces defined by `data-wp-interactive` directives, in 90 98 * the order they are processed. … … 372 380 * 373 381 * @since 6.5.0 382 * @since 6.9.0 Adds support for client-side navigation in script modules. 374 383 */ 375 384 public function add_hooks() { 376 385 add_filter( 'script_module_data_@wordpress/interactivity', array( $this, 'filter_script_module_interactivity_data' ) ); 377 386 add_filter( 'script_module_data_@wordpress/interactivity-router', array( $this, 'filter_script_module_interactivity_router_data' ) ); 387 add_filter( 'wp_script_attributes', array( $this, 'add_load_on_client_navigation_attribute_to_script_modules' ), 10, 1 ); 388 } 389 390 /** 391 * Adds the `data-wp-router-options` attribute to script modules that 392 * support client-side navigation. 393 * 394 * This method filters the script attributes to include loading instructions 395 * for the Interactivity API router, indicating which modules can be loaded 396 * during client-side navigation. 397 * 398 * @since 6.9.0 399 * 400 * @param array<string, string|true>|mixed $attributes The script tag attributes. 401 * @return array The modified script tag attributes. 402 */ 403 public function add_load_on_client_navigation_attribute_to_script_modules( $attributes ) { 404 if ( 405 is_array( $attributes ) && 406 isset( $attributes['type'], $attributes['id'] ) && 407 'module' === $attributes['type'] && 408 array_key_exists( 409 preg_replace( '/-js-module$/', '', $attributes['id'] ), 410 $this->script_modules_that_can_load_on_client_navigation 411 ) 412 ) { 413 $attributes['data-wp-router-options'] = wp_json_encode( array( 'loadOnClientNavigation' => true ) ); 414 } 415 return $attributes; 416 } 417 418 /** 419 * Marks a script module as compatible with client-side navigation. 420 * 421 * This method registers a script module to be loaded during client-side 422 * navigation in the Interactivity API router. Script modules marked with 423 * this method will have the `loadOnClientNavigation` option enabled in the 424 * `data-wp-router-options` directive. 425 * 426 * @since 6.9.0 427 * 428 * @param string $script_module_id The script module identifier. 429 */ 430 public function add_client_navigation_support_to_script_module( string $script_module_id ) { 431 $this->script_modules_that_can_load_on_client_navigation[ $script_module_id ] = true; 378 432 } 379 433 -
trunk/src/wp-includes/script-modules.php
r60999 r61019 203 203 } 204 204 205 // Marks all Core blocks as compatible with client-side navigation. 206 if ( str_starts_with( $script_module_id, '@wordpress/block-library' ) ) { 207 wp_interactivity()->add_client_navigation_support_to_script_module( $script_module_id ); 208 } 209 205 210 $path = includes_url( "js/dist/script-modules/{$file_name}" ); 206 211 wp_register_script_module( $script_module_id, $path, $script_module_data['dependencies'], $script_module_data['version'], $args ); -
trunk/tests/phpunit/tests/blocks/register.php
r61008 r61019 428 428 ) === 0 429 429 ); 430 } 431 432 /** 433 * Tests that blocks with supports.interactivity have the 434 * `data-wp-router-options` directive. 435 * 436 * @ticket 64122 437 * 438 * @covers ::register_block_script_module_id 439 */ 440 public function test_register_block_script_module_id_with_interactivity_true() { 441 $metadata = array( 442 'file' => DIR_TESTDATA . '/blocks/notice/block.json', 443 'viewScriptModule' => 'file:./block.js', 444 ); 445 446 $interactivity_true = array_merge( 447 $metadata, 448 array( 449 'name' => 'tests/interactivity-true', 450 'supports' => array( 'interactivity' => true ), 451 ) 452 ); 453 $interactive_and_client_navigation = array_merge( 454 $metadata, 455 array( 456 'name' => 'tests/interactive-and-client-navigation', 457 'supports' => array( 458 'interactivity' => array( 459 'interactive' => true, 460 'clientNavigation' => true, 461 ), 462 ), 463 ) 464 ); 465 $interactive_and_not_client_navigation = array_merge( 466 $metadata, 467 array( 468 'name' => 'tests/interactive-and-not-client-navigation', 469 'supports' => array( 470 'interactivity' => array( 471 'interactive' => true, 472 'clientNavigation' => false, 473 ), 474 ), 475 ) 476 ); 477 $not_interactive_and_client_navigation = array_merge( 478 $metadata, 479 array( 480 'name' => 'tests/not-interactive-and-client-navigation', 481 'supports' => array( 482 'interactivity' => array( 483 'interactive' => false, 484 'clientNavigation' => true, 485 ), 486 ), 487 ) 488 ); 489 $no_interactivity = array_merge( 490 $metadata, 491 array( 492 'name' => 'tests/no-interactivity', 493 'supports' => array(), 494 ) 495 ); 496 497 $interactivity_true_module_id = register_block_script_module_id( $interactivity_true, 'viewScriptModule' ); 498 $interactive_and_client_navigation_module_id = register_block_script_module_id( $interactive_and_client_navigation, 'viewScriptModule' ); 499 $interactive_and_not_client_navigation_module_id = register_block_script_module_id( $interactive_and_not_client_navigation, 'viewScriptModule' ); 500 $not_interactive_and_client_navigation_module_id = register_block_script_module_id( $not_interactive_and_client_navigation, 'viewScriptModule' ); 501 $no_interactivity_module_id = register_block_script_module_id( $no_interactivity, 'viewScriptModule' ); 502 wp_enqueue_script_module( $interactivity_true_module_id ); 503 wp_enqueue_script_module( $interactive_and_client_navigation_module_id ); 504 wp_enqueue_script_module( $interactive_and_not_client_navigation_module_id ); 505 wp_enqueue_script_module( $not_interactive_and_client_navigation_module_id ); 506 wp_enqueue_script_module( $no_interactivity_module_id ); 507 508 $output = get_echo( array( wp_script_modules(), 'print_enqueued_script_modules' ) ); 509 510 $p = new WP_HTML_Tag_Processor( $output ); 511 512 $this->assertTrue( $p->next_tag( array( 'tag_name' => 'SCRIPT' ) ), 'Expected there to be another SCRIPT.' ); 513 $this->assertSame( 'tests-interactivity-true-view-script-module-js-module', $p->get_attribute( 'id' ) ); 514 $this->assertSame( '{"loadOnClientNavigation":true}', $p->get_attribute( 'data-wp-router-options' ) ); 515 516 $this->assertTrue( $p->next_tag( array( 'tag_name' => 'SCRIPT' ) ), 'Expected there to be another SCRIPT.' ); 517 $this->assertSame( 'tests-interactive-and-client-navigation-view-script-module-js-module', $p->get_attribute( 'id' ) ); 518 $this->assertSame( '{"loadOnClientNavigation":true}', $p->get_attribute( 'data-wp-router-options' ) ); 519 520 $this->assertTrue( $p->next_tag( array( 'tag_name' => 'SCRIPT' ) ), 'Expected there to be another SCRIPT.' ); 521 $this->assertSame( 'tests-interactive-and-not-client-navigation-view-script-module-js-module', $p->get_attribute( 'id' ) ); 522 $this->assertNull( $p->get_attribute( 'data-wp-router-options' ) ); 523 524 $this->assertTrue( $p->next_tag( array( 'tag_name' => 'SCRIPT' ) ), 'Expected there to be another SCRIPT.' ); 525 $this->assertSame( 'tests-not-interactive-and-client-navigation-view-script-module-js-module', $p->get_attribute( 'id' ) ); 526 $this->assertNull( $p->get_attribute( 'data-wp-router-options' ) ); 527 528 $this->assertTrue( $p->next_tag( array( 'tag_name' => 'SCRIPT' ) ), 'Expected there to be another SCRIPT.' ); 529 $this->assertSame( 'tests-no-interactivity-view-script-module-js-module', $p->get_attribute( 'id' ) ); 530 $this->assertNull( $p->get_attribute( 'data-wp-router-options' ) ); 430 531 } 431 532 -
trunk/tests/phpunit/tests/interactivity-api/wpInteractivityAPI.php
r60953 r61019 27 27 $this->interactivity = new WP_Interactivity_API(); 28 28 wp_default_script_modules(); 29 $this->interactivity->add_hooks(); 30 } 31 32 /** 33 * Tear down. 34 */ 35 public function tear_down() { 36 global $wp_script_modules; 37 parent::tear_down(); 38 $wp_script_modules = null; 29 39 } 30 40 … … 237 247 */ 238 248 private function get_script_data_filter_result( ?Closure $callback = null ): MockAction { 239 $this->interactivity->add_hooks();240 249 wp_enqueue_script_module( '@wordpress/interactivity' ); 241 250 $filter = new MockAction(); … … 1724 1733 $this->assertStringNotContainsString( 'class="[disallowed]"', $processed_html ); 1725 1734 } 1735 1736 /** 1737 * Tests that add_client_navigation_support_to_script_module marks a 1738 * script module for client navigation. 1739 * 1740 * @ticket 64122 1741 * 1742 * @covers WP_Interactivity_API::add_client_navigation_support_to_script_module 1743 * @covers WP_Interactivity_API::add_load_on_client_navigation_attribute_to_script_modules 1744 */ 1745 public function test_add_client_navigation_support_to_script_module() { 1746 $this->interactivity->add_client_navigation_support_to_script_module( 'marked-module' ); 1747 1748 wp_register_script_module( 'marked-module', '/marked.js' ); 1749 wp_register_script_module( 'unmarked-module', '/unmarked.js' ); 1750 wp_enqueue_script_module( 'marked-module' ); 1751 wp_enqueue_script_module( 'unmarked-module' ); 1752 1753 $output = get_echo( array( wp_script_modules(), 'print_enqueued_script_modules' ) ); 1754 1755 $p = new WP_HTML_Tag_Processor( $output ); 1756 1757 // First module: marked-module should have the attribute. 1758 $p->next_tag( array( 'tag_name' => 'SCRIPT' ) ); 1759 $this->assertSame( 'marked-module-js-module', $p->get_attribute( 'id' ) ); 1760 $this->assertSame( 1761 '{"loadOnClientNavigation":true}', 1762 $p->get_attribute( 'data-wp-router-options' ) 1763 ); 1764 1765 // Second module: unmarked-module should NOT have the attribute. 1766 $p->next_tag( array( 'tag_name' => 'SCRIPT' ) ); 1767 $this->assertSame( 'unmarked-module-js-module', $p->get_attribute( 'id' ) ); 1768 $this->assertNull( $p->get_attribute( 'data-wp-router-options' ) ); 1769 } 1726 1770 } -
trunk/tests/phpunit/tests/script-modules/wpScriptModules.php
r60999 r61019 1807 1807 ' 1808 1808 <script type="module" src="/wp-includes/js/dist/script-modules/a11y/index.min.js" id="@wordpress/a11y-js-module" fetchpriority="low"></script> 1809 <script type="module" src="/wp-includes/js/dist/script-modules/block-library/navigation/view.min.js" id="@wordpress/block-library/navigation/view-js-module" fetchpriority="low" ></script>1809 <script type="module" src="/wp-includes/js/dist/script-modules/block-library/navigation/view.min.js" id="@wordpress/block-library/navigation/view-js-module" fetchpriority="low" data-wp-router-options="{"loadOnClientNavigation":true}"></script> 1810 1810 ', 1811 1811 $actual_footer_script_modules,
Note: See TracChangeset
for help on using the changeset viewer.