Changeset 60930
- Timestamp:
- 10/14/2025 12:10:31 AM (3 months ago)
- Location:
- trunk
- Files:
-
- 5 edited
-
src/wp-includes/class-wp-block.php (modified) (2 diffs)
-
src/wp-includes/class-wp-script-modules.php (modified) (9 diffs)
-
tests/phpunit/tests/blocks/editor.php (modified) (2 diffs)
-
tests/phpunit/tests/blocks/wpBlock.php (modified) (4 diffs)
-
tests/phpunit/tests/script-modules/wpScriptModules.php (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/wp-includes/class-wp-block.php
r60807 r60930 492 492 public function render( $options = array() ) { 493 493 global $post; 494 495 // Capture the current assets queues and then clear out to capture the diff of what was introduced by rendering. 496 $before_styles_queue = wp_styles()->queue; 497 $before_scripts_queue = wp_scripts()->queue; 498 $before_script_modules_queue = wp_script_modules()->queue; 499 wp_styles()->queue = array(); 500 wp_scripts()->queue = array(); 501 wp_script_modules()->queue = array(); 494 502 495 503 /* … … 662 670 } 663 671 672 // Capture the new assets enqueued during rendering, and restore the queues the state prior to rendering. 673 $new_styles_queue = wp_styles()->queue; 674 $new_scripts_queue = wp_scripts()->queue; 675 $new_script_modules_queue = wp_script_modules()->queue; 676 wp_styles()->queue = $before_styles_queue; 677 wp_scripts()->queue = $before_scripts_queue; 678 wp_script_modules()->queue = $before_script_modules_queue; 679 $has_new_styles = count( $new_styles_queue ) > 0; 680 $has_new_scripts = count( $new_scripts_queue ) > 0; 681 $has_new_script_modules = count( $new_script_modules_queue ) > 0; 682 683 // Merge the newly enqueued assets with the existing assets if the rendered block is not empty. 684 if ( 685 ( $has_new_styles || $has_new_scripts || $has_new_script_modules ) && 686 ( 687 trim( $block_content ) !== '' || 688 /** 689 * Filters whether to enqueue assets for a block which has no rendered content. 690 * 691 * @since 6.9.0 692 * 693 * @param bool $enqueue Whether to enqueue assets. 694 * @param string $block_name Block name. 695 */ 696 (bool) apply_filters( 'enqueue_empty_block_content_assets', false, $this->name ) 697 ) 698 ) { 699 if ( $has_new_styles ) { 700 wp_styles()->queue = array_unique( array_merge( wp_styles()->queue, $new_styles_queue ) ); 701 } 702 if ( $has_new_scripts ) { 703 wp_scripts()->queue = array_unique( array_merge( wp_scripts()->queue, $new_scripts_queue ) ); 704 } 705 if ( $has_new_script_modules ) { 706 wp_script_modules()->queue = array_unique( array_merge( wp_script_modules()->queue, $new_script_modules_queue ) ); 707 } 708 } 709 664 710 return $block_content; 665 711 } -
trunk/src/wp-includes/class-wp-script-modules.php
r60704 r60930 24 24 25 25 /** 26 * Holds the script module identifiers that were enqueued before registered.27 * 28 * @since 6. 5.029 * @var array<string, true>30 */ 31 p rivate $enqueued_before_registered= array();26 * An array of IDs for queued script modules. 27 * 28 * @since 6.9.0 29 * @var string[] 30 */ 31 public $queue = array(); 32 32 33 33 /** … … 123 123 'src' => $src, 124 124 'version' => $version, 125 'enqueue' => isset( $this->enqueued_before_registered[ $id ] ),126 125 'dependencies' => $dependencies, 127 126 'fetchpriority' => $fetchpriority, … … 214 213 */ 215 214 public function enqueue( string $id, string $src = '', array $deps = array(), $version = false, array $args = array() ) { 216 if ( isset( $this->registered[ $id ] ) ) { 217 $this->registered[ $id ]['enqueue'] = true; 218 } elseif ( $src ) { 215 if ( ! in_array( $id, $this->queue, true ) ) { 216 $this->queue[] = $id; 217 } 218 if ( ! isset( $this->registered[ $id ] ) && $src ) { 219 219 $this->register( $id, $src, $deps, $version, $args ); 220 $this->registered[ $id ]['enqueue'] = true;221 } else {222 $this->enqueued_before_registered[ $id ] = true;223 220 } 224 221 } … … 232 229 */ 233 230 public function dequeue( string $id ) { 234 if ( isset( $this->registered[ $id ] ) ) { 235 $this->registered[ $id ]['enqueue'] = false; 236 } 237 unset( $this->enqueued_before_registered[ $id ] ); 231 $this->queue = array_diff( $this->queue, array( $id ) ); 238 232 } 239 233 … … 246 240 */ 247 241 public function deregister( string $id ) { 242 $this->dequeue( $id ); 248 243 unset( $this->registered[ $id ] ); 249 unset( $this->enqueued_before_registered[ $id ] );250 244 } 251 245 … … 305 299 */ 306 300 public function print_script_module_preloads() { 307 foreach ( $this->get_dependencies( array_ keys( $this->get_marked_for_enqueue()), array( 'static' ) ) as $id => $script_module ) {301 foreach ( $this->get_dependencies( array_unique( $this->queue ), array( 'static' ) ) as $id => $script_module ) { 308 302 // Don't preload if it's marked for enqueue. 309 if ( true !== $script_module['enqueue']) {303 if ( ! in_array( $id, $this->queue, true ) ) { 310 304 echo sprintf( 311 305 '<link rel="modulepreload" href="%s" id="%s"%s>', … … 346 340 private function get_import_map(): array { 347 341 $imports = array(); 348 foreach ( $this->get_dependencies( array_ keys( $this->get_marked_for_enqueue()) ) as $id => $script_module ) {342 foreach ( $this->get_dependencies( array_unique( $this->queue ) ) as $id => $script_module ) { 349 343 $imports[ $id ] = $this->get_src( $id ); 350 344 } … … 360 354 */ 361 355 private function get_marked_for_enqueue(): array { 362 $enqueued = array(); 363 foreach ( $this->registered as $id => $script_module ) { 364 if ( true === $script_module['enqueue'] ) { 365 $enqueued[ $id ] = $script_module; 366 } 367 } 368 return $enqueued; 356 return wp_array_slice_assoc( 357 $this->registered, 358 $this->queue 359 ); 369 360 } 370 361 … … 458 449 public function print_script_module_data(): void { 459 450 $modules = array(); 460 foreach ( array_ keys( $this->get_marked_for_enqueue()) as $id ) {451 foreach ( array_unique( $this->queue ) as $id ) { 461 452 if ( '@wordpress/a11y' === $id ) { 462 453 $this->a11y_available = true; -
trunk/tests/phpunit/tests/blocks/editor.php
r60719 r60930 32 32 global $post_ID; 33 33 $post_ID = 1; 34 35 global $wp_scripts, $wp_styles; 36 $this->original_wp_scripts = $wp_scripts; 37 $this->original_wp_styles = $wp_styles; 38 $wp_scripts = null; 39 $wp_styles = null; 40 wp_scripts(); 41 wp_styles(); 34 42 } 35 43 36 44 public function tear_down() { 45 global $wp_scripts, $wp_styles; 46 $wp_scripts = $this->original_wp_scripts; 47 $wp_styles = $this->original_wp_styles; 48 37 49 /** @var WP_REST_Server $wp_rest_server */ 38 50 global $wp_rest_server; … … 42 54 parent::tear_down(); 43 55 } 56 57 /** 58 * @var WP_Scripts|null 59 */ 60 protected $original_wp_scripts; 61 62 /** 63 * @var WP_Styles|null 64 */ 65 protected $original_wp_styles; 44 66 45 67 public function filter_set_block_categories_post( $block_categories, $post ) { -
trunk/tests/phpunit/tests/blocks/wpBlock.php
r59866 r60930 14 14 * Fake block type registry. 15 15 * 16 * @var WP_Block_Type_Registry 16 * @var WP_Block_Type_Registry|null 17 17 */ 18 18 private $registry = null; … … 24 24 parent::set_up(); 25 25 26 global $wp_styles, $wp_scripts, $wp_script_modules; 27 $wp_styles = null; 28 $wp_scripts = null; 29 $wp_script_modules = null; 30 26 31 $this->registry = new WP_Block_Type_Registry(); 27 32 } … … 32 37 public function tear_down() { 33 38 $this->registry = null; 39 40 global $wp_styles, $wp_scripts, $wp_script_modules; 41 $wp_styles = null; 42 $wp_scripts = null; 43 $wp_script_modules = null; 34 44 35 45 parent::tear_down(); … … 351 361 352 362 $this->assertSame( 'Original: "StaticOriginal: "Inner", from block "core/example"", from block "core/example"', $rendered_content ); 363 } 364 365 /** 366 * Data provider for test_render_enqueues_scripts_and_styles. 367 * 368 * @return array 369 */ 370 public function data_provider_test_render_enqueues_scripts_and_styles(): array { 371 $block_markup = ' 372 <!-- wp:static --> 373 <div class="static"> 374 <!-- wp:static-child --> 375 <div class="static-child">First child</div> 376 <!-- /wp:static-child --> 377 <!-- wp:dynamic /--> 378 <!-- wp:static-child --> 379 <div class="static-child">Last child</div> 380 <!-- /wp:static-child --> 381 </div> 382 <!-- /wp:static --> 383 '; 384 385 // TODO: Add case where a dynamic block renders other blocks? 386 return array( 387 'all_printed' => array( 388 'set_up' => null, 389 'block_markup' => $block_markup, 390 'expected_rendered_block' => ' 391 <div class="static"> 392 <div class="static-child">First child</div> 393 <p class="dynamic">Hello World!</p> 394 <div class="static-child">Last child</div> 395 </div> 396 ', 397 'expected_styles' => array( 'static-view-style', 'static-child-view-style', 'dynamic-view-style' ), 398 'expected_scripts' => array( 'static-view-script', 'static-child-view-script', 'dynamic-view-script' ), 399 'expected_script_modules' => array( 'static-view-script-module', 'static-child-view-script-module', 'dynamic-view-script-module' ), 400 ), 401 'all_printed_with_extra_asset_via_filter' => array( 402 'set_up' => static function () { 403 add_filter( 404 'render_block_core/dynamic', 405 static function ( $content ) { 406 wp_enqueue_style( 'dynamic-extra', home_url( '/dynamic-extra.css' ), array(), null ); 407 $processor = new WP_HTML_Tag_Processor( $content ); 408 if ( $processor->next_tag() ) { 409 $processor->add_class( 'filtered' ); 410 $content = $processor->get_updated_html(); 411 } 412 return $content; 413 } 414 ); 415 }, 416 'block_markup' => $block_markup, 417 'expected_rendered_block' => ' 418 <div class="static"> 419 <div class="static-child">First child</div> 420 <p class="dynamic filtered">Hello World!</p> 421 <div class="static-child">Last child</div> 422 </div> 423 ', 424 'expected_styles' => array( 'static-view-style', 'dynamic-extra', 'static-child-view-style', 'dynamic-view-style' ), 425 'expected_scripts' => array( 'static-view-script', 'static-child-view-script', 'dynamic-view-script' ), 426 'expected_script_modules' => array( 'static-view-script-module', 'static-child-view-script-module', 'dynamic-view-script-module' ), 427 ), 428 'dynamic_hidden_assets_omitted' => array( 429 'set_up' => static function () { 430 add_filter( 'render_block_core/dynamic', '__return_empty_string' ); 431 }, 432 'block_markup' => $block_markup, 433 'expected_rendered_block' => ' 434 <div class="static"> 435 <div class="static-child">First child</div> 436 <div class="static-child">Last child</div> 437 </div> 438 ', 439 'expected_styles' => array( 'static-view-style', 'static-child-view-style' ), 440 'expected_scripts' => array( 'static-view-script', 'static-child-view-script' ), 441 'expected_script_modules' => array( 'static-view-script-module', 'static-child-view-script-module' ), 442 ), 443 'dynamic_hidden_assets_included' => array( 444 'set_up' => static function () { 445 add_filter( 'render_block_core/dynamic', '__return_empty_string' ); 446 add_filter( 447 'enqueue_empty_block_content_assets', 448 static function ( $enqueue, $block_name ) { 449 if ( 'core/dynamic' === $block_name ) { 450 $enqueue = true; 451 } 452 return $enqueue; 453 }, 454 10, 455 2 456 ); 457 }, 458 'block_markup' => $block_markup, 459 'expected_rendered_block' => ' 460 <div class="static"> 461 <div class="static-child">First child</div> 462 <div class="static-child">Last child</div> 463 </div> 464 ', 465 'expected_styles' => array( 'static-view-style', 'static-child-view-style', 'dynamic-view-style' ), 466 'expected_scripts' => array( 'static-view-script', 'static-child-view-script', 'dynamic-view-script' ), 467 'expected_script_modules' => array( 'static-view-script-module', 'static-child-view-script-module', 'dynamic-view-script-module' ), 468 ), 469 'static_hidden_assets_omitted' => array( 470 'set_up' => static function () { 471 add_filter( 'render_block_core/static', '__return_empty_string' ); 472 add_filter( 473 'render_block_core/dynamic', 474 static function ( $content ) { 475 wp_enqueue_style( 'dynamic-extra', home_url( '/dynamic-extra.css' ), array(), null ); 476 return $content; 477 } 478 ); 479 }, 480 'block_markup' => $block_markup, 481 'expected_rendered_block' => '', 482 'expected_styles' => array(), 483 'expected_scripts' => array(), 484 'expected_script_modules' => array(), 485 ), 486 'static_child_hidden_assets_omitted' => array( 487 'set_up' => static function () { 488 add_filter( 'render_block_core/static-child', '__return_empty_string' ); 489 }, 490 'block_markup' => $block_markup, 491 'expected_rendered_block' => ' 492 <div class="static"> 493 <p class="dynamic">Hello World!</p> 494 </div> 495 ', 496 'expected_styles' => array( 'static-view-style', 'dynamic-view-style' ), 497 'expected_scripts' => array( 'static-view-script', 'dynamic-view-script' ), 498 'expected_script_modules' => array( 'static-view-script-module', 'dynamic-view-script-module' ), 499 ), 500 'last_static_child_hidden_assets_omitted' => array( 501 'set_up' => static function () { 502 add_filter( 503 'render_block_core/static-child', 504 static function ( $content ) { 505 if ( str_contains( $content, 'Last child' ) ) { 506 $content = ''; 507 } 508 return $content; 509 }, 510 10, 511 3 512 ); 513 }, 514 'block_markup' => $block_markup, 515 'expected_rendered_block' => ' 516 <div class="static"> 517 <div class="static-child">First child</div> 518 <p class="dynamic">Hello World!</p> 519 </div> 520 ', 521 'expected_styles' => array( 'static-view-style', 'static-child-view-style', 'dynamic-view-style' ), 522 'expected_scripts' => array( 'static-view-script', 'static-child-view-script', 'dynamic-view-script' ), 523 'expected_script_modules' => array( 'static-view-script-module', 'static-child-view-script-module', 'dynamic-view-script-module' ), 524 ), 525 'all_hidden_assets_omitted' => array( 526 'set_up' => static function () { 527 add_filter( 'render_block', '__return_empty_string' ); 528 }, 529 'block_markup' => $block_markup, 530 'expected_rendered_block' => '', 531 'expected_styles' => array(), 532 'expected_scripts' => array(), 533 'expected_script_modules' => array(), 534 ), 535 'all_hidden_assets_included' => array( 536 'set_up' => static function () { 537 add_filter( 'render_block', '__return_empty_string' ); 538 add_filter( 'enqueue_empty_block_content_assets', '__return_true' ); 539 }, 540 'block_markup' => $block_markup, 541 'expected_rendered_block' => '', 542 'expected_styles' => array( 'static-view-style', 'static-child-view-style', 'dynamic-view-style' ), 543 'expected_scripts' => array( 'static-view-script', 'static-child-view-script', 'dynamic-view-script' ), 544 'expected_script_modules' => array( 'static-view-script-module', 'static-child-view-script-module', 'dynamic-view-script-module' ), 545 ), 546 ); 547 } 548 549 /** 550 * @ticket 63676 551 * @covers WP_Block::render() 552 * 553 * @dataProvider data_provider_test_render_enqueues_scripts_and_styles 554 * 555 * @param Closure|null $set_up 556 * @param string $block_markup 557 * @param string[] $expected_styles 558 * @param string[] $expected_scripts 559 * @param string[] $expected_script_modules 560 */ 561 public function test_render_enqueues_scripts_and_styles( ?Closure $set_up, string $block_markup, string $expected_rendered_block, array $expected_styles, array $expected_scripts, array $expected_script_modules ) { 562 if ( $set_up instanceof Closure ) { 563 $set_up(); 564 } 565 wp_register_style( 'static-view-style', home_url( '/static-view-style.css' ) ); 566 wp_register_script( 'static-view-script', home_url( '/static-view-script.js' ) ); 567 wp_register_script_module( 'static-view-script-module', home_url( '/static-view-script-module.js' ) ); 568 $this->registry->register( 569 'core/static', 570 array( 571 'view_style_handles' => array( 'static-view-style' ), 572 'view_script_handles' => array( 'static-view-script' ), 573 'view_script_module_ids' => array( 'static-view-script-module' ), 574 ) 575 ); 576 577 wp_register_style( 'static-child-view-style', home_url( '/static-child-view-style.css' ) ); 578 wp_register_script( 'static-child-view-script', home_url( '/static-child-view-script.js' ) ); 579 wp_register_script_module( 'static-child-view-script-module', home_url( '/static-child-view-script-module.js' ) ); 580 $this->registry->register( 581 'core/static-child', 582 array( 583 'view_style_handles' => array( 'static-child-view-style' ), 584 'view_script_handles' => array( 'static-child-view-script' ), 585 'view_script_module_ids' => array( 'static-child-view-script-module' ), 586 ) 587 ); 588 589 wp_register_style( 'dynamic-view-style', home_url( '/dynamic-view-style.css' ) ); 590 wp_register_script( 'dynamic-view-script', home_url( '/dynamic-view-script.js' ) ); 591 wp_register_script_module( 'dynamic-view-script-module', home_url( '/dynamic-view-script-module.js' ) ); 592 $this->registry->register( 593 'core/dynamic', 594 array( 595 'render_callback' => static function () { 596 return '<p class="dynamic">Hello World!</p>'; 597 }, 598 'view_style_handles' => array( 'dynamic-view-style' ), 599 'view_script_handles' => array( 'dynamic-view-script' ), 600 'view_script_module_ids' => array( 'dynamic-view-script-module' ), 601 ) 602 ); 603 604 // TODO: Why not use do_blocks() instead? 605 $parsed_blocks = parse_blocks( trim( $block_markup ) ); 606 $parsed_block = $parsed_blocks[0]; 607 $context = array(); 608 $block = new WP_Block( $parsed_block, $context, $this->registry ); 609 $rendered_block = $block->render(); 610 611 $this->assertEqualHTML( 612 $expected_rendered_block, 613 $rendered_block, 614 '<body>', 615 "Rendered block does not contain expected HTML:\n$rendered_block" 616 ); 617 618 remove_action( 'wp_print_styles', 'print_emoji_styles' ); 619 620 $actual_styles = array(); 621 $printed_styles = get_echo( 'wp_print_styles' ); 622 $processor = new WP_HTML_Tag_Processor( $printed_styles ); 623 while ( $processor->next_tag( array( 'tag_name' => 'LINK' ) ) ) { 624 if ( 1 === preg_match( '/^(.+)-css$/', $processor->get_attribute( 'id' ), $matches ) ) { 625 $actual_styles[] = $matches[1]; 626 } 627 } 628 $this->assertSameSets( $expected_styles, $actual_styles, 'Enqueued styles do not meet expectations' ); 629 630 $actual_scripts = array(); 631 $printed_scripts = get_echo( 'wp_print_scripts' ); 632 $processor = new WP_HTML_Tag_Processor( $printed_scripts ); 633 while ( $processor->next_tag( array( 'tag_name' => 'SCRIPT' ) ) ) { 634 if ( 1 === preg_match( '/^(.+)-js$/', $processor->get_attribute( 'id' ), $matches ) ) { 635 $actual_scripts[] = $matches[1]; 636 } 637 } 638 $this->assertSameSets( $expected_scripts, $actual_scripts, 'Enqueued scripts do not meet expectations' ); 639 640 $actual_script_modules = array(); 641 $printed_script_modules = get_echo( array( wp_script_modules(), 'print_enqueued_script_modules' ) ); 642 $processor = new WP_HTML_Tag_Processor( $printed_script_modules ); 643 while ( $processor->next_tag( array( 'tag_name' => 'SCRIPT' ) ) ) { 644 if ( 1 === preg_match( '/^(.+)-js-module$/', $processor->get_attribute( 'id' ), $matches ) ) { 645 $actual_script_modules[] = $matches[1]; 646 } 647 } 648 $this->assertSameSets( $expected_script_modules, $actual_script_modules, 'Enqueued script modules do not meet expectations' ); 353 649 } 354 650 -
trunk/tests/phpunit/tests/script-modules/wpScriptModules.php
r60729 r60930 1345 1345 1346 1346 /** 1347 * Tests that directly manipulating the queue works as expected. 1348 * 1349 * @ticket 63676 1350 * 1351 * @covers WP_Script_Modules::queue 1352 * @covers WP_Script_Modules::dequeue 1353 */ 1354 public function test_direct_queue_manipulation() { 1355 $this->script_modules->register( 'foo', '/foo.js' ); 1356 $this->script_modules->register( 'bar', '/bar.js' ); 1357 $this->script_modules->register( 'baz', '/baz.js' ); 1358 $this->assertSame( array(), $this->script_modules->queue, 'Expected queue to be empty.' ); 1359 $this->script_modules->enqueue( 'foo' ); 1360 $this->script_modules->enqueue( 'foo' ); 1361 $this->script_modules->enqueue( 'bar' ); 1362 $this->assertSame( array( 'foo', 'bar' ), $this->script_modules->queue, 'Expected two deduplicated queued items.' ); 1363 $this->script_modules->queue = array( 'baz' ); 1364 $this->script_modules->enqueue( 'bar' ); 1365 $this->assertSame( array( 'baz', 'bar' ), $this->script_modules->queue, 'Expected queue updated via setter and enqueue method to have two items.' ); 1366 $this->script_modules->dequeue( 'baz' ); 1367 $this->script_modules->dequeue( 'bar' ); 1368 $this->assertSame( array(), $this->script_modules->queue, 'Expected queue to be empty after dequeueing both items.' ); 1369 } 1370 1371 /** 1347 1372 * Gets registered script modules. 1348 1373 *
Note: See TracChangeset
for help on using the changeset viewer.