From 6f546a023c06c558d99e9ef0c50c6f1a3fd5b3ba Mon Sep 17 00:00:00 2001 From: Jb Audras Date: Tue, 7 Dec 2021 17:44:46 +0000 Subject: [PATCH] Script Loader: Allow for `wp_register_script()` to be called after `wp_enqueue_script()`. When a plugin registers styles/scripts on `wp_enqueue_scripts` (as plugin authors are encouraged to do), and conditionally enqueues their script/style on `the_content` filter, things "just work". In block themes, `the_content` is run prior to the header being processed, which results in the above scenario failing. This change makes a `wp_enqueue_script( 'example' ); wp_register_script( 'example' );` work, where as currently the enqueue silently fails (no "doing it wrong" message) and the following register has no impact. Scripts can therefore be enqueued and dequeued (by "handle") before they are registered. Fixes #54529. git-svn-id: https://develop.svn.wordpress.org/trunk@52338 602fd350-edb4-49c9-b593-d223f7449a82 --- src/wp-includes/class.wp-dependencies.php | 29 +++++++++++++++++++++++ tests/phpunit/tests/dependencies.php | 14 +++++++++++ 2 files changed, 43 insertions(+) diff --git a/src/wp-includes/class.wp-dependencies.php b/src/wp-includes/class.wp-dependencies.php index e9f701b727..649bf172c3 100644 --- a/src/wp-includes/class.wp-dependencies.php +++ b/src/wp-includes/class.wp-dependencies.php @@ -94,6 +94,15 @@ class WP_Dependencies { */ private $all_queued_deps; + /** + * List of assets enqueued before details were registered. + * + * @since 5.9.0 + * + * @var array + */ + private $queued_before_register = array(); + /** * Processes the items and dependencies. * @@ -248,6 +257,18 @@ class WP_Dependencies { return false; } $this->registered[ $handle ] = new _WP_Dependency( $handle, $src, $deps, $ver, $args ); + + // If the item was enqueued before the details were registered, enqueue it now. + if ( array_key_exists( $handle, $this->queued_before_register ) ) { + if ( ! is_null( $this->queued_before_register[ $handle ] ) ) { + $this->enqueue( $handle . '?' . $this->queued_before_register[ $handle ] ); + } else { + $this->enqueue( $handle ); + } + + unset( $this->queued_before_register[ $handle ] ); + } + return true; } @@ -334,6 +355,12 @@ class WP_Dependencies { if ( isset( $handle[1] ) ) { $this->args[ $handle[0] ] = $handle[1]; } + } else if ( ! isset( $this->registered[ $handle[0] ] ) ) { + $this->queued_before_register[ $handle[0] ] = null; // $args + + if ( isset( $handle[1] ) ) { + $this->queued_before_register[ $handle[0] ] = $handle[1]; + } } } } @@ -360,6 +387,8 @@ class WP_Dependencies { unset( $this->queue[ $key ] ); unset( $this->args[ $handle[0] ] ); + } else if ( array_key_exists( $handle[0], $this->queued_before_register ) ) { + unset( $this->queued_before_register[ $handle[0] ] ); } } } diff --git a/tests/phpunit/tests/dependencies.php b/tests/phpunit/tests/dependencies.php index 354bfd376e..0087a0c143 100644 --- a/tests/phpunit/tests/dependencies.php +++ b/tests/phpunit/tests/dependencies.php @@ -136,4 +136,18 @@ class Tests_Dependencies extends WP_UnitTestCase { $this->assertFalse( $dep->query( 'one' ) ); } + + function test_enqueue_before_register() { + $dep = new WP_Dependencies; + + $this->assertArrayNotHasKey( 'one', $dep->registered ); + + $dep->enqueue( 'one' ); + + $this->assertNotContains( 'one', $dep->queue ); + + $this->assertTrue( $dep->add( 'one', '' ) ); + + $this->assertContains( 'one', $dep->queue ); + } }