From f1cf211969d45930bd60a202b51ca44000315321 Mon Sep 17 00:00:00 2001 From: Catalin Ciobanu Date: Tue, 4 Nov 2025 12:25:32 +0200 Subject: [PATCH 01/13] Fix for https://core.trac.wordpress.org/ticket/64194#ticket --- src/wp-includes/class-wp-scripts.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/wp-includes/class-wp-scripts.php b/src/wp-includes/class-wp-scripts.php index ff226b5661425..aa1dcfc1922fe 100644 --- a/src/wp-includes/class-wp-scripts.php +++ b/src/wp-includes/class-wp-scripts.php @@ -1070,7 +1070,7 @@ private function filter_eligible_strategies( $handle, $eligible_strategies = nul * @param array $checked Optional. An array of already checked script handles, used to avoid recursive loops. * @return string|null Highest fetch priority for the script and its dependents. */ - private function get_highest_fetchpriority_with_dependents( string $handle, array $checked = array() ): ?string { + private function get_highest_fetchpriority_with_dependents( string $handle, array &$checked = array() ): ?string { // If there is a recursive dependency, return early. if ( isset( $checked[ $handle ] ) ) { return null; From d5ca1d1a6e0bfb4a4c271b9ed97ced8adf231044 Mon Sep 17 00:00:00 2001 From: Catalin Ciobanu Date: Wed, 5 Nov 2025 10:20:53 +0200 Subject: [PATCH 02/13] Better solution for issue 64194 --- src/wp-includes/class-wp-scripts.php | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/wp-includes/class-wp-scripts.php b/src/wp-includes/class-wp-scripts.php index aa1dcfc1922fe..a813cb6d8979c 100644 --- a/src/wp-includes/class-wp-scripts.php +++ b/src/wp-includes/class-wp-scripts.php @@ -1068,9 +1068,16 @@ private function filter_eligible_strategies( $handle, $eligible_strategies = nul * * @param string $handle Script module ID. * @param array $checked Optional. An array of already checked script handles, used to avoid recursive loops. + * @param array $stored_results Optional. An array of already computed max priority by handle, used to increase performance in large dependency lists. + * * @return string|null Highest fetch priority for the script and its dependents. */ - private function get_highest_fetchpriority_with_dependents( string $handle, array &$checked = array() ): ?string { + private function get_highest_fetchpriority_with_dependents( string $handle, array $checked = array(), array &$stored_results = array() ): ?string { + if(isset($stored_results[$handle]) && !empty($stored_results[$handle])) { + return $stored_results[$handle]; + } + + // If there is a recursive dependency, return early. if ( isset( $checked[ $handle ] ) ) { return null; @@ -1099,7 +1106,7 @@ private function get_highest_fetchpriority_with_dependents( string $handle, arra $highest_priority_index = (int) array_search( $fetchpriority, $priorities, true ); if ( $highest_priority_index !== $high_priority_index ) { foreach ( $this->get_dependents( $handle ) as $dependent_handle ) { - $dependent_priority = $this->get_highest_fetchpriority_with_dependents( $dependent_handle, $checked ); + $dependent_priority = $this->get_highest_fetchpriority_with_dependents( $dependent_handle, $checked, $stored_results ); if ( is_string( $dependent_priority ) ) { $highest_priority_index = max( $highest_priority_index, @@ -1111,7 +1118,7 @@ private function get_highest_fetchpriority_with_dependents( string $handle, arra } } } - + $stored_results[$handle] = $priorities[ $highest_priority_index ]; return $priorities[ $highest_priority_index ]; } From 3878d181fb6bd488e8db7dc91325f7d585f79927 Mon Sep 17 00:00:00 2001 From: Catalin Ciobanu Date: Wed, 5 Nov 2025 10:47:02 +0200 Subject: [PATCH 03/13] coding standards fixes --- src/wp-includes/class-wp-scripts.php | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/wp-includes/class-wp-scripts.php b/src/wp-includes/class-wp-scripts.php index a813cb6d8979c..66c14d45eedb5 100644 --- a/src/wp-includes/class-wp-scripts.php +++ b/src/wp-includes/class-wp-scripts.php @@ -1073,11 +1073,10 @@ private function filter_eligible_strategies( $handle, $eligible_strategies = nul * @return string|null Highest fetch priority for the script and its dependents. */ private function get_highest_fetchpriority_with_dependents( string $handle, array $checked = array(), array &$stored_results = array() ): ?string { - if(isset($stored_results[$handle]) && !empty($stored_results[$handle])) { - return $stored_results[$handle]; + if ( isset( $stored_results[ $handle ] ) && ! empty( $stored_results[ $handle ] ) ) { + return $stored_results[ $handle ]; } - // If there is a recursive dependency, return early. if ( isset( $checked[ $handle ] ) ) { return null; @@ -1118,7 +1117,7 @@ private function get_highest_fetchpriority_with_dependents( string $handle, arra } } } - $stored_results[$handle] = $priorities[ $highest_priority_index ]; + $stored_results[ $handle ] = $priorities[ $highest_priority_index ]; return $priorities[ $highest_priority_index ]; } From df6561fe681149c2b403d6301502c51990edb3ff Mon Sep 17 00:00:00 2001 From: Catalin Ciobanu Date: Thu, 6 Nov 2025 11:35:54 +0200 Subject: [PATCH 04/13] Fixed performance issue from ticket 64194 for filter_eligible_strategies function Added tests for both functions --- src/wp-includes/class-wp-scripts.php | 9 +- tests/phpunit/tests/dependencies/scripts.php | 125 +++++++++++++++++++ 2 files changed, 132 insertions(+), 2 deletions(-) diff --git a/src/wp-includes/class-wp-scripts.php b/src/wp-includes/class-wp-scripts.php index 66c14d45eedb5..796566fa594bc 100644 --- a/src/wp-includes/class-wp-scripts.php +++ b/src/wp-includes/class-wp-scripts.php @@ -1000,9 +1000,14 @@ private function get_eligible_loading_strategy( $handle ) { * @param string $handle The script handle. * @param string[]|null $eligible_strategies Optional. The list of strategies to filter. Default null. * @param array $checked Optional. An array of already checked script handles, used to avoid recursive loops. + * @param array $stored_results Optional. An array of already computed eligible loading strategies by handle, used to increase performance in large dependency lists. * @return string[] A list of eligible loading strategies that could be used. */ - private function filter_eligible_strategies( $handle, $eligible_strategies = null, $checked = array() ) { + private function filter_eligible_strategies( $handle, $eligible_strategies = null, $checked = array(), array &$stored_results = array() ) { + if ( isset( $stored_results[ $handle ] ) && ! empty( $stored_results[ $handle ] ) ) { + return $stored_results[ $handle ]; + } + // If no strategies are being passed, all strategies are eligible. if ( null === $eligible_strategies ) { $eligible_strategies = $this->delayed_strategies; @@ -1055,7 +1060,7 @@ private function filter_eligible_strategies( $handle, $eligible_strategies = nul $eligible_strategies = $this->filter_eligible_strategies( $dependent, $eligible_strategies, $checked ); } - + $stored_results[ $handle ] = $eligible_strategies; return $eligible_strategies; } diff --git a/tests/phpunit/tests/dependencies/scripts.php b/tests/phpunit/tests/dependencies/scripts.php index fec0d032227c7..1e26f2a9f7ba6 100644 --- a/tests/phpunit/tests/dependencies/scripts.php +++ b/tests/phpunit/tests/dependencies/scripts.php @@ -1435,6 +1435,66 @@ public function test_fetchpriority_bumping_a_to_z() { $this->assertEqualHTML( $expected, $actual, '', "Snapshot:\n$actual" ); } + /** + * @ticket 64194 + * + * Tests that `WP_Scripts::get_highest_fetchpriority_with_dependents()` correctly + * reuses cached results (`$stored_results`) for shared dependencies in a diamond-shaped graph. + * + * Dependency Graph: + * + * D <- [B, C] + * B <- [A] + * C <- [A] + * A <- [] + * + * This verifies that when multiple dependents share a common dependency (`D`), + * the cached result for `D` is used rather than recalculating it multiple times. + * @covers WP_Scripts::get_highest_fetchpriority_with_dependents + */ + + public function test_highest_fetchpriority_with_dependents_uses_cached_result_for_shared_dependency() { + $wp_scripts = new WP_Scripts(); + + /* + * Register scripts forming a diamond-shaped dependency graph: + * D is the shared dependent of B and C, and A depends on both B and C. + */ + $wp_scripts->add( 'a', 'https://example.com/a.js', array( 'b', 'c' ) ); + $wp_scripts->add( 'b', 'https://example.com/b.js', array( 'd' ) ); + $wp_scripts->add( 'c', 'https://example.com/c.js', array( 'd' ) ); + $wp_scripts->add( 'd', 'https://example.com/d.js' ); + + // Enqueue all scripts so they are considered active ("enqueued"). + foreach ( array( 'a', 'b', 'c', 'd' ) as $handle ) { + $wp_scripts->enqueue( $handle ); + } + + $wp_scripts->add_data( 'a', 'fetchpriority', 'auto' ); + $wp_scripts->add_data( 'b', 'fetchpriority', 'low' ); + $wp_scripts->add_data( 'c', 'fetchpriority', 'low' ); + $wp_scripts->add_data( 'd', 'fetchpriority', 'low' ); + + /* + * Simulate a pre-existing `$stored_results` cache entry for `d`. + * If the caching logic works, the function should use this "high" value + * instead of recalculating based on the actual (lower) value. + */ + $stored_results = array( 'd' => 'high' ); + + // Access the private method using reflection. + $method = new ReflectionMethod( WP_Scripts::class, 'get_highest_fetchpriority_with_dependents' ); + $method->setAccessible( true ); + + // Pass `$stored_results` BY REFERENCE. + $result = $method->invokeArgs( $wp_scripts, array( 'd', array(), &$stored_results ) ); + + $this->assertSame( + 'high', + $result, + 'Expected "high" indicates that the cached `$stored_results` entry for D was used instead of recalculating.' + ); + } /** * Tests that printing a script without enqueueing has the same output as when it is enqueued. * @@ -1533,7 +1593,72 @@ public function test_loading_strategy_with_valid_blocking_registration() { $expected = str_replace( "'", '"', $expected ); $this->assertSame( $expected, $output, 'Scripts registered with no strategy assigned, and who have no dependencies, should have no loading strategy attributes printed.' ); } + /** + * @ticket 64194 + * + * Tests that `WP_Scripts::filter_eligible_strategies()` correctly reuses cached results + * for shared dependencies in a diamond-shaped dependency graph. + * + * Dependency Graph: + * + * D <- [B, C] + * B <- [A] + * C <- [A] + * A <- [] + * + * In this scenario, both B and C depend on D, and A depends on both B and C. + * The goal is to confirm that when `$stored_results` already contains an entry for D, + * the cached value is reused instead of recalculating the strategies for D multiple times. + */ + public function test_filter_eligible_strategies_uses_cached_result_for_shared_dependency() { + $wp_scripts = new WP_Scripts(); + + /* + * Register scripts forming a diamond-shaped dependency graph: + * D is the shared dependent of B and C, and A depends on both B and C. + */ + $wp_scripts->add( 'a', 'https://example.com/a.js', array( 'b', 'c' ) ); + $wp_scripts->add( 'b', 'https://example.com/b.js', array( 'd' ) ); + $wp_scripts->add( 'c', 'https://example.com/c.js', array( 'd' ) ); + $wp_scripts->add( 'd', 'https://example.com/d.js' ); + + // Enqueue all scripts so they are treated as active/enqueued. + foreach ( array( 'a', 'b', 'c', 'd' ) as $handle ) { + $wp_scripts->enqueue( $handle ); + } + /* + * Assign strategies: + * - A: async + * - B: async + * - C: async + * - D: async + */ + $wp_scripts->add_data( 'a', 'strategy', 'defer' ); + $wp_scripts->add_data( 'b', 'strategy', 'defer' ); + $wp_scripts->add_data( 'c', 'strategy', 'defer' ); + $wp_scripts->add_data( 'd', 'strategy', 'async' ); + + /* + * Simulate a cached result in `$stored_results` for D. + * If caching logic is functioning properly, this cached value + * should be returned immediately without recomputing. + */ + $stored_results = array( 'd' => array( 'async' ) ); + + // Access the private method via reflection. + $method = new ReflectionMethod( WP_Scripts::class, 'filter_eligible_strategies' ); + $method->setAccessible( true ); + + // Invoke the method with `$stored_results` passed by reference. + $result = $method->invokeArgs( $wp_scripts, array( 'd', null, array(), &$stored_results ) ); + + $this->assertSame( + array( 'async' ), + $result, + 'Expected cached `$stored_results` value for D to be reused instead of recomputed.' + ); + } /** * Tests that scripts registered for the head do indeed end up there. * From e602aa5681ed2325fdd5be790c90a2dea6b647cc Mon Sep 17 00:00:00 2001 From: Catalin Ciobanu Date: Thu, 6 Nov 2025 11:55:00 +0200 Subject: [PATCH 05/13] fix for filter_eligible_strategies --- src/wp-includes/class-wp-scripts.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/wp-includes/class-wp-scripts.php b/src/wp-includes/class-wp-scripts.php index 796566fa594bc..4db484ae27587 100644 --- a/src/wp-includes/class-wp-scripts.php +++ b/src/wp-includes/class-wp-scripts.php @@ -1004,7 +1004,7 @@ private function get_eligible_loading_strategy( $handle ) { * @return string[] A list of eligible loading strategies that could be used. */ private function filter_eligible_strategies( $handle, $eligible_strategies = null, $checked = array(), array &$stored_results = array() ) { - if ( isset( $stored_results[ $handle ] ) && ! empty( $stored_results[ $handle ] ) ) { + if ( isset( $stored_results[ $handle ] ) ) { return $stored_results[ $handle ]; } @@ -1058,7 +1058,7 @@ private function filter_eligible_strategies( $handle, $eligible_strategies = nul return array(); } - $eligible_strategies = $this->filter_eligible_strategies( $dependent, $eligible_strategies, $checked ); + $eligible_strategies = $this->filter_eligible_strategies( $dependent, $eligible_strategies, $checked, $stored_results); } $stored_results[ $handle ] = $eligible_strategies; return $eligible_strategies; From 929af8ed07a3fdd782c0f83187b255d7d479ec56 Mon Sep 17 00:00:00 2001 From: Catalin Ciobanu Date: Thu, 6 Nov 2025 12:06:56 +0200 Subject: [PATCH 06/13] minor code standard fix and also allow empty values in the cache results if that was the previous result --- src/wp-includes/class-wp-scripts.php | 4 ++-- tests/phpunit/tests/dependencies/scripts.php | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/wp-includes/class-wp-scripts.php b/src/wp-includes/class-wp-scripts.php index 4db484ae27587..f833d4ca562a9 100644 --- a/src/wp-includes/class-wp-scripts.php +++ b/src/wp-includes/class-wp-scripts.php @@ -1058,7 +1058,7 @@ private function filter_eligible_strategies( $handle, $eligible_strategies = nul return array(); } - $eligible_strategies = $this->filter_eligible_strategies( $dependent, $eligible_strategies, $checked, $stored_results); + $eligible_strategies = $this->filter_eligible_strategies( $dependent, $eligible_strategies, $checked, $stored_results ); } $stored_results[ $handle ] = $eligible_strategies; return $eligible_strategies; @@ -1078,7 +1078,7 @@ private function filter_eligible_strategies( $handle, $eligible_strategies = nul * @return string|null Highest fetch priority for the script and its dependents. */ private function get_highest_fetchpriority_with_dependents( string $handle, array $checked = array(), array &$stored_results = array() ): ?string { - if ( isset( $stored_results[ $handle ] ) && ! empty( $stored_results[ $handle ] ) ) { + if ( isset( $stored_results[ $handle ] ) ) { return $stored_results[ $handle ]; } diff --git a/tests/phpunit/tests/dependencies/scripts.php b/tests/phpunit/tests/dependencies/scripts.php index 1e26f2a9f7ba6..785e761375c14 100644 --- a/tests/phpunit/tests/dependencies/scripts.php +++ b/tests/phpunit/tests/dependencies/scripts.php @@ -1609,6 +1609,7 @@ public function test_loading_strategy_with_valid_blocking_registration() { * In this scenario, both B and C depend on D, and A depends on both B and C. * The goal is to confirm that when `$stored_results` already contains an entry for D, * the cached value is reused instead of recalculating the strategies for D multiple times. + * @covers WP_Scripts::filter_eligible_strategies */ public function test_filter_eligible_strategies_uses_cached_result_for_shared_dependency() { $wp_scripts = new WP_Scripts(); From 1b15f971cd02377dd52806f01e2314be2f9afbe7 Mon Sep 17 00:00:00 2001 From: Catalin Ciobanu Date: Thu, 6 Nov 2025 14:28:28 +0200 Subject: [PATCH 07/13] fixed build error --- tests/phpunit/tests/dependencies/scripts.php | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/tests/phpunit/tests/dependencies/scripts.php b/tests/phpunit/tests/dependencies/scripts.php index 785e761375c14..e0e2dabba8f04 100644 --- a/tests/phpunit/tests/dependencies/scripts.php +++ b/tests/phpunit/tests/dependencies/scripts.php @@ -1484,8 +1484,9 @@ public function test_highest_fetchpriority_with_dependents_uses_cached_result_fo // Access the private method using reflection. $method = new ReflectionMethod( WP_Scripts::class, 'get_highest_fetchpriority_with_dependents' ); - $method->setAccessible( true ); - + if ( PHP_VERSION_ID < 80100 ) { + $method->setAccessible( true ); + } // Pass `$stored_results` BY REFERENCE. $result = $method->invokeArgs( $wp_scripts, array( 'd', array(), &$stored_results ) ); @@ -1649,8 +1650,9 @@ public function test_filter_eligible_strategies_uses_cached_result_for_shared_de // Access the private method via reflection. $method = new ReflectionMethod( WP_Scripts::class, 'filter_eligible_strategies' ); - $method->setAccessible( true ); - + if ( PHP_VERSION_ID < 80100 ) { + $method->setAccessible( true ); + } // Invoke the method with `$stored_results` passed by reference. $result = $method->invokeArgs( $wp_scripts, array( 'd', null, array(), &$stored_results ) ); From be2c24b2553be7a612d29693db9134226c525f8f Mon Sep 17 00:00:00 2001 From: Weston Ruter Date: Thu, 6 Nov 2025 12:44:53 -0800 Subject: [PATCH 08/13] Tidy phpdoc --- src/wp-includes/class-wp-scripts.php | 13 ++++++------- tests/phpunit/tests/dependencies/scripts.php | 16 +++++++++++----- 2 files changed, 17 insertions(+), 12 deletions(-) diff --git a/src/wp-includes/class-wp-scripts.php b/src/wp-includes/class-wp-scripts.php index f833d4ca562a9..c5786be6cbe41 100644 --- a/src/wp-includes/class-wp-scripts.php +++ b/src/wp-includes/class-wp-scripts.php @@ -997,10 +997,10 @@ private function get_eligible_loading_strategy( $handle ) { * * @since 6.3.0 * - * @param string $handle The script handle. - * @param string[]|null $eligible_strategies Optional. The list of strategies to filter. Default null. - * @param array $checked Optional. An array of already checked script handles, used to avoid recursive loops. - * @param array $stored_results Optional. An array of already computed eligible loading strategies by handle, used to increase performance in large dependency lists. + * @param string $handle The script handle. + * @param string[]|null $eligible_strategies Optional. The list of strategies to filter. Default null. + * @param array $checked Optional. An array of already checked script handles, used to avoid recursive loops. + * @param array $stored_results Optional. An array of already computed eligible loading strategies by handle, used to increase performance in large dependency lists. * @return string[] A list of eligible loading strategies that could be used. */ private function filter_eligible_strategies( $handle, $eligible_strategies = null, $checked = array(), array &$stored_results = array() ) { @@ -1071,10 +1071,9 @@ private function filter_eligible_strategies( $handle, $eligible_strategies = nul * @see self::filter_eligible_strategies() * @see WP_Script_Modules::get_highest_fetchpriority_with_dependents() * - * @param string $handle Script module ID. - * @param array $checked Optional. An array of already checked script handles, used to avoid recursive loops. + * @param string $handle Script module ID. + * @param array $checked Optional. An array of already checked script handles, used to avoid recursive loops. * @param array $stored_results Optional. An array of already computed max priority by handle, used to increase performance in large dependency lists. - * * @return string|null Highest fetch priority for the script and its dependents. */ private function get_highest_fetchpriority_with_dependents( string $handle, array $checked = array(), array &$stored_results = array() ): ?string { diff --git a/tests/phpunit/tests/dependencies/scripts.php b/tests/phpunit/tests/dependencies/scripts.php index e0e2dabba8f04..8caec800cc39a 100644 --- a/tests/phpunit/tests/dependencies/scripts.php +++ b/tests/phpunit/tests/dependencies/scripts.php @@ -1436,8 +1436,6 @@ public function test_fetchpriority_bumping_a_to_z() { } /** - * @ticket 64194 - * * Tests that `WP_Scripts::get_highest_fetchpriority_with_dependents()` correctly * reuses cached results (`$stored_results`) for shared dependencies in a diamond-shaped graph. * @@ -1450,9 +1448,11 @@ public function test_fetchpriority_bumping_a_to_z() { * * This verifies that when multiple dependents share a common dependency (`D`), * the cached result for `D` is used rather than recalculating it multiple times. + * + * @ticket 64194 + * * @covers WP_Scripts::get_highest_fetchpriority_with_dependents */ - public function test_highest_fetchpriority_with_dependents_uses_cached_result_for_shared_dependency() { $wp_scripts = new WP_Scripts(); @@ -1487,6 +1487,7 @@ public function test_highest_fetchpriority_with_dependents_uses_cached_result_fo if ( PHP_VERSION_ID < 80100 ) { $method->setAccessible( true ); } + // Pass `$stored_results` BY REFERENCE. $result = $method->invokeArgs( $wp_scripts, array( 'd', array(), &$stored_results ) ); @@ -1496,6 +1497,7 @@ public function test_highest_fetchpriority_with_dependents_uses_cached_result_fo 'Expected "high" indicates that the cached `$stored_results` entry for D was used instead of recalculating.' ); } + /** * Tests that printing a script without enqueueing has the same output as when it is enqueued. * @@ -1594,9 +1596,8 @@ public function test_loading_strategy_with_valid_blocking_registration() { $expected = str_replace( "'", '"', $expected ); $this->assertSame( $expected, $output, 'Scripts registered with no strategy assigned, and who have no dependencies, should have no loading strategy attributes printed.' ); } + /** - * @ticket 64194 - * * Tests that `WP_Scripts::filter_eligible_strategies()` correctly reuses cached results * for shared dependencies in a diamond-shaped dependency graph. * @@ -1610,6 +1611,9 @@ public function test_loading_strategy_with_valid_blocking_registration() { * In this scenario, both B and C depend on D, and A depends on both B and C. * The goal is to confirm that when `$stored_results` already contains an entry for D, * the cached value is reused instead of recalculating the strategies for D multiple times. + * + * @ticket 64194 + * * @covers WP_Scripts::filter_eligible_strategies */ public function test_filter_eligible_strategies_uses_cached_result_for_shared_dependency() { @@ -1653,6 +1657,7 @@ public function test_filter_eligible_strategies_uses_cached_result_for_shared_de if ( PHP_VERSION_ID < 80100 ) { $method->setAccessible( true ); } + // Invoke the method with `$stored_results` passed by reference. $result = $method->invokeArgs( $wp_scripts, array( 'd', null, array(), &$stored_results ) ); @@ -1662,6 +1667,7 @@ public function test_filter_eligible_strategies_uses_cached_result_for_shared_de 'Expected cached `$stored_results` value for D to be reused instead of recomputed.' ); } + /** * Tests that scripts registered for the head do indeed end up there. * From 8c068bb3e00b322d597143ecaddcff2b1a7ba417 Mon Sep 17 00:00:00 2001 From: Weston Ruter Date: Thu, 6 Nov 2025 12:52:13 -0800 Subject: [PATCH 09/13] Ignore false positive from PHPStan --- src/wp-includes/class-wp-scripts.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/wp-includes/class-wp-scripts.php b/src/wp-includes/class-wp-scripts.php index c5786be6cbe41..8c3b5a4ba9f64 100644 --- a/src/wp-includes/class-wp-scripts.php +++ b/src/wp-includes/class-wp-scripts.php @@ -1121,7 +1121,7 @@ private function get_highest_fetchpriority_with_dependents( string $handle, arra } } } - $stored_results[ $handle ] = $priorities[ $highest_priority_index ]; + $stored_results[ $handle ] = $priorities[ $highest_priority_index ]; // @phpstan-ignore parameterByRef.type (We know the index is valid and that this will be a string.) return $priorities[ $highest_priority_index ]; } From 2b2c09c58348eca12e37a6bd6a97f2b92bce7988 Mon Sep 17 00:00:00 2001 From: Weston Ruter Date: Thu, 6 Nov 2025 13:13:49 -0800 Subject: [PATCH 10/13] Clarify test phpdoc --- tests/phpunit/tests/dependencies/scripts.php | 31 +++++--------------- 1 file changed, 8 insertions(+), 23 deletions(-) diff --git a/tests/phpunit/tests/dependencies/scripts.php b/tests/phpunit/tests/dependencies/scripts.php index 8caec800cc39a..390d391e9bcb9 100644 --- a/tests/phpunit/tests/dependencies/scripts.php +++ b/tests/phpunit/tests/dependencies/scripts.php @@ -1436,18 +1436,11 @@ public function test_fetchpriority_bumping_a_to_z() { } /** - * Tests that `WP_Scripts::get_highest_fetchpriority_with_dependents()` correctly - * reuses cached results (`$stored_results`) for shared dependencies in a diamond-shaped graph. + * Tests that `WP_Scripts::get_highest_fetchpriority_with_dependents()` correctly reuses cached results. * - * Dependency Graph: - * - * D <- [B, C] - * B <- [A] - * C <- [A] - * A <- [] - * - * This verifies that when multiple dependents share a common dependency (`D`), - * the cached result for `D` is used rather than recalculating it multiple times. + * This test uses a diamond-shaped dependency graph where 'a' depends on 'b' and 'c', and both 'b' and 'c' depend + * on 'd'. This verifies that when multiple dependents share a common dependency ('d'), the cached result for 'd' + * is used rather than recalculating it multiple times. * * @ticket 64194 * @@ -1598,19 +1591,11 @@ public function test_loading_strategy_with_valid_blocking_registration() { } /** - * Tests that `WP_Scripts::filter_eligible_strategies()` correctly reuses cached results - * for shared dependencies in a diamond-shaped dependency graph. - * - * Dependency Graph: - * - * D <- [B, C] - * B <- [A] - * C <- [A] - * A <- [] + * Tests that `WP_Scripts::filter_eligible_strategies()` correctly reuses cached results for shared dependencies. * - * In this scenario, both B and C depend on D, and A depends on both B and C. - * The goal is to confirm that when `$stored_results` already contains an entry for D, - * the cached value is reused instead of recalculating the strategies for D multiple times. + * This test uses a diamond-shaped dependency graph where 'a' depends on 'b' and 'c', and both 'b' and 'c' depend + * on 'd' (a diamond-shaped dependency graph). The goal is to confirm that when `$stored_results` already contains + * an entry for 'd', the cached value is reused instead of recalculating the strategies for 'd' multiple times. * * @ticket 64194 * From 2115fa91d4037610d5a80937d09e2510a69ddcdc Mon Sep 17 00:00:00 2001 From: Weston Ruter Date: Thu, 6 Nov 2025 21:45:16 -0800 Subject: [PATCH 11/13] Simplify test_filter_eligible_strategies_uses_cached_result_for_shared_dependency --- tests/phpunit/tests/dependencies/scripts.php | 30 +------------------- 1 file changed, 1 insertion(+), 29 deletions(-) diff --git a/tests/phpunit/tests/dependencies/scripts.php b/tests/phpunit/tests/dependencies/scripts.php index 390d391e9bcb9..b26f002fe8304 100644 --- a/tests/phpunit/tests/dependencies/scripts.php +++ b/tests/phpunit/tests/dependencies/scripts.php @@ -1593,42 +1593,14 @@ public function test_loading_strategy_with_valid_blocking_registration() { /** * Tests that `WP_Scripts::filter_eligible_strategies()` correctly reuses cached results for shared dependencies. * - * This test uses a diamond-shaped dependency graph where 'a' depends on 'b' and 'c', and both 'b' and 'c' depend - * on 'd' (a diamond-shaped dependency graph). The goal is to confirm that when `$stored_results` already contains - * an entry for 'd', the cached value is reused instead of recalculating the strategies for 'd' multiple times. - * * @ticket 64194 * * @covers WP_Scripts::filter_eligible_strategies */ public function test_filter_eligible_strategies_uses_cached_result_for_shared_dependency() { $wp_scripts = new WP_Scripts(); - - /* - * Register scripts forming a diamond-shaped dependency graph: - * D is the shared dependent of B and C, and A depends on both B and C. - */ - $wp_scripts->add( 'a', 'https://example.com/a.js', array( 'b', 'c' ) ); - $wp_scripts->add( 'b', 'https://example.com/b.js', array( 'd' ) ); - $wp_scripts->add( 'c', 'https://example.com/c.js', array( 'd' ) ); $wp_scripts->add( 'd', 'https://example.com/d.js' ); - - // Enqueue all scripts so they are treated as active/enqueued. - foreach ( array( 'a', 'b', 'c', 'd' ) as $handle ) { - $wp_scripts->enqueue( $handle ); - } - - /* - * Assign strategies: - * - A: async - * - B: async - * - C: async - * - D: async - */ - $wp_scripts->add_data( 'a', 'strategy', 'defer' ); - $wp_scripts->add_data( 'b', 'strategy', 'defer' ); - $wp_scripts->add_data( 'c', 'strategy', 'defer' ); - $wp_scripts->add_data( 'd', 'strategy', 'async' ); + $wp_scripts->add_data( 'd', 'strategy', 'defer' ); /* * Simulate a cached result in `$stored_results` for D. From eb741e175a072b9d69a006a33d4c3bb98cc7401c Mon Sep 17 00:00:00 2001 From: Weston Ruter Date: Thu, 6 Nov 2025 21:50:21 -0800 Subject: [PATCH 12/13] Simplify test_highest_fetchpriority_with_dependents_uses_cached_result_for_shared_dependency --- tests/phpunit/tests/dependencies/scripts.php | 21 -------------------- 1 file changed, 21 deletions(-) diff --git a/tests/phpunit/tests/dependencies/scripts.php b/tests/phpunit/tests/dependencies/scripts.php index b26f002fe8304..2db58b75607bf 100644 --- a/tests/phpunit/tests/dependencies/scripts.php +++ b/tests/phpunit/tests/dependencies/scripts.php @@ -1438,34 +1438,13 @@ public function test_fetchpriority_bumping_a_to_z() { /** * Tests that `WP_Scripts::get_highest_fetchpriority_with_dependents()` correctly reuses cached results. * - * This test uses a diamond-shaped dependency graph where 'a' depends on 'b' and 'c', and both 'b' and 'c' depend - * on 'd'. This verifies that when multiple dependents share a common dependency ('d'), the cached result for 'd' - * is used rather than recalculating it multiple times. - * * @ticket 64194 * * @covers WP_Scripts::get_highest_fetchpriority_with_dependents */ public function test_highest_fetchpriority_with_dependents_uses_cached_result_for_shared_dependency() { $wp_scripts = new WP_Scripts(); - - /* - * Register scripts forming a diamond-shaped dependency graph: - * D is the shared dependent of B and C, and A depends on both B and C. - */ - $wp_scripts->add( 'a', 'https://example.com/a.js', array( 'b', 'c' ) ); - $wp_scripts->add( 'b', 'https://example.com/b.js', array( 'd' ) ); - $wp_scripts->add( 'c', 'https://example.com/c.js', array( 'd' ) ); $wp_scripts->add( 'd', 'https://example.com/d.js' ); - - // Enqueue all scripts so they are considered active ("enqueued"). - foreach ( array( 'a', 'b', 'c', 'd' ) as $handle ) { - $wp_scripts->enqueue( $handle ); - } - - $wp_scripts->add_data( 'a', 'fetchpriority', 'auto' ); - $wp_scripts->add_data( 'b', 'fetchpriority', 'low' ); - $wp_scripts->add_data( 'c', 'fetchpriority', 'low' ); $wp_scripts->add_data( 'd', 'fetchpriority', 'low' ); /* From 371719b9cf305e9615ffe2ae07fd4236d246fa11 Mon Sep 17 00:00:00 2001 From: Weston Ruter Date: Thu, 6 Nov 2025 21:52:08 -0800 Subject: [PATCH 13/13] Update test naming after simplification --- tests/phpunit/tests/dependencies/scripts.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/phpunit/tests/dependencies/scripts.php b/tests/phpunit/tests/dependencies/scripts.php index 2db58b75607bf..ebde14efbf261 100644 --- a/tests/phpunit/tests/dependencies/scripts.php +++ b/tests/phpunit/tests/dependencies/scripts.php @@ -1442,7 +1442,7 @@ public function test_fetchpriority_bumping_a_to_z() { * * @covers WP_Scripts::get_highest_fetchpriority_with_dependents */ - public function test_highest_fetchpriority_with_dependents_uses_cached_result_for_shared_dependency() { + public function test_highest_fetchpriority_with_dependents_uses_cached_result() { $wp_scripts = new WP_Scripts(); $wp_scripts->add( 'd', 'https://example.com/d.js' ); $wp_scripts->add_data( 'd', 'fetchpriority', 'low' ); @@ -1570,13 +1570,13 @@ public function test_loading_strategy_with_valid_blocking_registration() { } /** - * Tests that `WP_Scripts::filter_eligible_strategies()` correctly reuses cached results for shared dependencies. + * Tests that `WP_Scripts::filter_eligible_strategies()` correctly reuses cached results. * * @ticket 64194 * * @covers WP_Scripts::filter_eligible_strategies */ - public function test_filter_eligible_strategies_uses_cached_result_for_shared_dependency() { + public function test_filter_eligible_strategies_uses_cached_result() { $wp_scripts = new WP_Scripts(); $wp_scripts->add( 'd', 'https://example.com/d.js' ); $wp_scripts->add_data( 'd', 'strategy', 'defer' );