Skip to content

Commit c358db3

Browse files
committed
Script Loader: Emit notices when enqueueing a script, style, or script module with missing dependencies.
First Developed in #10545. Backport developed in #10789. Follow-up to [60999]. Reviewed by jorbin, wildworks. Merges [61323], [61357], and [61542]. Props deepakprajapati, westonruter, mukeshpanchal27, jorbin, wildworks. See #63486. Fixes #64229. git-svn-id: https://develop.svn.wordpress.org/branches/6.9@61550 602fd350-edb4-49c9-b593-d223f7449a82
1 parent 13431d6 commit c358db3

7 files changed

Lines changed: 197 additions & 4 deletions

File tree

src/wp-includes/class-wp-dependencies.php

Lines changed: 44 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,18 @@ class WP_Dependencies {
104104
*/
105105
private $queued_before_register = array();
106106

107+
/**
108+
* List of handles for dependencies encountered which themselves have missing dependencies.
109+
*
110+
* A dependency handle is added to this list when it is discovered to have missing dependencies. At this time, a
111+
* warning is emitted with {@see _doing_it_wrong()}. The handle is then added to this list, so that duplicate
112+
* warnings don't occur.
113+
*
114+
* @since 6.9.1
115+
* @var string[]
116+
*/
117+
private $dependencies_with_missing_dependencies = array();
118+
107119
/**
108120
* Processes the items and dependencies.
109121
*
@@ -199,10 +211,22 @@ public function all_deps( $handles, $recursion = false, $group = false ) {
199211
continue;
200212
}
201213

202-
$keep_going = true;
214+
$keep_going = true;
215+
$missing_dependencies = array();
216+
if ( isset( $this->registered[ $handle ] ) && count( $this->registered[ $handle ]->deps ) > 0 ) {
217+
$missing_dependencies = array_diff( $this->registered[ $handle ]->deps, array_keys( $this->registered ) );
218+
}
203219
if ( ! isset( $this->registered[ $handle ] ) ) {
204220
$keep_going = false; // Item doesn't exist.
205-
} elseif ( $this->registered[ $handle ]->deps && array_diff( $this->registered[ $handle ]->deps, array_keys( $this->registered ) ) ) {
221+
} elseif ( count( $missing_dependencies ) > 0 ) {
222+
if ( ! in_array( $handle, $this->dependencies_with_missing_dependencies, true ) ) {
223+
_doing_it_wrong(
224+
get_class( $this ) . '::add',
225+
$this->get_dependency_warning_message( $handle, $missing_dependencies ),
226+
'6.9.1'
227+
);
228+
$this->dependencies_with_missing_dependencies[] = $handle;
229+
}
206230
$keep_going = false; // Item requires dependencies that don't exist.
207231
} elseif ( $this->registered[ $handle ]->deps && ! $this->all_deps( $this->registered[ $handle ]->deps, true, $new_group ) ) {
208232
$keep_going = false; // Item requires dependencies that don't exist.
@@ -535,4 +559,22 @@ public function get_etag( $load ) {
535559
*/
536560
return 'W/"' . md5( $etag ) . '"';
537561
}
562+
563+
/**
564+
* Gets a dependency warning message for a handle.
565+
*
566+
* @since 6.9.1
567+
*
568+
* @param string $handle Handle with missing dependencies.
569+
* @param string[] $missing_dependency_handles Missing dependency handles.
570+
* @return string Formatted, localized warning message.
571+
*/
572+
protected function get_dependency_warning_message( $handle, $missing_dependency_handles ) {
573+
return sprintf(
574+
/* translators: 1: Handle, 2: List of missing dependency handles. */
575+
__( 'The handle "%1$s" was enqueued with dependencies that are not registered: %2$s.' ),
576+
$handle,
577+
implode( wp_get_list_item_separator(), $missing_dependency_handles )
578+
);
579+
}
538580
}

src/wp-includes/class-wp-script-modules.php

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,17 @@ class WP_Script_Modules {
7070
'high',
7171
);
7272

73+
/**
74+
* List of IDs for script modules encountered which have missing dependencies.
75+
*
76+
* An ID is added to this list when it is discovered to have missing dependencies. At this time, a warning is
77+
* emitted with {@see _doing_it_wrong()}. The ID is then added to this list, so that duplicate warnings don't occur.
78+
*
79+
* @since 6.9.1
80+
* @var string[]
81+
*/
82+
private $modules_with_missing_dependencies = array();
83+
7384
/**
7485
* Registers the script module if no script module with that script module
7586
* identifier has already been registered.
@@ -722,7 +733,22 @@ private function sort_item_dependencies( string $id, array $import_types, array
722733
}
723734

724735
// If the item requires dependencies that do not exist, fail.
725-
if ( count( array_diff( $dependency_ids, array_keys( $this->registered ) ) ) > 0 ) {
736+
$missing_dependencies = array_diff( $dependency_ids, array_keys( $this->registered ) );
737+
if ( count( $missing_dependencies ) > 0 ) {
738+
if ( ! in_array( $id, $this->modules_with_missing_dependencies, true ) ) {
739+
_doing_it_wrong(
740+
get_class( $this ) . '::register',
741+
sprintf(
742+
/* translators: 1: Script module ID, 2: List of missing dependency IDs. */
743+
__( 'The script module with the ID "%1$s" was enqueued with dependencies that are not registered: %2$s.' ),
744+
$id,
745+
implode( wp_get_list_item_separator(), $missing_dependencies )
746+
),
747+
'6.9.1'
748+
);
749+
$this->modules_with_missing_dependencies[] = $id;
750+
}
751+
726752
return false;
727753
}
728754

src/wp-includes/class-wp-scripts.php

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1164,4 +1164,22 @@ public function reset() {
11641164
$this->ext_version = '';
11651165
$this->ext_handles = '';
11661166
}
1167+
1168+
/**
1169+
* Gets a script-specific dependency warning message.
1170+
*
1171+
* @since 6.9.1
1172+
*
1173+
* @param string $handle Script handle with missing dependencies.
1174+
* @param string[] $missing_dependency_handles Missing dependency handles.
1175+
* @return string Formatted, localized warning message.
1176+
*/
1177+
protected function get_dependency_warning_message( $handle, $missing_dependency_handles ) {
1178+
return sprintf(
1179+
/* translators: 1: Script handle, 2: List of missing dependency handles. */
1180+
__( 'The script with the handle "%1$s" was enqueued with dependencies that are not registered: %2$s.' ),
1181+
$handle,
1182+
implode( wp_get_list_item_separator(), $missing_dependency_handles )
1183+
);
1184+
}
11671185
}

src/wp-includes/class-wp-styles.php

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -493,4 +493,22 @@ public function reset() {
493493
$this->concat_version = '';
494494
$this->print_html = '';
495495
}
496+
497+
/**
498+
* Gets a style-specific dependency warning message.
499+
*
500+
* @since 6.9.1
501+
*
502+
* @param string $handle Style handle with missing dependencies.
503+
* @param string[] $missing_dependency_handles Missing dependency handles.
504+
* @return string Formatted, localized warning message.
505+
*/
506+
protected function get_dependency_warning_message( $handle, $missing_dependency_handles ) {
507+
return sprintf(
508+
/* translators: 1: Style handle, 2: List of missing dependency handles. */
509+
__( 'The style with the handle "%1$s" was enqueued with dependencies that are not registered: %2$s.' ),
510+
$handle,
511+
implode( wp_get_list_item_separator(), $missing_dependency_handles )
512+
);
513+
}
496514
}

tests/phpunit/tests/dependencies/scripts.php

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4132,4 +4132,33 @@ private function normalize_markup_for_snapshot( string $markup ): string {
41324132
}
41334133
return $processor->get_updated_html();
41344134
}
4135+
4136+
/**
4137+
* Tests that WP_Scripts emits a _doing_it_wrong() notice for missing dependencies.
4138+
*
4139+
* @ticket 64229
4140+
* @covers WP_Dependencies::all_deps
4141+
*/
4142+
public function test_wp_scripts_doing_it_wrong_for_missing_dependencies() {
4143+
$expected_incorrect_usage = 'WP_Scripts::add';
4144+
$this->setExpectedIncorrectUsage( $expected_incorrect_usage );
4145+
4146+
wp_register_script( 'registered-dep', '/registered-dep.js' );
4147+
wp_enqueue_script( 'main', '/main.js', array( 'registered-dep', 'missing-dep' ) );
4148+
4149+
$markup = get_echo( 'wp_print_scripts' );
4150+
$this->assertStringNotContainsString( 'main.js', $markup, 'Expected script to be absent.' );
4151+
4152+
$this->assertArrayHasKey(
4153+
$expected_incorrect_usage,
4154+
$this->caught_doing_it_wrong,
4155+
"Expected $expected_incorrect_usage to trigger a _doing_it_wrong() notice for missing dependency."
4156+
);
4157+
4158+
$this->assertStringContainsString(
4159+
'The script with the handle "main" was enqueued with dependencies that are not registered: missing-dep',
4160+
$this->caught_doing_it_wrong[ $expected_incorrect_usage ],
4161+
'Expected _doing_it_wrong() notice to indicate missing dependencies for enqueued script.'
4162+
);
4163+
}
41354164
}

tests/phpunit/tests/dependencies/styles.php

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -815,4 +815,36 @@ public function test_source_url_with_concat() {
815815

816816
$this->assertEqualHTML( $expected, $printed );
817817
}
818+
819+
/**
820+
* Tests that WP_Styles emits a _doing_it_wrong() notice for missing dependencies.
821+
*
822+
* @ticket 64229
823+
* @covers WP_Dependencies::all_deps
824+
*/
825+
public function test_wp_style_doing_it_wrong_for_missing_dependencies() {
826+
$expected_incorrect_usage = 'WP_Styles::add';
827+
$this->setExpectedIncorrectUsage( $expected_incorrect_usage );
828+
829+
wp_enqueue_style(
830+
'main-style',
831+
'/main-style.css',
832+
array( 'missing-style-dep' )
833+
);
834+
835+
$markup = get_echo( 'wp_print_styles' );
836+
$this->assertStringNotContainsString( 'main-style.css', $markup, 'Expected style to be absent.' );
837+
838+
$this->assertArrayHasKey(
839+
$expected_incorrect_usage,
840+
$this->caught_doing_it_wrong,
841+
"Expected $expected_incorrect_usage to trigger a _doing_it_wrong() notice for missing dependency."
842+
);
843+
844+
$this->assertStringContainsString(
845+
'The style with the handle "main-style" was enqueued with dependencies that are not registered: missing-style-dep',
846+
$this->caught_doing_it_wrong[ $expected_incorrect_usage ],
847+
'Expected _doing_it_wrong() notice to indicate missing dependencies for enqueued styles.'
848+
);
849+
}
818850
}

tests/phpunit/tests/script-modules/wpScriptModules.php

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2106,7 +2106,7 @@ public function test_script_module_printing_and_dependency_ordering( bool $use_g
21062106
"Snapshot:\n" . var_export( $actual, true )
21072107
);
21082108

2109-
$deregister( array( 'b', 'c ' ) );
2109+
$deregister( array( 'b', 'c' ) );
21102110

21112111
// Test that registered dependency in footer doesn't place dependant in footer.
21122112
$register( 'd', '/d.js', array(), '1.0.0', array( 'in_footer' => true ) );
@@ -2355,4 +2355,32 @@ public function test_static_import_dependency_with_dynamic_imports_depending_on_
23552355
'Expected script modules to match.'
23562356
);
23572357
}
2358+
2359+
/**
2360+
* Tests that a missing script module dependency triggers a _doing_it_wrong() notice.
2361+
*
2362+
* @ticket 64229
2363+
* @covers WP_Script_Modules::sort_item_dependencies
2364+
*/
2365+
public function test_missing_script_module_dependency_triggers_incorrect_usage() {
2366+
$expected_incorrect_usage = 'WP_Script_Modules::register';
2367+
$this->setExpectedIncorrectUsage( $expected_incorrect_usage );
2368+
2369+
$this->script_modules->enqueue( 'main-module', '/main-module.js', array( 'missing-mod-dep' ) );
2370+
2371+
$markup = get_echo( array( $this->script_modules, 'print_enqueued_script_modules' ) );
2372+
$this->assertStringNotContainsString( 'main-module.js', $markup, 'Expected script module to be absent.' );
2373+
2374+
$this->assertArrayHasKey(
2375+
$expected_incorrect_usage,
2376+
$this->caught_doing_it_wrong,
2377+
'Expected WP_Script_Modules::register to be reported via doing_it_wrong().'
2378+
);
2379+
2380+
// Assert the message mentions the missing dependency handle.
2381+
$this->assertStringContainsString(
2382+
'The script module with the ID "main-module" was enqueued with dependencies that are not registered: missing-mod-dep',
2383+
$this->caught_doing_it_wrong[ $expected_incorrect_usage ]
2384+
);
2385+
}
23582386
}

0 commit comments

Comments
 (0)