WordPress.org

Make WordPress Core

Opened 2 years ago

Last modified 8 days ago

#25247 reviewing defect (bug)

WP_Dependencies unsets a to do item when it isn't loaded

Reported by: markoheijnen Owned by: chriscct7
Milestone: Future Release Priority: normal
Severity: normal Version: 3.6
Component: Script Loader Keywords: has-patch dev-feedback needs-testing has-unit-tests
Focuses: Cc:

Description

Currently it unsets $this->to_do no matter if do_item() return true or false. For example If you move jquery to the footer it will not load jquery at all. since it thinks jquery-core is loaded.

add_action( 'wp_default_scripts', 'move_jquery_to_footer_and_not_load_migrate' );
public function move_jquery_to_footer_and_not_load_migrate( &$scripts ) {
	if( ! is_admin() ) {
		$scripts->registered['jquery']->deps  = array( 'jquery-core' );
		$scripts->add_data( 'jquery', 'group', 1 );
		$scripts->add_data( 'jquery-core', 'group', 1 );
	}
}

Attachments (11)

#25247_bugfix.diff (984 bytes) - added by nmarks 17 months ago.
Patch for #25247
#25247_bugfix_v2.diff (1.1 KB) - added by nmarks 15 months ago.
Revised patch for #25247
25247-unit-test.diff (1.1 KB) - added by nmarks 14 months ago.
Unit test for ticket #25247
25247_dependencies.diff (1.4 KB) - added by gitlost 14 months ago.
Proposed patch.
25247_tests.diff (3.4 KB) - added by gitlost 14 months ago.
Unit tests for patch.
25247_scripts.diff (2.2 KB) - added by gitlost 14 months ago.
Optional cleanup patch to WP_Scripts.
25247_tests2.diff (3.4 KB) - added by gitlost 12 months ago.
Refresh on unit tests to patch to latest version.
25247_scripts2.diff (2.2 KB) - added by gitlost 5 months ago.
Refresh for 4.4.
25247_tests3.diff (3.5 KB) - added by gitlost 5 months ago.
Refresh for 4.4.
25247_scripts3.diff (2.3 KB) - added by gitlost 3 weeks ago.
Refresh for 4.5.
25247_scripts4.diff (2.3 KB) - added by gitlost 8 days ago.
Updated @since to 4.5 on overridden add().

Download all attachments as: .zip

Change History (32)

#1 follow-up: @nacin
2 years ago

  • Keywords needs-unit-tests added

Could you submit a unit test patch demonstrating the issue?

#2 @ocean90
2 years ago

  • Cc ocean90 added

#3 @ocean90
2 years ago

  • Cc azaozz added
  • Keywords needs-patch added
  • Milestone changed from Awaiting Review to Future Release
  • Version set to 3.6

This script has worked until 3.6:

/**
 * Prints jQuery in footer on front-end.
 */
function ds_print_jquery_in_footer( &$scripts) {
	if ( ! is_admin() )
		$scripts->add_data( 'jquery', 'group', 1 );
}
add_action( 'wp_default_scripts', 'ds_print_jquery_in_footer' );

With 3.6 I would set the group arg for the dependencies to 1 too, but that doesn't work.

#4 @nacin
2 years ago

  • Component changed from General to Script Loader

@nmarks
17 months ago

Patch for #25247

#5 @nmarks
17 months ago

  • Keywords has-patch added; needs-patch removed

I added a patch for this. I found that the function was adding jquery to the 'done' array as it doesn't have an src set (src is set on jquery-core).

What's currently happening is when it is doing the footer items, jquery is already in the done array and it makes no attempt to load it.

I've added a patch that checks the current group and set group (if isset) on the item when adding to the done array in the !(has-src) conditional.

For this to work, just set the jQuery and its dependencies' group to 1 with the wp_default_scripts action.

Last edited 17 months ago by nmarks (previous) (diff)

#6 @nmarks
17 months ago

  • Keywords dev-feedback needs-testing added

#7 @pauldewouters
15 months ago

Tested the patch #25247_bugfix.diff on WordPress 4.0 on a site with a variety of javascript files with dependencies. jQuery is loaded in the footer as expected, in first place so all depending scripts are loaded after it, using Marko's function.
Would be great to get this merged in, as scripts should really load in the footer

@nmarks
15 months ago

Revised patch for #25247

#8 @nmarks
15 months ago

Hey fellas,

I submitted a revised patch that makes the conditional more readable by expressing some of the conditions as variables and ensured that spacing etc follows the WordPress PHP coding standards.

Last edited 15 months ago by nmarks (previous) (diff)

#9 in reply to: ↑ 1 @nmarks
15 months ago

@nacin would you like this to be a test for WP_Scripts or WP_Dependencies?

Edit: I need to use a method from WP_Scripts to test this properly, but all the code changes are in the parent class WP_Dependencies. Should I put the test in Tests_Dependencies_Scripts or Tests_Dependencies?

Last edited 15 months ago by nmarks (previous) (diff)

@nmarks
14 months ago

Unit test for ticket #25247

#10 @nmarks
14 months ago

  • Keywords needs-unit-tests removed

Ok.

Since it relies on the WP_Scripts version of the do_item method, I put the unit test in tests/dependencies/scripts.php.

I also verified that it fails without my patch and passes with my patch.

Please Note: If you are testing, I have put the unit test and the core fix in 2 separate patches so you'll need both:

[Core Patch](https://core.trac.wordpress.org/attachment/ticket/25247/%2325247_bugfix_v2.diff)
[Unit Test](https://core.trac.wordpress.org/attachment/ticket/25247/25247-unit-test.diff)

Last edited 14 months ago by nmarks (previous) (diff)

#11 @gitlost
14 months ago

I think the no src issue is a bit of a red herring. The real problem here - as stated by the OP markoheijnen - is that the do_items() loop is removing an item from the to_do list whether or not it succeeded. An issue reported by helgatheviking on WP stackexchange (Loading a script with a dependency, is unloading another script's dependency is another symptom of the problem, which can be seen simply with this setup:

		$scripts = new WP_Scripts;
		$scripts->add( 'jquery-ui-datepicker', 'one', array(), 'v1', 1 ); 
		$scripts->add( 'wc-admin-meta-boxes', 'two', array( 'jquery-ui-datepicker' ) ); 
		$scripts->add( 'My_Plugin_Metabox', 'three', array( 'wc-admin-meta-boxes' ), 'v1', 1 ); 
		$scripts->enqueue( array( 'My_Plugin_Metabox' ) );
		$scripts->do_items( false, 0 );
		$scripts->do_items( false, 1 );

Note the mismatch in groups between 'wc-admin-meta-boxes' and 'jquery-ui-datepicker', If you run this, 'jquery-ui-datepicker' won't be outputted, it's just appended to the $in_footer array in WP_Scripts and left there, and since the array is no longer used in do_footer_items(), it gets lost.

Basically it seems that when the code was changed to do two passes of do_items() instead of one, the loop wasn't updated. The fix is simple, only remove the item from the to_do list when it's successfully added (or when the src is null).

The helgatheviking scenario also shows up another issue, in that although with the loop fix 'jquery-ui-datepicker' will get outputted, it will output in the footer, after the dependent 'wc-admin-meta-boxes' which gets outputted in the head. To fix this it would seem best to force any dependencies to the lowest common group, which can I think be achieved by setting the class $this->group when recursing in set_group().

I'll attach a patch and unit tests with these changes.

Last edited 14 months ago by gitlost (previous) (diff)

@gitlost
14 months ago

Proposed patch.

@gitlost
14 months ago

Unit tests for patch.

#12 @gitlost
14 months ago

Also the following is an optional patch to WP_Scripts, removing references to the vestigal $in_footer array, and also replacing the use of item $args === 1 with add_data('group', 1) (by overriding the add() function) - having the group state in two separate variables is not the best idea and no doubt legacy again...

@gitlost
14 months ago

Optional cleanup patch to WP_Scripts.

#13 @nmarks
14 months ago

Tested gitlost's patch, looks good.

@gitlost
12 months ago

Refresh on unit tests to patch to latest version.

#14 @gitlost
12 months ago

Would like to see this bug get more attention, it's 18 months old and in a fundamental part of WP which shouldn't have bugs (and where some non-bug changes seem to be getting more consideration).

@gitlost
5 months ago

Refresh for 4.4.

@gitlost
5 months ago

Refresh for 4.4.

#15 @gitlost
5 months ago

Refreshes for gardening drive - 25247_dependencies.diff still good.

#16 @OddOneOut
4 months ago

Just got hit by this as well, using a clean installation of WP 4.3. Hopefully the above patches get merged soon.

@gitlost
3 weeks ago

Refresh for 4.5.

#17 @gitlost
3 weeks ago

Refresh for 4.5 Bug Scrub. 25247_dependencies.diff and 25247_tests3.diff still good.

This ticket was mentioned in Slack in #core by chriscct7. View the logs.


8 days ago

#19 @chriscct7
8 days ago

  • Keywords has-unit-tests added

Unit tests are still good to go.

#20 @chriscct7
8 days ago

  • Owner set to chriscct7
  • Status changed from new to reviewing

@gitlost
8 days ago

Updated @since to 4.5 on overridden add().

#21 @gitlost
8 days ago

Per https://wordpress.slack.com/archives/core/p1454692115001728, set since to 4.5 on overridden add() in class.wp-scripts.php.

Note: See TracTickets for help on using tickets.