<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[56033] trunk: Script Loader: Add support for HTML 5 "async" and "defer" attributes.</title>
</head>
<body>
<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; }
#msg dl a { font-weight: bold}
#msg dl a:link { color:#fc3; }
#msg dl a:active { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { white-space: pre-line; overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta" style="font-size: 105%">
<dt style="float: left; width: 6em; font-weight: bold">Revision</dt> <dd><a style="font-weight: bold" href="https://core.trac.wordpress.org/changeset/56033">56033</a><script type="application/ld+json">{"@context":"http://schema.org","@type":"EmailMessage","description":"Review this Commit","action":{"@type":"ViewAction","url":"https://core.trac.wordpress.org/changeset/56033","name":"Review Commit"}}</script></dd>
<dt style="float: left; width: 6em; font-weight: bold">Author</dt> <dd>joemcgill</dd>
<dt style="float: left; width: 6em; font-weight: bold">Date</dt> <dd>2023-06-26 13:40:31 +0000 (Mon, 26 Jun 2023)</dd>
</dl>
<pre style='padding-left: 1em; margin: 2em 0; border-left: 2px solid #ccc; line-height: 1.25; font-size: 105%; font-family: sans-serif'>Script Loader: Add support for HTML 5 "async" and "defer" attributes.
This allows developers to register scripts with an intended loading strategy by changing the `$in_footer` parameter of `wp_register_script` and `wp_enqueue_script` to an array that accepts both an `in_footer` and `strategy` argument. If present, the loading strategy attribute will be added to the script tag when that script is printed to the page as long as it is not a dependency of any blocking scripts, including any inline scripts attached to the script or any of its dependents.
Props 10upsimon, thekt12, westonruter, costdev, flixos90, spacedmonkey, adamsilverstein, azaozz, mukeshpanchal27, mor10, scep, wpnook, vanaf1979, Otto42.
Fixes <a href="https://core.trac.wordpress.org/ticket/12009">#12009</a>.</pre>
<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkjshintrc">trunk/.jshintrc</a></li>
<li><a href="#trunkphpcsxmldist">trunk/phpcs.xml.dist</a></li>
<li><a href="#trunksrcwpincludesclasswpscriptsphp">trunk/src/wp-includes/class-wp-scripts.php</a></li>
<li><a href="#trunksrcwpincludesfunctionswpscriptsphp">trunk/src/wp-includes/functions.wp-scripts.php</a></li>
<li><a href="#trunktestsphpunittestsdependenciesscriptsphp">trunk/tests/phpunit/tests/dependencies/scripts.php</a></li>
</ul>
</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkjshintrc"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/.jshintrc</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/.jshintrc 2023-06-26 10:42:54 UTC (rev 56032)
+++ trunk/.jshintrc 2023-06-26 13:40:31 UTC (rev 56033)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -19,11 +19,13 @@
</span><span class="cx" style="display: block; padding: 0 10px"> "globals": {
</span><span class="cx" style="display: block; padding: 0 10px"> "_": false,
</span><span class="cx" style="display: block; padding: 0 10px"> "Backbone": false,
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ "console": false,
</ins><span class="cx" style="display: block; padding: 0 10px"> "jQuery": false,
</span><span class="cx" style="display: block; padding: 0 10px"> "JSON": false,
</span><span class="cx" style="display: block; padding: 0 10px"> "wp": false,
</span><span class="cx" style="display: block; padding: 0 10px"> "export": false,
</span><span class="cx" style="display: block; padding: 0 10px"> "module": false,
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- "require": false
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ "require": false,
+ "Set": false
</ins><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span></span></pre></div>
<a id="trunkphpcsxmldist"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/phpcs.xml.dist</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/phpcs.xml.dist 2023-06-26 10:42:54 UTC (rev 56032)
+++ trunk/phpcs.xml.dist 2023-06-26 13:40:31 UTC (rev 56033)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -68,7 +68,9 @@
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> <!-- From DOMDocument. -->
</span><span class="cx" style="display: block; padding: 0 10px"> <element value="childNodes"/>
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ <element value="firstChild"/>
</ins><span class="cx" style="display: block; padding: 0 10px"> <element value="formatOutput"/>
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ <element value="lastChild"/>
</ins><span class="cx" style="display: block; padding: 0 10px"> <element value="nodeName"/>
</span><span class="cx" style="display: block; padding: 0 10px"> <element value="nodeType"/>
</span><span class="cx" style="display: block; padding: 0 10px"> <element value="parentNode"/>
</span></span></pre></div>
<a id="trunksrcwpincludesclasswpscriptsphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-includes/class-wp-scripts.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-includes/class-wp-scripts.php 2023-06-26 10:42:54 UTC (rev 56032)
+++ trunk/src/wp-includes/class-wp-scripts.php 2023-06-26 13:40:31 UTC (rev 56033)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -134,6 +134,24 @@
</span><span class="cx" style="display: block; padding: 0 10px"> private $type_attr = '';
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Holds a mapping of dependents (as handles) for a given script handle.
+ * Used to optimize recursive dependency tree checks.
+ *
+ * @since 6.3.0
+ * @var array
+ */
+ private $dependents_map = array();
+
+ /**
+ * Holds a reference to the delayed (non-blocking) script loading strategies.
+ * Used by methods that validate loading strategies.
+ *
+ * @since 6.3.0
+ * @var string[]
+ */
+ private $delayed_strategies = array( 'defer', 'async' );
+
+ /**
</ins><span class="cx" style="display: block; padding: 0 10px"> * Constructor.
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * @since 2.6.0
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -284,29 +302,27 @@
</span><span class="cx" style="display: block; padding: 0 10px"> $ver = $ver ? $ver . '&' . $this->args[ $handle ] : $this->args[ $handle ];
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $src = $obj->src;
- $cond_before = '';
- $cond_after = '';
- $conditional = isset( $obj->extra['conditional'] ) ? $obj->extra['conditional'] : '';
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $src = $obj->src;
+ $strategy = $this->get_eligible_loading_strategy( $handle );
+ $intended_strategy = (string) $this->get_data( $handle, 'strategy' );
+ $cond_before = '';
+ $cond_after = '';
+ $conditional = isset( $obj->extra['conditional'] ) ? $obj->extra['conditional'] : '';
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if ( ! $this->is_delayed_strategy( $intended_strategy ) ) {
+ $intended_strategy = '';
+ }
+
</ins><span class="cx" style="display: block; padding: 0 10px"> if ( $conditional ) {
</span><span class="cx" style="display: block; padding: 0 10px"> $cond_before = "<!--[if {$conditional}]>\n";
</span><span class="cx" style="display: block; padding: 0 10px"> $cond_after = "<![endif]-->\n";
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $before_handle = $this->print_inline_script( $handle, 'before', false );
- $after_handle = $this->print_inline_script( $handle, 'after', false );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $before_script = $this->get_inline_script_tag( $handle, 'before' );
+ $after_script = $this->get_inline_script_tag( $handle, 'after' );
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if ( $before_handle ) {
- $before_handle = sprintf( "<script%s id='%s-js-before'>\n%s\n</script>\n", $this->type_attr, esc_attr( $handle ), $before_handle );
- }
-
- if ( $after_handle ) {
- $after_handle = sprintf( "<script%s id='%s-js-after'>\n%s\n</script>\n", $this->type_attr, esc_attr( $handle ), $after_handle );
- }
-
- if ( $before_handle || $after_handle ) {
- $inline_script_tag = $cond_before . $before_handle . $after_handle . $cond_after;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if ( $before_script || $after_script ) {
+ $inline_script_tag = $cond_before . $before_script . $after_script . $cond_after;
</ins><span class="cx" style="display: block; padding: 0 10px"> } else {
</span><span class="cx" style="display: block; padding: 0 10px"> $inline_script_tag = '';
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -333,7 +349,10 @@
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><span class="cx" style="display: block; padding: 0 10px"> $srce = apply_filters( 'script_loader_src', $src, $handle );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if ( $this->in_default_dir( $srce ) && ( $before_handle || $after_handle || $translations_stop_concat ) ) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if (
+ $this->in_default_dir( $srce )
+ && ( $before_script || $after_script || $translations_stop_concat || $this->is_delayed_strategy( $strategy ) )
+ ) {
</ins><span class="cx" style="display: block; padding: 0 10px"> $this->do_concat = false;
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> // Have to print the so-far concatenated scripts right away to maintain the right order.
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -390,9 +409,16 @@
</span><span class="cx" style="display: block; padding: 0 10px"> return true;
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $tag = $translations . $cond_before . $before_handle;
- $tag .= sprintf( "<script%s src='%s' id='%s-js'></script>\n", $this->type_attr, $src, esc_attr( $handle ) );
- $tag .= $after_handle . $cond_after;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $tag = $translations . $cond_before . $before_script;
+ $tag .= sprintf(
+ "<script%s src='%s' id='%s-js'%s%s></script>\n",
+ $this->type_attr,
+ $src, // Value is escaped above.
+ esc_attr( $handle ),
+ $strategy ? " {$strategy}" : '',
+ $intended_strategy ? " data-wp-strategy='{$intended_strategy}'" : ''
+ );
+ $tag .= $after_script . $cond_after;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="cx" style="display: block; padding: 0 10px"> * Filters the HTML script tag of an enqueued script.
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -445,32 +471,100 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * Prints inline scripts registered for a specific handle.
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * @since 4.5.0
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @deprecated 6.3.0 Use methods get_inline_script_tag() or get_inline_script_data() instead.
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * @param string $handle Name of the script to add the inline script to.
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @param string $handle Name of the script to print inline scripts for.
</ins><span class="cx" style="display: block; padding: 0 10px"> * Must be lowercase.
</span><span class="cx" style="display: block; padding: 0 10px"> * @param string $position Optional. Whether to add the inline script
</span><span class="cx" style="display: block; padding: 0 10px"> * before the handle or after. Default 'after'.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * @param bool $display Optional. Whether to print the script
- * instead of just returning it. Default true.
- * @return string|false Script on success, false otherwise.
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @param bool $display Optional. Whether to print the script tag
+ * instead of just returning the script data. Default true.
+ * @return string|false Script data on success, false otherwise.
</ins><span class="cx" style="display: block; padding: 0 10px"> */
</span><span class="cx" style="display: block; padding: 0 10px"> public function print_inline_script( $handle, $position = 'after', $display = true ) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $output = $this->get_data( $handle, $position );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ _deprecated_function( __METHOD__, '6.3.0', 'WP_Scripts::get_inline_script_data() or WP_Scripts::get_inline_script_tag()' );
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $output = $this->get_inline_script_data( $handle, $position );
</ins><span class="cx" style="display: block; padding: 0 10px"> if ( empty( $output ) ) {
</span><span class="cx" style="display: block; padding: 0 10px"> return false;
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $output = trim( implode( "\n", $output ), "\n" );
-
</del><span class="cx" style="display: block; padding: 0 10px"> if ( $display ) {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- printf( "<script%s id='%s-js-%s'>\n%s\n</script>\n", $this->type_attr, esc_attr( $handle ), esc_attr( $position ), $output );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ echo $this->get_inline_script_tag( $handle, $position );
</ins><span class="cx" style="display: block; padding: 0 10px"> }
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-
</del><span class="cx" style="display: block; padding: 0 10px"> return $output;
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Gets data for inline scripts registered for a specific handle.
+ *
+ * @since 6.3.0
+ *
+ * @param string $handle Name of the script to get data for.
+ * Must be lowercase.
+ * @param string $position Optional. Whether to add the inline script
+ * before the handle or after. Default 'after'.
+ * @return string Inline script, which may be empty string.
+ */
+ public function get_inline_script_data( $handle, $position = 'after' ) {
+ $data = $this->get_data( $handle, $position );
+ if ( empty( $data ) || ! is_array( $data ) ) {
+ return '';
+ }
+
+ return trim( implode( "\n", $data ), "\n" );
+ }
+
+ /**
+ * Gets unaliased dependencies.
+ *
+ * An alias is a dependency whose src is false. It is used as a way to bundle multiple dependencies in a single
+ * handle. This in effect flattens an alias dependency tree.
+ *
+ * @since 6.3.0
+ *
+ * @param string[] $deps Dependency handles.
+ * @return string[] Unaliased handles.
+ */
+ private function get_unaliased_deps( array $deps ) {
+ $flattened = array();
+ foreach ( $deps as $dep ) {
+ if ( ! isset( $this->registered[ $dep ] ) ) {
+ continue;
+ }
+
+ if ( $this->registered[ $dep ]->src ) {
+ $flattened[] = $dep;
+ } elseif ( $this->registered[ $dep ]->deps ) {
+ array_push( $flattened, ...$this->get_unaliased_deps( $this->registered[ $dep ]->deps ) );
+ }
+ }
+ return $flattened;
+ }
+
+ /**
+ * Gets tags for inline scripts registered for a specific handle.
+ *
+ * @since 6.3.0
+ *
+ * @param string $handle Name of the script to get associated inline script tag for.
+ * Must be lowercase.
+ * @param string $position Optional. Whether to get tag for inline
+ * scripts in the before or after position. Default 'after'.
+ * @return string Inline script, which may be empty string.
+ */
+ public function get_inline_script_tag( $handle, $position = 'after' ) {
+ $js = $this->get_inline_script_data( $handle, $position );
+ if ( empty( $js ) ) {
+ return '';
+ }
+
+ $id = "{$handle}-js-{$position}";
+
+ return wp_get_inline_script_tag( $js, compact( 'id' ) );
+ }
+
+ /**
</ins><span class="cx" style="display: block; padding: 0 10px"> * Localizes a script, only if the script has already been added.
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * @since 2.1.0
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -715,6 +809,199 @@
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * This overrides the add_data method from WP_Dependencies, to support normalizing of $args.
+ *
+ * @since 6.3.0
+ *
+ * @param string $handle Name of the item. Should be unique.
+ * @param string $key The data key.
+ * @param mixed $value The data value.
+ * @return bool True on success, false on failure.
+ */
+ public function add_data( $handle, $key, $value ) {
+ if ( ! isset( $this->registered[ $handle ] ) ) {
+ return false;
+ }
+
+ if ( 'strategy' === $key ) {
+ if ( ! empty( $value ) && ! $this->is_delayed_strategy( $value ) ) {
+ _doing_it_wrong(
+ __METHOD__,
+ sprintf(
+ /* translators: 1: $strategy, 2: $handle */
+ __( 'Invalid strategy `%1$s` defined for `%2$s` during script registration.' ),
+ $value,
+ $handle
+ ),
+ '6.3.0'
+ );
+ return false;
+ } elseif ( ! $this->registered[ $handle ]->src && $this->is_delayed_strategy( $value ) ) {
+ _doing_it_wrong(
+ __METHOD__,
+ sprintf(
+ /* translators: 1: $strategy, 2: $handle */
+ __( 'Cannot supply a strategy `%1$s` for script `%2$s` because it is an alias (it lacks a `src` value).' ),
+ $value,
+ $handle
+ ),
+ '6.3.0'
+ );
+ return false;
+ }
+ }
+ return parent::add_data( $handle, $key, $value );
+ }
+
+ /**
+ * Gets all dependents of a script.
+ *
+ * @since 6.3.0
+ *
+ * @param string $handle The script handle.
+ * @return string[] Script handles.
+ */
+ private function get_dependents( $handle ) {
+ // Check if dependents map for the handle in question is present. If so, use it.
+ if ( isset( $this->dependents_map[ $handle ] ) ) {
+ return $this->dependents_map[ $handle ];
+ }
+
+ $dependents = array();
+
+ // Iterate over all registered scripts, finding dependents of the script passed to this method.
+ foreach ( $this->registered as $registered_handle => $args ) {
+ if ( in_array( $handle, $args->deps, true ) ) {
+ $dependents[] = $registered_handle;
+ }
+ }
+
+ // Add the handles dependents to the map to ease future lookups.
+ $this->dependents_map[ $handle ] = $dependents;
+
+ return $dependents;
+ }
+
+ /**
+ * Checks if the strategy passed is a valid delayed (non-blocking) strategy.
+ *
+ * @since 6.3.0
+ *
+ * @param string $strategy The strategy to check.
+ * @return bool True if $strategy is one of the delayed strategies, otherwise false.
+ */
+ private function is_delayed_strategy( $strategy ) {
+ return in_array(
+ $strategy,
+ $this->delayed_strategies,
+ true
+ );
+ }
+
+ /**
+ * Gets the best eligible loading strategy for a script.
+ *
+ * @since 6.3.0
+ *
+ * @param string $handle The script handle.
+ * @return string The best eligible loading strategy.
+ */
+ private function get_eligible_loading_strategy( $handle ) {
+ $eligible = $this->filter_eligible_strategies( $handle );
+
+ // Bail early once we know the eligible strategy is blocking.
+ if ( empty( $eligible ) ) {
+ return '';
+ }
+
+ return in_array( 'async', $eligible, true ) ? 'async' : 'defer';
+ }
+
+ /**
+ * Filter the list of eligible loading strategies for a script.
+ *
+ * @since 6.3.0
+ *
+ * @param string $handle The script handle.
+ * @param string[]|null $eligible Optional. The list of strategies to filter. Default null.
+ * @param array<string, true> $checked Optional. An array of already checked script handles, used to avoid recursive loops.
+ * @return string[] A list of eligible loading strategies that could be used.
+ */
+ private function filter_eligible_strategies( $handle, $eligible = null, $checked = array() ) {
+ // If no strategies are being passed, all strategies are eligible.
+ if ( null === $eligible ) {
+ $eligible = $this->delayed_strategies;
+ }
+
+ // If this handle was already checked, return early.
+ if ( isset( $checked[ $handle ] ) ) {
+ return $eligible;
+ }
+
+ // Mark this handle as checked.
+ $checked[ $handle ] = true;
+
+ // If this handle isn't registered, don't filter anything and return.
+ if ( ! isset( $this->registered[ $handle ] ) ) {
+ return $eligible;
+ }
+
+ // If the handle is not enqueued, don't filter anything and return.
+ if ( ! $this->query( $handle, 'enqueued' ) ) {
+ return $eligible;
+ }
+
+ $is_alias = (bool) ! $this->registered[ $handle ]->src;
+ $intended_strategy = $this->get_data( $handle, 'strategy' );
+
+ // For non-alias handles, an empty intended strategy filters all strategies.
+ if ( ! $is_alias && empty( $intended_strategy ) ) {
+ return array();
+ }
+
+ // Handles with inline scripts attached in the 'after' position cannot be delayed.
+ if ( $this->has_inline_script( $handle, 'after' ) ) {
+ return array();
+ }
+
+ // If the intended strategy is 'defer', filter out 'async'.
+ if ( 'defer' === $intended_strategy ) {
+ $eligible = array( 'defer' );
+ }
+
+ $dependents = $this->get_dependents( $handle );
+
+ // Recursively filter eligible strategies for dependents.
+ foreach ( $dependents as $dependent ) {
+ // Bail early once we know the eligible strategy is blocking.
+ if ( empty( $eligible ) ) {
+ return array();
+ }
+
+ $eligible = $this->filter_eligible_strategies( $dependent, $eligible, $checked );
+ }
+
+ return $eligible;
+ }
+
+ /**
+ * Gets data for inline scripts registered for a specific handle.
+ *
+ * @since 6.3.0
+ *
+ * @param string $handle Name of the script to get data for. Must be lowercase.
+ * @param string $position The position of the inline script.
+ * @return bool Whether the handle has an inline script (either before or after).
+ */
+ private function has_inline_script( $handle, $position = null ) {
+ if ( $position && in_array( $position, array( 'before', 'after' ), true ) ) {
+ return (bool) $this->get_data( $handle, $position );
+ }
+
+ return (bool) ( $this->get_data( $handle, 'before' ) || $this->get_data( $handle, 'after' ) );
+ }
+
+ /**
</ins><span class="cx" style="display: block; padding: 0 10px"> * Resets class properties.
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * @since 2.8.0
</span></span></pre></div>
<a id="trunksrcwpincludesfunctionswpscriptsphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/src/wp-includes/functions.wp-scripts.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/src/wp-includes/functions.wp-scripts.php 2023-06-26 10:42:54 UTC (rev 56032)
+++ trunk/src/wp-includes/functions.wp-scripts.php 2023-06-26 13:40:31 UTC (rev 56033)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -157,6 +157,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * @since 2.1.0
</span><span class="cx" style="display: block; padding: 0 10px"> * @since 4.3.0 A return value was added.
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @since 6.3.0 The $in_footer parameter of type boolean was overloaded to be an $args parameter of type array.
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * @param string $handle Name of the script. Should be unique.
</span><span class="cx" style="display: block; padding: 0 10px"> * @param string|false $src Full URL of the script, or path of the script relative to the WordPress root directory.
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -166,20 +167,32 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * as a query string for cache busting purposes. If version is set to false, a version
</span><span class="cx" style="display: block; padding: 0 10px"> * number is automatically added equal to current installed WordPress version.
</span><span class="cx" style="display: block; padding: 0 10px"> * If set to null, no version is added.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * @param bool $in_footer Optional. Whether to enqueue the script before `</body>` instead of in the `<head>`.
- * Default 'false'.
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @param array|bool $args {
+ * Optional. An array of additional script loading strategies. Default empty array.
+ * Otherwise, it may be a boolean in which case it determines whether the script is printed in the footer. Default false.
+ *
+ * @type string $strategy Optional. If provided, may be either 'defer' or 'async'.
+ * @type bool $in_footer Optional. Whether to print the script in the footer. Default 'false'.
+ * }
</ins><span class="cx" style="display: block; padding: 0 10px"> * @return bool Whether the script has been registered. True on success, false on failure.
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-function wp_register_script( $handle, $src, $deps = array(), $ver = false, $in_footer = false ) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+function wp_register_script( $handle, $src, $deps = array(), $ver = false, $args = array() ) {
+ if ( ! is_array( $args ) ) {
+ $args = array(
+ 'in_footer' => (bool) $args,
+ );
+ }
</ins><span class="cx" style="display: block; padding: 0 10px"> _wp_scripts_maybe_doing_it_wrong( __FUNCTION__, $handle );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> $wp_scripts = wp_scripts();
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> $registered = $wp_scripts->add( $handle, $src, $deps, $ver );
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if ( $in_footer ) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if ( ! empty( $args['in_footer'] ) ) {
</ins><span class="cx" style="display: block; padding: 0 10px"> $wp_scripts->add_data( $handle, 'group', 1 );
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if ( ! empty( $args['strategy'] ) ) {
+ $wp_scripts->add_data( $handle, 'strategy', $args['strategy'] );
+ }
</ins><span class="cx" style="display: block; padding: 0 10px"> return $registered;
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -331,6 +344,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * @see WP_Dependencies::enqueue()
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * @since 2.1.0
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @since 6.3.0 The $in_footer parameter of type boolean was overloaded to be an $args parameter of type array.
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * @param string $handle Name of the script. Should be unique.
</span><span class="cx" style="display: block; padding: 0 10px"> * @param string $src Full URL of the script, or path of the script relative to the WordPress root directory.
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -340,24 +354,36 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * as a query string for cache busting purposes. If version is set to false, a version
</span><span class="cx" style="display: block; padding: 0 10px"> * number is automatically added equal to current installed WordPress version.
</span><span class="cx" style="display: block; padding: 0 10px"> * If set to null, no version is added.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * @param bool $in_footer Optional. Whether to enqueue the script before `</body>` instead of in the `<head>`.
- * Default 'false'.
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @param array|bool $args {
+ * Optional. An array of additional script loading strategies. Default empty array.
+ * Otherwise, it may be a boolean in which case it determines whether the script is printed in the footer. Default false.
+ *
+ * @type string $strategy Optional. If provided, may be either 'defer' or 'async'.
+ * @type bool $in_footer Optional. Whether to print the script in the footer. Default 'false'.
+ * }
</ins><span class="cx" style="display: block; padding: 0 10px"> */
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-function wp_enqueue_script( $handle, $src = '', $deps = array(), $ver = false, $in_footer = false ) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+function wp_enqueue_script( $handle, $src = '', $deps = array(), $ver = false, $args = array() ) {
</ins><span class="cx" style="display: block; padding: 0 10px"> _wp_scripts_maybe_doing_it_wrong( __FUNCTION__, $handle );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> $wp_scripts = wp_scripts();
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- if ( $src || $in_footer ) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if ( $src || ! empty( $args ) ) {
</ins><span class="cx" style="display: block; padding: 0 10px"> $_handle = explode( '?', $handle );
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if ( ! is_array( $args ) ) {
+ $args = array(
+ 'in_footer' => (bool) $args,
+ );
+ }
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> if ( $src ) {
</span><span class="cx" style="display: block; padding: 0 10px"> $wp_scripts->add( $_handle[0], $src, $deps, $ver );
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">-
- if ( $in_footer ) {
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if ( ! empty( $args['in_footer'] ) ) {
</ins><span class="cx" style="display: block; padding: 0 10px"> $wp_scripts->add_data( $_handle[0], 'group', 1 );
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ if ( ! empty( $args['strategy'] ) ) {
+ $wp_scripts->add_data( $_handle[0], 'strategy', $args['strategy'] );
+ }
</ins><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> $wp_scripts->enqueue( $handle );
</span></span></pre></div>
<a id="trunktestsphpunittestsdependenciesscriptsphp"></a>
<div class="modfile"><h4 style="background-color: #eee; color: inherit; margin: 1em 0; padding: 1.3em; font-size: 115%">Modified: trunk/tests/phpunit/tests/dependencies/scripts.php</h4>
<pre class="diff"><span>
<span class="info" style="display: block; padding: 0 10px; color: #888">--- trunk/tests/phpunit/tests/dependencies/scripts.php 2023-06-26 10:42:54 UTC (rev 56032)
+++ trunk/tests/phpunit/tests/dependencies/scripts.php 2023-06-26 13:40:31 UTC (rev 56033)
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -10,17 +10,35 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * @covers ::wp_set_script_translations
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><span class="cx" style="display: block; padding: 0 10px"> class Tests_Dependencies_Scripts extends WP_UnitTestCase {
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+
+ /**
+ * @var WP_Scripts
+ */
</ins><span class="cx" style="display: block; padding: 0 10px"> protected $old_wp_scripts;
</span><span class="cx" style="display: block; padding: 0 10px">
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * @var WP_Styles
+ */
+ protected $old_wp_styles;
+
</ins><span class="cx" style="display: block; padding: 0 10px"> protected $wp_scripts_print_translations_output;
</span><span class="cx" style="display: block; padding: 0 10px">
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ /**
+ * Stores a string reference to a default scripts directory name, utilised by certain tests.
+ *
+ * @var string
+ */
+ protected $default_scripts_dir = '/directory/';
+
</ins><span class="cx" style="display: block; padding: 0 10px"> public function set_up() {
</span><span class="cx" style="display: block; padding: 0 10px"> parent::set_up();
</span><span class="cx" style="display: block; padding: 0 10px"> $this->old_wp_scripts = isset( $GLOBALS['wp_scripts'] ) ? $GLOBALS['wp_scripts'] : null;
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $this->old_wp_styles = isset( $GLOBALS['wp_styles'] ) ? $GLOBALS['wp_styles'] : null;
</ins><span class="cx" style="display: block; padding: 0 10px"> remove_action( 'wp_default_scripts', 'wp_default_scripts' );
</span><span class="cx" style="display: block; padding: 0 10px"> remove_action( 'wp_default_scripts', 'wp_default_packages' );
</span><span class="cx" style="display: block; padding: 0 10px"> $GLOBALS['wp_scripts'] = new WP_Scripts();
</span><span class="cx" style="display: block; padding: 0 10px"> $GLOBALS['wp_scripts']->default_version = get_bloginfo( 'version' );
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $GLOBALS['wp_styles'] = new WP_Styles();
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> $this->wp_scripts_print_translations_output = <<<JS
</span><span class="cx" style="display: block; padding: 0 10px"> <script type='text/javascript' id='__HANDLE__-js-translations'>
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -36,6 +54,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> public function tear_down() {
</span><span class="cx" style="display: block; padding: 0 10px"> $GLOBALS['wp_scripts'] = $this->old_wp_scripts;
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $GLOBALS['wp_styles'] = $this->old_wp_styles;
</ins><span class="cx" style="display: block; padding: 0 10px"> add_action( 'wp_default_scripts', 'wp_default_scripts' );
</span><span class="cx" style="display: block; padding: 0 10px"> parent::tear_down();
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -46,14 +65,15 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * @ticket 11315
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><span class="cx" style="display: block; padding: 0 10px"> public function test_wp_enqueue_script() {
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ global $wp_version;
+
</ins><span class="cx" style="display: block; padding: 0 10px"> wp_enqueue_script( 'no-deps-no-version', 'example.com', array() );
</span><span class="cx" style="display: block; padding: 0 10px"> wp_enqueue_script( 'empty-deps-no-version', 'example.com' );
</span><span class="cx" style="display: block; padding: 0 10px"> wp_enqueue_script( 'empty-deps-version', 'example.com', array(), 1.2 );
</span><span class="cx" style="display: block; padding: 0 10px"> wp_enqueue_script( 'empty-deps-null-version', 'example.com', array(), null );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $ver = get_bloginfo( 'version' );
- $expected = "<script type='text/javascript' src='http://example.com?ver=$ver' id='no-deps-no-version-js'></script>\n";
- $expected .= "<script type='text/javascript' src='http://example.com?ver=$ver' id='empty-deps-no-version-js'></script>\n";
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $expected = "<script type='text/javascript' src='http://example.com?ver={$wp_version}' id='no-deps-no-version-js'></script>\n";
+ $expected .= "<script type='text/javascript' src='http://example.com?ver={$wp_version}' id='empty-deps-no-version-js'></script>\n";
</ins><span class="cx" style="display: block; padding: 0 10px"> $expected .= "<script type='text/javascript' src='http://example.com?ver=1.2' id='empty-deps-version-js'></script>\n";
</span><span class="cx" style="display: block; padding: 0 10px"> $expected .= "<script type='text/javascript' src='http://example.com' id='empty-deps-null-version-js'></script>\n";
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -64,9 +84,1334 @@
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Gets delayed strategies as a data provider.
+ *
+ * @return array[] Delayed strategies.
+ */
+ public function data_provider_delayed_strategies() {
+ return array(
+ 'defer' => array( 'defer' ),
+ 'async' => array( 'async' ),
+ );
+ }
+
+ /**
+ * Tests that inline scripts in the `after` position, attached to delayed main scripts, remain unaffected.
+ *
+ * If the main script with delayed loading strategy has an `after` inline script,
+ * the inline script should not be affected.
+ *
+ * @ticket 12009
+ *
+ * @covers WP_Scripts::do_item
+ * @covers WP_Scripts::get_inline_script_tag
+ * @covers ::wp_add_inline_script
+ * @covers ::wp_enqueue_script
+ *
+ * @dataProvider data_provider_delayed_strategies
+ *
+ * @param string $strategy Strategy.
+ */
+ public function test_after_inline_script_with_delayed_main_script( $strategy ) {
+ wp_enqueue_script( 'ms-isa-1', 'http://example.org/ms-isa-1.js', array(), null, compact( 'strategy' ) );
+ wp_add_inline_script( 'ms-isa-1', 'console.log("after one");', 'after' );
+ $output = get_echo( 'wp_print_scripts' );
+ $expected = "<script type='text/javascript' src='http://example.org/ms-isa-1.js' id='ms-isa-1-js' data-wp-strategy='{$strategy}'></script>\n";
+ $expected .= wp_get_inline_script_tag(
+ "console.log(\"after one\");\n",
+ array(
+ 'id' => 'ms-isa-1-js-after',
+ )
+ );
+ $this->assertSame( $expected, $output, 'Inline scripts in the "after" position, that are attached to a deferred main script, are failing to print/execute.' );
+ }
+
+ /**
+ * Tests that inline scripts in the `after` position, attached to a blocking main script, are rendered as javascript.
+ *
+ * If a main script with a `blocking` strategy has an `after` inline script,
+ * the inline script should be rendered as type='text/javascript'.
+ *
+ * @ticket 12009
+ *
+ * @covers WP_Scripts::do_item
+ * @covers WP_Scripts::get_inline_script_tag
+ * @covers ::wp_add_inline_script
+ * @covers ::wp_enqueue_script
+ */
+ public function test_after_inline_script_with_blocking_main_script() {
+ wp_enqueue_script( 'ms-insa-3', 'http://example.org/ms-insa-3.js', array(), null );
+ wp_add_inline_script( 'ms-insa-3', 'console.log("after one");', 'after' );
+ $output = get_echo( 'wp_print_scripts' );
+
+ $expected = "<script type='text/javascript' src='http://example.org/ms-insa-3.js' id='ms-insa-3-js'></script>\n";
+ $expected .= wp_get_inline_script_tag(
+ "console.log(\"after one\");\n",
+ array(
+ 'id' => 'ms-insa-3-js-after',
+ )
+ );
+
+ $this->assertSame( $expected, $output, 'Inline scripts in the "after" position, that are attached to a blocking main script, are failing to print/execute.' );
+ }
+
+ /**
+ * Tests that inline scripts in the `before` position, attached to a delayed inline main script, results in all
+ * dependents being delayed.
+ *
+ * @ticket 12009
+ *
+ * @covers WP_Scripts::do_item
+ * @covers WP_Scripts::get_inline_script_tag
+ * @covers ::wp_add_inline_script
+ * @covers ::wp_enqueue_script
+ *
+ * @dataProvider data_provider_delayed_strategies
+ *
+ * @param string $strategy
+ */
+ public function test_before_inline_scripts_with_delayed_main_script( $strategy ) {
+ wp_enqueue_script( 'ds-i1-1', 'http://example.org/ds-i1-1.js', array(), null, compact( 'strategy' ) );
+ wp_add_inline_script( 'ds-i1-1', 'console.log("before first");', 'before' );
+ wp_enqueue_script( 'ds-i1-2', 'http://example.org/ds-i1-2.js', array(), null, compact( 'strategy' ) );
+ wp_enqueue_script( 'ds-i1-3', 'http://example.org/ds-i1-3.js', array(), null, compact( 'strategy' ) );
+ wp_enqueue_script( 'ms-i1-1', 'http://example.org/ms-i1-1.js', array( 'ds-i1-1', 'ds-i1-2', 'ds-i1-3' ), null, compact( 'strategy' ) );
+ wp_add_inline_script( 'ms-i1-1', 'console.log("before last");', 'before' );
+ $output = get_echo( 'wp_print_scripts' );
+
+ $expected = wp_get_inline_script_tag(
+ "console.log(\"before first\");\n",
+ array(
+ 'id' => 'ds-i1-1-js-before',
+ )
+ );
+ $expected .= "<script type='text/javascript' src='http://example.org/ds-i1-1.js' id='ds-i1-1-js' $strategy data-wp-strategy='{$strategy}'></script>\n";
+ $expected .= "<script type='text/javascript' src='http://example.org/ds-i1-2.js' id='ds-i1-2-js' $strategy data-wp-strategy='{$strategy}'></script>\n";
+ $expected .= "<script type='text/javascript' src='http://example.org/ds-i1-3.js' id='ds-i1-3-js' $strategy data-wp-strategy='{$strategy}'></script>\n";
+ $expected .= wp_get_inline_script_tag(
+ "console.log(\"before last\");\n",
+ array(
+ 'id' => 'ms-i1-1-js-before',
+ 'type' => 'text/javascript',
+ )
+ );
+ $expected .= "<script type='text/javascript' src='http://example.org/ms-i1-1.js' id='ms-i1-1-js' {$strategy} data-wp-strategy='{$strategy}'></script>\n";
+
+ $this->assertSame( $expected, $output, 'Inline scripts in the "before" position, that are attached to a deferred main script, are failing to print/execute.' );
+ }
+
+ /**
+ * Tests that scripts registered with an async strategy print with the async attribute.
+ *
+ * @ticket 12009
+ *
+ * @covers WP_Scripts::do_item
+ * @covers WP_Scripts::get_eligible_loading_strategy
+ * @covers WP_Scripts::filter_eligible_strategies
+ * @covers ::wp_enqueue_script
+ */
+ public function test_loading_strategy_with_valid_async_registration() {
+ // No dependents, No dependencies then async.
+ wp_enqueue_script( 'main-script-a1', '/main-script-a1.js', array(), null, array( 'strategy' => 'async' ) );
+ $output = get_echo( 'wp_print_scripts' );
+ $expected = "<script type='text/javascript' src='/main-script-a1.js' id='main-script-a1-js' async data-wp-strategy='async'></script>\n";
+ $this->assertSame( $expected, $output, 'Scripts enqueued with an async loading strategy are failing to have the async attribute applied to the script handle when being printed.' );
+ }
+
+ /**
+ * Tests that dependents of a blocking dependency script are free to contain any strategy.
+ *
+ * @ticket 12009
+ *
+ * @covers WP_Scripts::do_item
+ * @covers WP_Scripts::get_eligible_loading_strategy
+ * @covers WP_Scripts::filter_eligible_strategies
+ * @covers ::wp_enqueue_script
+ *
+ * @dataProvider data_provider_delayed_strategies
+ *
+ * @param string $strategy Strategy.
+ */
+ public function test_delayed_dependent_with_blocking_dependency( $strategy ) {
+ wp_enqueue_script( 'dependency-script-a2', '/dependency-script-a2.js', array(), null );
+ wp_enqueue_script( 'main-script-a2', '/main-script-a2.js', array( 'dependency-script-a2' ), null, compact( 'strategy' ) );
+ $output = get_echo( 'wp_print_scripts' );
+ $expected = "<script type='text/javascript' src='/main-script-a2.js' id='main-script-a2-js' {$strategy} data-wp-strategy='{$strategy}'></script>";
+ $this->assertStringContainsString( $expected, $output, 'Dependents of a blocking dependency are free to have any strategy.' );
+ }
+
+ /**
+ * Tests that blocking dependents force delayed dependencies to become blocking.
+ *
+ * @ticket 12009
+ *
+ * @covers WP_Scripts::do_item
+ * @covers WP_Scripts::get_eligible_loading_strategy
+ * @covers WP_Scripts::filter_eligible_strategies
+ * @covers ::wp_enqueue_script
+ *
+ * @dataProvider data_provider_delayed_strategies
+ * @param string $strategy Strategy.
+ */
+ public function test_blocking_dependent_with_delayed_dependency( $strategy ) {
+ wp_enqueue_script( 'main-script-a3', '/main-script-a3.js', array(), null, compact( 'strategy' ) );
+ wp_enqueue_script( 'dependent-script-a3', '/dependent-script-a3.js', array( 'main-script-a3' ), null );
+ $output = get_echo( 'wp_print_scripts' );
+ $expected = "<script type='text/javascript' src='/main-script-a3.js' id='main-script-a3-js' data-wp-strategy='{$strategy}'></script>";
+ $this->assertStringContainsString( $expected, $output, 'Blocking dependents must force delayed dependencies to become blocking.' );
+ }
+
+ /**
+ * Tests that only enqueued dependents effect the eligible loading strategy.
+ *
+ * @ticket 12009
+ *
+ * @covers WP_Scripts::do_item
+ * @covers WP_Scripts::get_eligible_loading_strategy
+ * @covers WP_Scripts::filter_eligible_strategies
+ * @covers ::wp_enqueue_script
+ *
+ * @dataProvider data_provider_delayed_strategies
+ * @param string $strategy Strategy.
+ */
+ public function test_delayed_dependent_with_blocking_dependency_not_enqueued( $strategy ) {
+ wp_enqueue_script( 'main-script-a4', '/main-script-a4.js', array(), null, compact( 'strategy' ) );
+ // This dependent is registered but not enqueued, so it should not factor into the eligible loading strategy.
+ wp_register_script( 'dependent-script-a4', '/dependent-script-a4.js', array( 'main-script-a4' ), null );
+ $output = get_echo( 'wp_print_scripts' );
+ $expected = "<script type='text/javascript' src='/main-script-a4.js' id='main-script-a4-js' {$strategy} data-wp-strategy='{$strategy}'></script>";
+ $this->assertStringContainsString( $expected, $output, 'Only enqueued dependents should affect the eligible strategy.' );
+ }
+
+ /**
+ * Data provider for test_filter_eligible_strategies.
+ *
+ * @return array
+ */
+ public function get_data_to_filter_eligible_strategies() {
+ return array(
+ 'no_dependents' => array(
+ 'set_up' => static function () {
+ wp_enqueue_script( 'foo', 'https://example.com/foo.js', array(), null, array( 'strategy' => 'defer' ) );
+ return 'foo';
+ },
+ 'expected' => array( 'defer' ),
+ ),
+ 'one_delayed_dependent' => array(
+ 'set_up' => static function () {
+ wp_enqueue_script( 'foo', 'https://example.com/foo.js', array(), null, array( 'strategy' => 'defer' ) );
+ wp_enqueue_script( 'bar', 'https://example.com/bar.js', array( 'foo' ), null, array( 'strategy' => 'defer' ) );
+ return 'foo';
+ },
+ 'expected' => array( 'defer' ),
+ ),
+ 'one_blocking_dependent' => array(
+ 'set_up' => static function () {
+ wp_enqueue_script( 'foo', 'https://example.com/foo.js', array(), null, array( 'strategy' => 'defer' ) );
+ wp_enqueue_script( 'bar', 'https://example.com/bar.js', array( 'foo' ), null );
+ return 'foo';
+ },
+ 'expected' => array(),
+ ),
+ 'one_blocking_dependent_not_enqueued' => array(
+ 'set_up' => static function () {
+ wp_enqueue_script( 'foo', 'https://example.com/foo.js', array(), null, array( 'strategy' => 'defer' ) );
+ wp_register_script( 'bar', 'https://example.com/bar.js', array( 'foo' ), null );
+ return 'foo';
+ },
+ 'expected' => array( 'defer' ), // Because bar was not enqueued, only foo was.
+ ),
+ 'two_delayed_dependents' => array(
+ 'set_up' => static function () {
+ wp_enqueue_script( 'foo', 'https://example.com/foo.js', array(), null, array( 'strategy' => 'defer' ) );
+ wp_enqueue_script( 'bar', 'https://example.com/bar.js', array( 'foo' ), null, array( 'strategy' => 'defer' ) );
+ wp_enqueue_script( 'baz', 'https://example.com/baz.js', array( 'foo' ), null, array( 'strategy' => 'defer' ) );
+ return 'foo';
+ },
+ 'expected' => array( 'defer' ),
+ ),
+ 'recursion_not_delayed' => array(
+ 'set_up' => static function () {
+ wp_enqueue_script( 'foo', 'https://example.com/foo.js', array( 'foo' ), null );
+ return 'foo';
+ },
+ 'expected' => array(),
+ ),
+ 'recursion_yes_delayed' => array(
+ 'set_up' => static function () {
+ wp_enqueue_script( 'foo', 'https://example.com/foo.js', array( 'foo' ), null, array( 'strategy' => 'defer' ) );
+ return 'foo';
+ },
+ 'expected' => array( 'defer' ),
+ ),
+ 'recursion_triple_level' => array(
+ 'set_up' => static function () {
+ wp_enqueue_script( 'foo', 'https://example.com/foo.js', array( 'baz' ), null, array( 'strategy' => 'defer' ) );
+ wp_enqueue_script( 'bar', 'https://example.com/bar.js', array( 'foo' ), null, array( 'strategy' => 'defer' ) );
+ wp_enqueue_script( 'baz', 'https://example.com/bar.js', array( 'bar' ), null, array( 'strategy' => 'defer' ) );
+ return 'foo';
+ },
+ 'expected' => array( 'defer' ),
+ ),
+ 'async_only_with_async_dependency' => array(
+ 'set_up' => static function () {
+ wp_enqueue_script( 'foo', 'https://example.com/foo.js', array(), null, array( 'strategy' => 'async' ) );
+ wp_enqueue_script( 'bar', 'https://example.com/bar.js', array( 'foo' ), null, array( 'strategy' => 'async' ) );
+ return 'foo';
+ },
+ 'expected' => array( 'defer', 'async' ),
+ ),
+ 'async_only_with_defer_dependency' => array(
+ 'set_up' => static function () {
+ wp_enqueue_script( 'foo', 'https://example.com/foo.js', array(), null, array( 'strategy' => 'async' ) );
+ wp_enqueue_script( 'bar', 'https://example.com/bar.js', array( 'foo' ), null, array( 'strategy' => 'defer' ) );
+ return 'foo';
+ },
+ 'expected' => array( 'defer' ),
+ ),
+ 'async_only_with_blocking_dependency' => array(
+ 'set_up' => static function () {
+ wp_enqueue_script( 'foo', 'https://example.com/foo.js', array(), null, array( 'strategy' => 'async' ) );
+ wp_enqueue_script( 'bar', 'https://example.com/bar.js', array( 'foo' ), null );
+ return 'foo';
+ },
+ 'expected' => array(),
+ ),
+ 'defer_with_inline_after_script' => array(
+ 'set_up' => static function () {
+ wp_enqueue_script( 'foo', 'https://example.com/foo.js', array(), null, array( 'strategy' => 'defer' ) );
+ wp_add_inline_script( 'foo', 'console.log("foo")', 'after' );
+ return 'foo';
+ },
+ 'expected' => array(),
+ ),
+ 'defer_with_inline_before_script' => array(
+ 'set_up' => static function () {
+ wp_enqueue_script( 'foo', 'https://example.com/foo.js', array(), null, array( 'strategy' => 'defer' ) );
+ wp_add_inline_script( 'foo', 'console.log("foo")', 'before' );
+ return 'foo';
+ },
+ 'expected' => array( 'defer' ),
+ ),
+ 'async_with_inline_after_script' => array(
+ 'set_up' => static function () {
+ wp_enqueue_script( 'foo', 'https://example.com/foo.js', array(), null, array( 'strategy' => 'async' ) );
+ wp_add_inline_script( 'foo', 'console.log("foo")', 'after' );
+ return 'foo';
+ },
+ 'expected' => array(),
+ ),
+ 'async_with_inline_before_script' => array(
+ 'set_up' => static function () {
+ wp_enqueue_script( 'foo', 'https://example.com/foo.js', array(), null, array( 'strategy' => 'async' ) );
+ wp_add_inline_script( 'foo', 'console.log("foo")', 'before' );
+ return 'foo';
+ },
+ 'expected' => array( 'defer', 'async' ),
+ ),
+ );
+ }
+
+ /**
+ * Tests that the filter_eligible_strategies method works as expected and returns the correct value.
+ *
+ * @ticket 12009
+ *
+ * @covers WP_Scripts::filter_eligible_strategies
+ *
+ * @dataProvider get_data_to_filter_eligible_strategies
+ *
+ * @param callable $set_up Set up.
+ * @param bool $async_only Async only.
+ * @param bool $expected Expected return value.
+ */
+ public function test_filter_eligible_strategies( $set_up, $expected ) {
+ $handle = $set_up();
+
+ $wp_scripts_reflection = new ReflectionClass( WP_Scripts::class );
+ $filter_eligible_strategies = $wp_scripts_reflection->getMethod( 'filter_eligible_strategies' );
+ $filter_eligible_strategies->setAccessible( true );
+ $this->assertSame( $expected, $filter_eligible_strategies->invokeArgs( wp_scripts(), array( $handle ) ), 'Expected return value of WP_Scripts::filter_eligible_strategies to match.' );
+ }
+
+ /**
+ * Register test script.
+ *
+ * @param string $handle Dependency handle to enqueue.
+ * @param string $strategy Strategy to use for dependency.
+ * @param string[] $deps Dependencies for the script.
+ * @param bool $in_footer Whether to print the script in the footer.
+ */
+ protected function register_test_script( $handle, $strategy, $deps = array(), $in_footer = false ) {
+ wp_register_script(
+ $handle,
+ add_query_arg(
+ array(
+ 'script_event_log' => "$handle: script",
+ ),
+ 'https://example.com/external.js'
+ ),
+ $deps,
+ null
+ );
+ if ( 'blocking' !== $strategy ) {
+ wp_script_add_data( $handle, 'strategy', $strategy );
+ }
+ }
+
+ /**
+ * Enqueue test script.
+ *
+ * @param string $handle Dependency handle to enqueue.
+ * @param string $strategy Strategy to use for dependency.
+ * @param string[] $deps Dependencies for the script.
+ * @param bool $in_footer Whether to print the script in the footer.
+ */
+ protected function enqueue_test_script( $handle, $strategy, $deps = array(), $in_footer = false ) {
+ $this->register_test_script( $handle, $strategy, $deps, $in_footer );
+ wp_enqueue_script( $handle );
+ }
+
+ /**
+ * Adds test inline script.
+ *
+ * @param string $handle Dependency handle to enqueue.
+ * @param string $position Position.
+ */
+ protected function add_test_inline_script( $handle, $position ) {
+ wp_add_inline_script( $handle, sprintf( 'scriptEventLog.push( %s )', wp_json_encode( "{$handle}: {$position} inline" ) ), $position );
+ }
+
+ /**
+ * Data provider to test various strategy dependency chains.
+ *
+ * @return array[]
+ */
+ public function data_provider_to_test_various_strategy_dependency_chains() {
+ return array(
+ 'async-dependent-with-one-blocking-dependency' => array(
+ 'set_up' => function () {
+ $handle1 = 'blocking-not-async-without-dependency';
+ $handle2 = 'async-with-blocking-dependency';
+ $this->enqueue_test_script( $handle1, 'blocking', array() );
+ $this->enqueue_test_script( $handle2, 'async', array( $handle1 ) );
+ foreach ( array( $handle1, $handle2 ) as $handle ) {
+ $this->add_test_inline_script( $handle, 'before' );
+ $this->add_test_inline_script( $handle, 'after' );
+ }
+ },
+ 'expected_markup' => <<<HTML
+<script id="blocking-not-async-without-dependency-js-before" type="text/javascript">
+scriptEventLog.push( "blocking-not-async-without-dependency: before inline" )
+</script>
+<script type='text/javascript' src='https://example.com/external.js?script_event_log=blocking-not-async-without-dependency:%20script' id='blocking-not-async-without-dependency-js'></script>
+<script id="blocking-not-async-without-dependency-js-after" type="text/javascript">
+scriptEventLog.push( "blocking-not-async-without-dependency: after inline" )
+</script>
+<script id="async-with-blocking-dependency-js-before" type="text/javascript">
+scriptEventLog.push( "async-with-blocking-dependency: before inline" )
+</script>
+<script type='text/javascript' src='https://example.com/external.js?script_event_log=async-with-blocking-dependency:%20script' id='async-with-blocking-dependency-js' data-wp-strategy='async'></script>
+<script id="async-with-blocking-dependency-js-after" type="text/javascript">
+scriptEventLog.push( "async-with-blocking-dependency: after inline" )
+</script>
+HTML
+ ,
+ /*
+ * Note: The above comma must be on its own line in PHP<7.3 and not after the `HTML` identifier
+ * terminating the heredoc. Otherwise, a syntax error is raised with the line number being wildly wrong:
+ *
+ * PHP Parse error: syntax error, unexpected '' (T_ENCAPSED_AND_WHITESPACE), expecting '-' or identifier (T_STRING) or variable (T_VARIABLE) or number (T_NUM_STRING)
+ */
+ ),
+ 'async-with-async-dependencies' => array(
+ 'set_up' => function () {
+ $handle1 = 'async-no-dependency';
+ $handle2 = 'async-one-async-dependency';
+ $handle3 = 'async-two-async-dependencies';
+ $this->enqueue_test_script( $handle1, 'async', array() );
+ $this->enqueue_test_script( $handle2, 'async', array( $handle1 ) );
+ $this->enqueue_test_script( $handle3, 'async', array( $handle1, $handle2 ) );
+ foreach ( array( $handle1, $handle2, $handle3 ) as $handle ) {
+ $this->add_test_inline_script( $handle, 'before' );
+ $this->add_test_inline_script( $handle, 'after' );
+ }
+ },
+ 'expected_markup' => <<<HTML
+<script id="async-no-dependency-js-before" type="text/javascript">
+scriptEventLog.push( "async-no-dependency: before inline" )
+</script>
+<script type='text/javascript' src='https://example.com/external.js?script_event_log=async-no-dependency:%20script' id='async-no-dependency-js' data-wp-strategy='async'></script>
+<script id="async-no-dependency-js-after" type="text/javascript">
+scriptEventLog.push( "async-no-dependency: after inline" )
+</script>
+<script id="async-one-async-dependency-js-before" type="text/javascript">
+scriptEventLog.push( "async-one-async-dependency: before inline" )
+</script>
+<script type='text/javascript' src='https://example.com/external.js?script_event_log=async-one-async-dependency:%20script' id='async-one-async-dependency-js' data-wp-strategy='async'></script>
+<script id="async-one-async-dependency-js-after" type="text/javascript">
+scriptEventLog.push( "async-one-async-dependency: after inline" )
+</script>
+<script id="async-two-async-dependencies-js-before" type="text/javascript">
+scriptEventLog.push( "async-two-async-dependencies: before inline" )
+</script>
+<script type='text/javascript' src='https://example.com/external.js?script_event_log=async-two-async-dependencies:%20script' id='async-two-async-dependencies-js' data-wp-strategy='async'></script>
+<script id="async-two-async-dependencies-js-after" type="text/javascript">
+scriptEventLog.push( "async-two-async-dependencies: after inline" )
+</script>
+HTML
+ ,
+ ),
+ 'async-with-blocking-dependency' => array(
+ 'set_up' => function () {
+ $handle1 = 'async-with-blocking-dependent';
+ $handle2 = 'blocking-dependent-of-async';
+ $this->enqueue_test_script( $handle1, 'async', array() );
+ $this->enqueue_test_script( $handle2, 'blocking', array( $handle1 ) );
+ foreach ( array( $handle1, $handle2 ) as $handle ) {
+ $this->add_test_inline_script( $handle, 'before' );
+ $this->add_test_inline_script( $handle, 'after' );
+ }
+ },
+ 'expected_markup' => <<<HTML
+<script id="async-with-blocking-dependent-js-before" type="text/javascript">
+scriptEventLog.push( "async-with-blocking-dependent: before inline" )
+</script>
+<script type='text/javascript' src='https://example.com/external.js?script_event_log=async-with-blocking-dependent:%20script' id='async-with-blocking-dependent-js' data-wp-strategy='async'></script>
+<script id="async-with-blocking-dependent-js-after" type="text/javascript">
+scriptEventLog.push( "async-with-blocking-dependent: after inline" )
+</script>
+<script id="blocking-dependent-of-async-js-before" type="text/javascript">
+scriptEventLog.push( "blocking-dependent-of-async: before inline" )
+</script>
+<script type='text/javascript' src='https://example.com/external.js?script_event_log=blocking-dependent-of-async:%20script' id='blocking-dependent-of-async-js'></script>
+<script id="blocking-dependent-of-async-js-after" type="text/javascript">
+scriptEventLog.push( "blocking-dependent-of-async: after inline" )
+</script>
+HTML
+ ,
+ ),
+ 'defer-with-async-dependency' => array(
+ 'set_up' => function () {
+ $handle1 = 'async-with-defer-dependent';
+ $handle2 = 'defer-dependent-of-async';
+ $this->enqueue_test_script( $handle1, 'async', array() );
+ $this->enqueue_test_script( $handle2, 'defer', array( $handle1 ) );
+ foreach ( array( $handle1, $handle2 ) as $handle ) {
+ $this->add_test_inline_script( $handle, 'before' );
+ $this->add_test_inline_script( $handle, 'after' );
+ }
+ },
+ 'expected_markup' => <<<HTML
+<script id="async-with-defer-dependent-js-before" type="text/javascript">
+scriptEventLog.push( "async-with-defer-dependent: before inline" )
+</script>
+<script type='text/javascript' src='https://example.com/external.js?script_event_log=async-with-defer-dependent:%20script' id='async-with-defer-dependent-js' data-wp-strategy='async'></script>
+<script id="async-with-defer-dependent-js-after" type="text/javascript">
+scriptEventLog.push( "async-with-defer-dependent: after inline" )
+</script>
+<script id="defer-dependent-of-async-js-before" type="text/javascript">
+scriptEventLog.push( "defer-dependent-of-async: before inline" )
+</script>
+<script type='text/javascript' src='https://example.com/external.js?script_event_log=defer-dependent-of-async:%20script' id='defer-dependent-of-async-js' data-wp-strategy='defer'></script>
+<script id="defer-dependent-of-async-js-after" type="text/javascript">
+scriptEventLog.push( "defer-dependent-of-async: after inline" )
+</script>
+HTML
+ ,
+ ),
+ 'blocking-bundle-of-none-with-inline-scripts-and-defer-dependent' => array(
+ 'set_up' => function () {
+ $handle1 = 'blocking-bundle-of-none';
+ $handle2 = 'defer-dependent-of-blocking-bundle-of-none';
+
+ wp_register_script( $handle1, false, array(), null );
+ $this->add_test_inline_script( $handle1, 'before' );
+ $this->add_test_inline_script( $handle1, 'after' );
+
+ // Note: the before script for this will be blocking because the dependency is blocking.
+ $this->enqueue_test_script( $handle2, 'defer', array( $handle1 ) );
+ $this->add_test_inline_script( $handle2, 'before' );
+ $this->add_test_inline_script( $handle2, 'after' );
+ },
+ 'expected_markup' => <<<HTML
+<script id="blocking-bundle-of-none-js-before" type="text/javascript">
+scriptEventLog.push( "blocking-bundle-of-none: before inline" )
+</script>
+<script id="blocking-bundle-of-none-js-after" type="text/javascript">
+scriptEventLog.push( "blocking-bundle-of-none: after inline" )
+</script>
+<script id="defer-dependent-of-blocking-bundle-of-none-js-before" type="text/javascript">
+scriptEventLog.push( "defer-dependent-of-blocking-bundle-of-none: before inline" )
+</script>
+<script type='text/javascript' src='https://example.com/external.js?script_event_log=defer-dependent-of-blocking-bundle-of-none:%20script' id='defer-dependent-of-blocking-bundle-of-none-js' data-wp-strategy='defer'></script>
+<script id="defer-dependent-of-blocking-bundle-of-none-js-after" type="text/javascript">
+scriptEventLog.push( "defer-dependent-of-blocking-bundle-of-none: after inline" )
+</script>
+HTML
+ ,
+ ),
+ 'blocking-bundle-of-two-with-defer-dependent' => array(
+ 'set_up' => function () {
+ $handle1 = 'blocking-bundle-of-two';
+ $handle2 = 'blocking-bundle-member-one';
+ $handle3 = 'blocking-bundle-member-two';
+ $handle4 = 'defer-dependent-of-blocking-bundle-of-two';
+
+ wp_register_script( $handle1, false, array( $handle2, $handle3 ), null );
+ $this->enqueue_test_script( $handle2, 'blocking' );
+ $this->enqueue_test_script( $handle3, 'blocking' );
+ $this->enqueue_test_script( $handle4, 'defer', array( $handle1 ) );
+
+ foreach ( array( $handle2, $handle3, $handle4 ) as $handle ) {
+ $this->add_test_inline_script( $handle, 'before' );
+ $this->add_test_inline_script( $handle, 'after' );
+ }
+ },
+ 'expected_markup' => <<<HTML
+<script id="blocking-bundle-member-one-js-before" type="text/javascript">
+scriptEventLog.push( "blocking-bundle-member-one: before inline" )
+</script>
+<script type='text/javascript' src='https://example.com/external.js?script_event_log=blocking-bundle-member-one:%20script' id='blocking-bundle-member-one-js'></script>
+<script id="blocking-bundle-member-one-js-after" type="text/javascript">
+scriptEventLog.push( "blocking-bundle-member-one: after inline" )
+</script>
+<script id="blocking-bundle-member-two-js-before" type="text/javascript">
+scriptEventLog.push( "blocking-bundle-member-two: before inline" )
+</script>
+<script type='text/javascript' src='https://example.com/external.js?script_event_log=blocking-bundle-member-two:%20script' id='blocking-bundle-member-two-js'></script>
+<script id="blocking-bundle-member-two-js-after" type="text/javascript">
+scriptEventLog.push( "blocking-bundle-member-two: after inline" )
+</script>
+<script id="defer-dependent-of-blocking-bundle-of-two-js-before" type="text/javascript">
+scriptEventLog.push( "defer-dependent-of-blocking-bundle-of-two: before inline" )
+</script>
+<script type='text/javascript' src='https://example.com/external.js?script_event_log=defer-dependent-of-blocking-bundle-of-two:%20script' id='defer-dependent-of-blocking-bundle-of-two-js' data-wp-strategy='defer'></script>
+<script id="defer-dependent-of-blocking-bundle-of-two-js-after" type="text/javascript">
+scriptEventLog.push( "defer-dependent-of-blocking-bundle-of-two: after inline" )
+</script>
+HTML
+ ,
+ ),
+ 'defer-bundle-of-none-with-inline-scripts-and-defer-dependents' => array(
+ 'set_up' => function () {
+ $handle1 = 'defer-bundle-of-none';
+ $handle2 = 'defer-dependent-of-defer-bundle-of-none';
+
+ // The eligible loading strategy for this will be forced to be blocking when rendered since $src = false.
+ wp_register_script( $handle1, false, array(), null );
+ wp_scripts()->registered[ $handle1 ]->extra['strategy'] = 'defer'; // Bypass wp_script_add_data() which should no-op with _doing_it_wrong() because of $src=false.
+ $this->add_test_inline_script( $handle1, 'before' );
+ $this->add_test_inline_script( $handle1, 'after' );
+
+ // Note: the before script for this will be blocking because the dependency is blocking.
+ $this->enqueue_test_script( $handle2, 'defer', array( $handle1 ) );
+ $this->add_test_inline_script( $handle2, 'before' );
+ $this->add_test_inline_script( $handle2, 'after' );
+ },
+ 'expected_markup' => <<<HTML
+<script id="defer-bundle-of-none-js-before" type="text/javascript">
+scriptEventLog.push( "defer-bundle-of-none: before inline" )
+</script>
+<script id="defer-bundle-of-none-js-after" type="text/javascript">
+scriptEventLog.push( "defer-bundle-of-none: after inline" )
+</script>
+<script id="defer-dependent-of-defer-bundle-of-none-js-before" type="text/javascript">
+scriptEventLog.push( "defer-dependent-of-defer-bundle-of-none: before inline" )
+</script>
+<script type='text/javascript' src='https://example.com/external.js?script_event_log=defer-dependent-of-defer-bundle-of-none:%20script' id='defer-dependent-of-defer-bundle-of-none-js' data-wp-strategy='defer'></script>
+<script id="defer-dependent-of-defer-bundle-of-none-js-after" type="text/javascript">
+scriptEventLog.push( "defer-dependent-of-defer-bundle-of-none: after inline" )
+</script>
+HTML
+ ,
+ ),
+ 'defer-dependent-with-blocking-and-defer-dependencies' => array(
+ 'set_up' => function () {
+ $handle1 = 'blocking-dependency-with-defer-following-dependency';
+ $handle2 = 'defer-dependency-with-blocking-preceding-dependency';
+ $handle3 = 'defer-dependent-of-blocking-and-defer-dependencies';
+ $this->enqueue_test_script( $handle1, 'blocking', array() );
+ $this->enqueue_test_script( $handle2, 'defer', array() );
+ $this->enqueue_test_script( $handle3, 'defer', array( $handle1, $handle2 ) );
+
+ foreach ( array( $handle1, $handle2, $handle3 ) as $dep ) {
+ $this->add_test_inline_script( $dep, 'before' );
+ $this->add_test_inline_script( $dep, 'after' );
+ }
+ },
+ 'expected_markup' => <<<HTML
+<script id="blocking-dependency-with-defer-following-dependency-js-before" type="text/javascript">
+scriptEventLog.push( "blocking-dependency-with-defer-following-dependency: before inline" )
+</script>
+<script type='text/javascript' src='https://example.com/external.js?script_event_log=blocking-dependency-with-defer-following-dependency:%20script' id='blocking-dependency-with-defer-following-dependency-js'></script>
+<script id="blocking-dependency-with-defer-following-dependency-js-after" type="text/javascript">
+scriptEventLog.push( "blocking-dependency-with-defer-following-dependency: after inline" )
+</script>
+<script id="defer-dependency-with-blocking-preceding-dependency-js-before" type="text/javascript">
+scriptEventLog.push( "defer-dependency-with-blocking-preceding-dependency: before inline" )
+</script>
+<script type='text/javascript' src='https://example.com/external.js?script_event_log=defer-dependency-with-blocking-preceding-dependency:%20script' id='defer-dependency-with-blocking-preceding-dependency-js' data-wp-strategy='defer'></script>
+<script id="defer-dependency-with-blocking-preceding-dependency-js-after" type="text/javascript">
+scriptEventLog.push( "defer-dependency-with-blocking-preceding-dependency: after inline" )
+</script>
+<script id="defer-dependent-of-blocking-and-defer-dependencies-js-before" type="text/javascript">
+scriptEventLog.push( "defer-dependent-of-blocking-and-defer-dependencies: before inline" )
+</script>
+<script type='text/javascript' src='https://example.com/external.js?script_event_log=defer-dependent-of-blocking-and-defer-dependencies:%20script' id='defer-dependent-of-blocking-and-defer-dependencies-js' data-wp-strategy='defer'></script>
+<script id="defer-dependent-of-blocking-and-defer-dependencies-js-after" type="text/javascript">
+scriptEventLog.push( "defer-dependent-of-blocking-and-defer-dependencies: after inline" )
+</script>
+HTML
+ ,
+ ),
+ 'defer-dependent-with-defer-and-blocking-dependencies' => array(
+ 'set_up' => function () {
+ $handle1 = 'defer-dependency-with-blocking-following-dependency';
+ $handle2 = 'blocking-dependency-with-defer-preceding-dependency';
+ $handle3 = 'defer-dependent-of-defer-and-blocking-dependencies';
+ $this->enqueue_test_script( $handle1, 'defer', array() );
+ $this->enqueue_test_script( $handle2, 'blocking', array() );
+ $this->enqueue_test_script( $handle3, 'defer', array( $handle1, $handle2 ) );
+
+ foreach ( array( $handle1, $handle2, $handle3 ) as $dep ) {
+ $this->add_test_inline_script( $dep, 'before' );
+ $this->add_test_inline_script( $dep, 'after' );
+ }
+ },
+ 'expected_markup' => <<<HTML
+<script id="defer-dependency-with-blocking-following-dependency-js-before" type="text/javascript">
+scriptEventLog.push( "defer-dependency-with-blocking-following-dependency: before inline" )
+</script>
+<script type='text/javascript' src='https://example.com/external.js?script_event_log=defer-dependency-with-blocking-following-dependency:%20script' id='defer-dependency-with-blocking-following-dependency-js' data-wp-strategy='defer'></script>
+<script id="defer-dependency-with-blocking-following-dependency-js-after" type="text/javascript">
+scriptEventLog.push( "defer-dependency-with-blocking-following-dependency: after inline" )
+</script>
+<script id="blocking-dependency-with-defer-preceding-dependency-js-before" type="text/javascript">
+scriptEventLog.push( "blocking-dependency-with-defer-preceding-dependency: before inline" )
+</script>
+<script type='text/javascript' src='https://example.com/external.js?script_event_log=blocking-dependency-with-defer-preceding-dependency:%20script' id='blocking-dependency-with-defer-preceding-dependency-js'></script>
+<script id="blocking-dependency-with-defer-preceding-dependency-js-after" type="text/javascript">
+scriptEventLog.push( "blocking-dependency-with-defer-preceding-dependency: after inline" )
+</script>
+<script id="defer-dependent-of-defer-and-blocking-dependencies-js-before" type="text/javascript">
+scriptEventLog.push( "defer-dependent-of-defer-and-blocking-dependencies: before inline" )
+</script>
+<script type='text/javascript' src='https://example.com/external.js?script_event_log=defer-dependent-of-defer-and-blocking-dependencies:%20script' id='defer-dependent-of-defer-and-blocking-dependencies-js' data-wp-strategy='defer'></script>
+<script id="defer-dependent-of-defer-and-blocking-dependencies-js-after" type="text/javascript">
+scriptEventLog.push( "defer-dependent-of-defer-and-blocking-dependencies: after inline" )
+</script>
+HTML
+ ,
+ ),
+ 'async-with-defer-dependency' => array(
+ 'set_up' => function () {
+ $handle1 = 'defer-with-async-dependent';
+ $handle2 = 'async-dependent-of-defer';
+ $this->enqueue_test_script( $handle1, 'defer', array() );
+ $this->enqueue_test_script( $handle2, 'async', array( $handle1 ) );
+ foreach ( array( $handle1, $handle2 ) as $handle ) {
+ $this->add_test_inline_script( $handle, 'before' );
+ $this->add_test_inline_script( $handle, 'after' );
+ }
+ },
+ 'expected_markup' => <<<HTML
+<script id="defer-with-async-dependent-js-before" type="text/javascript">
+scriptEventLog.push( "defer-with-async-dependent: before inline" )
+</script>
+<script type='text/javascript' src='https://example.com/external.js?script_event_log=defer-with-async-dependent:%20script' id='defer-with-async-dependent-js' data-wp-strategy='defer'></script>
+<script id="defer-with-async-dependent-js-after" type="text/javascript">
+scriptEventLog.push( "defer-with-async-dependent: after inline" )
+</script>
+<script id="async-dependent-of-defer-js-before" type="text/javascript">
+scriptEventLog.push( "async-dependent-of-defer: before inline" )
+</script>
+<script type='text/javascript' src='https://example.com/external.js?script_event_log=async-dependent-of-defer:%20script' id='async-dependent-of-defer-js' data-wp-strategy='async'></script>
+<script id="async-dependent-of-defer-js-after" type="text/javascript">
+scriptEventLog.push( "async-dependent-of-defer: after inline" )
+</script>
+HTML
+ ,
+ ),
+ 'defer-with-before-inline-script' => array(
+ 'set_up' => function () {
+ // Note this should NOT result in no delayed-inline-script-loader script being added.
+ $handle = 'defer-with-before-inline';
+ $this->enqueue_test_script( $handle, 'defer', array() );
+ $this->add_test_inline_script( $handle, 'before' );
+ },
+ 'expected_markup' => <<<HTML
+<script id="defer-with-before-inline-js-before" type="text/javascript">
+scriptEventLog.push( "defer-with-before-inline: before inline" )
+</script>
+<script type='text/javascript' src='https://example.com/external.js?script_event_log=defer-with-before-inline:%20script' id='defer-with-before-inline-js' defer data-wp-strategy='defer'></script>
+HTML
+ ,
+ ),
+ 'defer-with-after-inline-script' => array(
+ 'set_up' => function () {
+ // Note this SHOULD result in delayed-inline-script-loader script being added.
+ $handle = 'defer-with-after-inline';
+ $this->enqueue_test_script( $handle, 'defer', array() );
+ $this->add_test_inline_script( $handle, 'after' );
+ },
+ 'expected_markup' => <<<HTML
+<script type='text/javascript' src='https://example.com/external.js?script_event_log=defer-with-after-inline:%20script' id='defer-with-after-inline-js' data-wp-strategy='defer'></script>
+<script id="defer-with-after-inline-js-after" type="text/javascript">
+scriptEventLog.push( "defer-with-after-inline: after inline" )
+</script>
+HTML
+ ,
+ ),
+ 'jquery-deferred' => array(
+ 'set_up' => function () {
+ $wp_scripts = wp_scripts();
+ wp_default_scripts( $wp_scripts );
+ foreach ( $wp_scripts->registered['jquery']->deps as $jquery_dep ) {
+ $wp_scripts->registered[ $jquery_dep ]->add_data( 'strategy', 'defer' );
+ $wp_scripts->registered[ $jquery_dep ]->ver = null; // Just to avoid markup changes in the test when jQuery is upgraded.
+ }
+ wp_enqueue_script( 'theme-functions', 'https://example.com/theme-functions.js', array( 'jquery' ), null, array( 'strategy' => 'defer' ) );
+ },
+ 'expected_markup' => <<<HTML
+<script type='text/javascript' src='http://example.org/wp-includes/js/jquery/jquery.js' id='jquery-core-js' defer data-wp-strategy='defer'></script>
+<script type='text/javascript' src='http://example.org/wp-includes/js/jquery/jquery-migrate.js' id='jquery-migrate-js' defer data-wp-strategy='defer'></script>
+<script type='text/javascript' src='https://example.com/theme-functions.js' id='theme-functions-js' defer data-wp-strategy='defer'></script>
+HTML
+ ,
+ ),
+ 'nested-aliases' => array(
+ 'set_up' => function () {
+ $outer_alias_handle = 'outer-bundle-of-two';
+ $inner_alias_handle = 'inner-bundle-of-two';
+
+ // The outer alias contains a blocking member, as well as a nested alias that contains defer scripts.
+ wp_register_script( $outer_alias_handle, false, array( $inner_alias_handle, 'outer-bundle-leaf-member' ), null );
+ $this->register_test_script( 'outer-bundle-leaf-member', 'blocking', array() );
+
+ // Inner alias only contains delay scripts.
+ wp_register_script( $inner_alias_handle, false, array( 'inner-bundle-member-one', 'inner-bundle-member-two' ), null );
+ $this->register_test_script( 'inner-bundle-member-one', 'defer', array() );
+ $this->register_test_script( 'inner-bundle-member-two', 'defer', array() );
+
+ $this->enqueue_test_script( 'defer-dependent-of-nested-aliases', 'defer', array( $outer_alias_handle ) );
+ $this->add_test_inline_script( 'defer-dependent-of-nested-aliases', 'before' );
+ $this->add_test_inline_script( 'defer-dependent-of-nested-aliases', 'after' );
+ },
+ 'expected_markup' => <<<HTML
+<script type='text/javascript' src='https://example.com/external.js?script_event_log=inner-bundle-member-one:%20script' id='inner-bundle-member-one-js' data-wp-strategy='defer'></script>
+<script type='text/javascript' src='https://example.com/external.js?script_event_log=inner-bundle-member-two:%20script' id='inner-bundle-member-two-js' data-wp-strategy='defer'></script>
+<script type='text/javascript' src='https://example.com/external.js?script_event_log=outer-bundle-leaf-member:%20script' id='outer-bundle-leaf-member-js'></script>
+<script id="defer-dependent-of-nested-aliases-js-before" type="text/javascript">
+scriptEventLog.push( "defer-dependent-of-nested-aliases: before inline" )
+</script>
+<script type='text/javascript' src='https://example.com/external.js?script_event_log=defer-dependent-of-nested-aliases:%20script' id='defer-dependent-of-nested-aliases-js' data-wp-strategy='defer'></script>
+<script id="defer-dependent-of-nested-aliases-js-after" type="text/javascript">
+scriptEventLog.push( "defer-dependent-of-nested-aliases: after inline" )
+</script>
+HTML
+ ,
+ ),
+
+ 'async-alias-members-with-defer-dependency' => array(
+ 'set_up' => function () {
+ $alias_handle = 'async-alias';
+ $async_handle1 = 'async1';
+ $async_handle2 = 'async2';
+
+ wp_register_script( $alias_handle, false, array( $async_handle1, $async_handle2 ), null );
+ $this->register_test_script( $async_handle1, 'async', array() );
+ $this->register_test_script( $async_handle2, 'async', array() );
+
+ $this->enqueue_test_script( 'defer-dependent-of-async-aliases', 'defer', array( $alias_handle ) );
+ },
+ 'expected_markup' => <<<HTML
+<script type='text/javascript' src='https://example.com/external.js?script_event_log=async1:%20script' id='async1-js' defer data-wp-strategy='async'></script>
+<script type='text/javascript' src='https://example.com/external.js?script_event_log=async2:%20script' id='async2-js' defer data-wp-strategy='async'></script>
+<script type='text/javascript' src='https://example.com/external.js?script_event_log=defer-dependent-of-async-aliases:%20script' id='defer-dependent-of-async-aliases-js' defer data-wp-strategy='defer'></script>
+HTML
+ ,
+ ),
+ );
+ }
+
+ /**
+ * Tests that various loading strategy dependency chains function as expected.
+ *
+ * @covers ::wp_enqueue_script()
+ * @covers ::wp_add_inline_script()
+ * @covers ::wp_print_scripts()
+ * @covers WP_Scripts::get_inline_script_tag
+ *
+ * @dataProvider data_provider_to_test_various_strategy_dependency_chains
+ *
+ * @param callable $set_up Set up.
+ * @param string $expected_markup Expected markup.
+ */
+ public function test_various_strategy_dependency_chains( $set_up, $expected_markup ) {
+ $set_up();
+ $actual_markup = get_echo( 'wp_print_scripts' );
+ $this->assertEqualMarkup( trim( $expected_markup ), trim( $actual_markup ), "Actual markup:\n{$actual_markup}" );
+ }
+
+ /**
+ * Tests that defer is the final strategy when registering a script using defer, that has no dependents/dependencies.
+ *
+ * @ticket 12009
+ *
+ * @covers WP_Scripts::do_item
+ * @covers WP_Scripts::get_eligible_loading_strategy
+ * @covers ::wp_enqueue_script
+ */
+ public function test_loading_strategy_with_defer_having_no_dependents_nor_dependencies() {
+ wp_enqueue_script( 'main-script-d1', 'http://example.com/main-script-d1.js', array(), null, array( 'strategy' => 'defer' ) );
+ $output = get_echo( 'wp_print_scripts' );
+ $expected = "<script type='text/javascript' src='http://example.com/main-script-d1.js' id='main-script-d1-js' defer data-wp-strategy='defer'></script>\n";
+ $this->assertStringContainsString( $expected, $output, 'Expected defer, as there is no dependent or dependency' );
+ }
+
+ /**
+ * Tests that a script registered with defer remains deferred when all dependencies are either deferred or blocking.
+ *
+ * @ticket 12009
+ *
+ * @covers WP_Scripts::do_item
+ * @covers WP_Scripts::get_eligible_loading_strategy
+ * @covers ::wp_enqueue_script
+ */
+ public function test_loading_strategy_with_defer_dependent_and_varied_dependencies() {
+ wp_enqueue_script( 'dependency-script-d2-1', 'http://example.com/dependency-script-d2-1.js', array(), null, array( 'strategy' => 'defer' ) );
+ wp_enqueue_script( 'dependency-script-d2-2', 'http://example.com/dependency-script-d2-2.js', array(), null );
+ wp_enqueue_script( 'dependency-script-d2-3', 'http://example.com/dependency-script-d2-3.js', array( 'dependency-script-d2-2' ), null, array( 'strategy' => 'defer' ) );
+ wp_enqueue_script( 'main-script-d2', 'http://example.com/main-script-d2.js', array( 'dependency-script-d2-1', 'dependency-script-d2-3' ), null, array( 'strategy' => 'defer' ) );
+ $output = get_echo( 'wp_print_scripts' );
+ $expected = "<script type='text/javascript' src='http://example.com/main-script-d2.js' id='main-script-d2-js' defer data-wp-strategy='defer'></script>\n";
+ $this->assertStringContainsString( $expected, $output, 'Expected defer, as all dependencies are either deferred or blocking' );
+ }
+
+ /**
+ * Tests that scripts registered with defer remain deferred when all dependents are also deferred.
+ *
+ * @ticket 12009
+ *
+ * @covers WP_Scripts::do_item
+ * @covers WP_Scripts::get_eligible_loading_strategy
+ * @covers ::wp_enqueue_script
+ */
+ public function test_loading_strategy_with_all_defer_dependencies() {
+ wp_enqueue_script( 'main-script-d3', 'http://example.com/main-script-d3.js', array(), null, array( 'strategy' => 'defer' ) );
+ wp_enqueue_script( 'dependent-script-d3-1', 'http://example.com/dependent-script-d3-1.js', array( 'main-script-d3' ), null, array( 'strategy' => 'defer' ) );
+ wp_enqueue_script( 'dependent-script-d3-2', 'http://example.com/dependent-script-d3-2.js', array( 'dependent-script-d3-1' ), null, array( 'strategy' => 'defer' ) );
+ wp_enqueue_script( 'dependent-script-d3-3', 'http://example.com/dependent-script-d3-3.js', array( 'dependent-script-d3-2' ), null, array( 'strategy' => 'defer' ) );
+ $output = get_echo( 'wp_print_scripts' );
+ $expected = "<script type='text/javascript' src='http://example.com/main-script-d3.js' id='main-script-d3-js' defer data-wp-strategy='defer'></script>\n";
+ $this->assertStringContainsString( $expected, $output, 'Expected defer, as all dependents have defer loading strategy' );
+ }
+
+ /**
+ * Tests that dependents that are async but attached to a deferred main script, print with defer as opposed to async.
+ *
+ * @ticket 12009
+ *
+ * @covers WP_Scripts::do_item
+ * @covers WP_Scripts::get_eligible_loading_strategy
+ * @covers ::wp_enqueue_script
+ */
+ public function test_defer_with_async_dependent() {
+ // case with one async dependent.
+ wp_enqueue_script( 'main-script-d4', '/main-script-d4.js', array(), null, array( 'strategy' => 'defer' ) );
+ wp_enqueue_script( 'dependent-script-d4-1', '/dependent-script-d4-1.js', array( 'main-script-d4' ), null, array( 'strategy' => 'defer' ) );
+ wp_enqueue_script( 'dependent-script-d4-2', '/dependent-script-d4-2.js', array( 'dependent-script-d4-1' ), null, array( 'strategy' => 'async' ) );
+ wp_enqueue_script( 'dependent-script-d4-3', '/dependent-script-d4-3.js', array( 'dependent-script-d4-2' ), null, array( 'strategy' => 'defer' ) );
+ $output = get_echo( 'wp_print_scripts' );
+ $expected = "<script type='text/javascript' src='/main-script-d4.js' id='main-script-d4-js' defer data-wp-strategy='defer'></script>\n";
+ $expected .= "<script type='text/javascript' src='/dependent-script-d4-1.js' id='dependent-script-d4-1-js' defer data-wp-strategy='defer'></script>\n";
+ $expected .= "<script type='text/javascript' src='/dependent-script-d4-2.js' id='dependent-script-d4-2-js' defer data-wp-strategy='async'></script>\n";
+ $expected .= "<script type='text/javascript' src='/dependent-script-d4-3.js' id='dependent-script-d4-3-js' defer data-wp-strategy='defer'></script>\n";
+
+ $this->assertSame( $expected, $output, 'Scripts registered as defer but that have dependents that are async are expected to have said dependents deferred.' );
+ }
+
+ /**
+ * Tests that scripts registered as defer become blocking when their dependents chain are all blocking.
+ *
+ * @ticket 12009
+ *
+ * @covers WP_Scripts::do_item
+ * @covers WP_Scripts::get_eligible_loading_strategy
+ * @covers WP_Scripts::filter_eligible_strategies
+ * @covers ::wp_enqueue_script
+ */
+ public function test_loading_strategy_with_invalid_defer_registration() {
+ // Main script is defer and all dependent are not defer. Then main script will have blocking(or no) strategy.
+ wp_enqueue_script( 'main-script-d4', '/main-script-d4.js', array(), null, array( 'strategy' => 'defer' ) );
+ wp_enqueue_script( 'dependent-script-d4-1', '/dependent-script-d4-1.js', array( 'main-script-d4' ), null, array( 'strategy' => 'defer' ) );
+ wp_enqueue_script( 'dependent-script-d4-2', '/dependent-script-d4-2.js', array( 'dependent-script-d4-1' ), null );
+ wp_enqueue_script( 'dependent-script-d4-3', '/dependent-script-d4-3.js', array( 'dependent-script-d4-2' ), null, array( 'strategy' => 'defer' ) );
+ $output = get_echo( 'wp_print_scripts' );
+ $expected = "<script type='text/javascript' src='/main-script-d4.js' id='main-script-d4-js' data-wp-strategy='defer'></script>\n";
+ $this->assertStringContainsString( $expected, $output, 'Scripts registered as defer but that have all dependents with no strategy, should become blocking (no strategy).' );
+ }
+
+ /**
+ * Tests that scripts registered as default/blocking remain as such when they have no dependencies.
+ *
+ * @ticket 12009
+ *
+ * @covers WP_Scripts::do_item
+ * @covers WP_Scripts::get_eligible_loading_strategy
+ * @covers WP_Scripts::filter_eligible_strategies
+ * @covers ::wp_enqueue_script
+ */
+ public function test_loading_strategy_with_valid_blocking_registration() {
+ wp_enqueue_script( 'main-script-b1', '/main-script-b1.js', array(), null );
+ $output = get_echo( 'wp_print_scripts' );
+ $expected = "<script type='text/javascript' src='/main-script-b1.js' id='main-script-b1-js'></script>\n";
+ $this->assertSame( $expected, $output, 'Scripts registered with a "blocking" strategy, and who have no dependencies, should have no loading strategy attributes printed.' );
+
+ // strategy args not set.
+ wp_enqueue_script( 'main-script-b2', '/main-script-b2.js', array(), null, array() );
+ $output = get_echo( 'wp_print_scripts' );
+ $expected = "<script type='text/javascript' src='/main-script-b2.js' id='main-script-b2-js'></script>\n";
+ $this->assertSame( $expected, $output, 'Scripts registered with no strategy assigned, and who have no dependencies, should have no loading strategy attributes printed.' );
+ }
+
+ /**
+ * Tests that scripts registered for the head do indeed end up there.
+ *
+ * @ticket 12009
+ *
+ * @covers WP_Scripts::do_item
+ * @covers ::wp_enqueue_script
+ * @covers ::wp_register_script
+ */
+ public function test_scripts_targeting_head() {
+ wp_register_script( 'header-old', '/header-old.js', array(), null, false );
+ wp_register_script( 'header-new', '/header-new.js', array( 'header-old' ), null, array( 'in_footer' => false ) );
+ wp_enqueue_script( 'enqueue-header-old', '/enqueue-header-old.js', array( 'header-new' ), null, false );
+ wp_enqueue_script( 'enqueue-header-new', '/enqueue-header-new.js', array( 'enqueue-header-old' ), null, array( 'in_footer' => false ) );
+
+ $actual_header = get_echo( 'wp_print_head_scripts' );
+ $actual_footer = get_echo( 'wp_print_scripts' );
+
+ $expected_header = "<script type='text/javascript' src='/header-old.js' id='header-old-js'></script>\n";
+ $expected_header .= "<script type='text/javascript' src='/header-new.js' id='header-new-js'></script>\n";
+ $expected_header .= "<script type='text/javascript' src='/enqueue-header-old.js' id='enqueue-header-old-js'></script>\n";
+ $expected_header .= "<script type='text/javascript' src='/enqueue-header-new.js' id='enqueue-header-new-js'></script>\n";
+
+ $this->assertSame( $expected_header, $actual_header, 'Scripts registered/enqueued using the older $in_footer parameter or the newer $args parameter should have the same outcome.' );
+ $this->assertEmpty( $actual_footer, 'Expected footer to be empty since all scripts were for head.' );
+ }
+
+ /**
+ * Test that scripts registered for the footer do indeed end up there.
+ *
+ * @ticket 12009
+ *
+ * @covers WP_Scripts::do_item
+ * @covers ::wp_enqueue_script
+ * @covers ::wp_register_script
+ */
+ public function test_scripts_targeting_footer() {
+ wp_register_script( 'footer-old', '/footer-old.js', array(), null, true );
+ wp_register_script( 'footer-new', '/footer-new.js', array( 'footer-old' ), null, array( 'in_footer' => true ) );
+ wp_enqueue_script( 'enqueue-footer-old', '/enqueue-footer-old.js', array( 'footer-new' ), null, true );
+ wp_enqueue_script( 'enqueue-footer-new', '/enqueue-footer-new.js', array( 'enqueue-footer-old' ), null, array( 'in_footer' => true ) );
+
+ $actual_header = get_echo( 'wp_print_head_scripts' );
+ $actual_footer = get_echo( 'wp_print_scripts' );
+
+ $expected_footer = "<script type='text/javascript' src='/footer-old.js' id='footer-old-js'></script>\n";
+ $expected_footer .= "<script type='text/javascript' src='/footer-new.js' id='footer-new-js'></script>\n";
+ $expected_footer .= "<script type='text/javascript' src='/enqueue-footer-old.js' id='enqueue-footer-old-js'></script>\n";
+ $expected_footer .= "<script type='text/javascript' src='/enqueue-footer-new.js' id='enqueue-footer-new-js'></script>\n";
+
+ $this->assertEmpty( $actual_header, 'Expected header to be empty since all scripts targeted footer.' );
+ $this->assertSame( $expected_footer, $actual_footer, 'Scripts registered/enqueued using the older $in_footer parameter or the newer $args parameter should have the same outcome.' );
+ }
+
+ /**
+ * Data provider for test_setting_in_footer_and_strategy.
+ *
+ * @return array[]
+ */
+ public function get_data_for_test_setting_in_footer_and_strategy() {
+ return array(
+ // Passing in_footer and strategy via args array.
+ 'async_footer_in_args_array' => array(
+ 'set_up' => static function ( $handle ) {
+ $args = array(
+ 'in_footer' => true,
+ 'strategy' => 'async',
+ );
+ wp_enqueue_script( $handle, '/footer-async.js', array(), null, $args );
+ },
+ 'group' => 1,
+ 'strategy' => 'async',
+ ),
+
+ // Passing in_footer=true but no strategy.
+ 'blocking_footer_in_args_array' => array(
+ 'set_up' => static function ( $handle ) {
+ wp_register_script( $handle, '/defaults.js', array(), null, array( 'in_footer' => true ) );
+ },
+ 'group' => 1,
+ 'strategy' => false,
+ ),
+
+ // Passing async strategy in script args array.
+ 'async_in_args_array' => array(
+ 'set_up' => static function ( $handle ) {
+ wp_register_script( $handle, '/defaults.js', array(), null, array( 'strategy' => 'async' ) );
+ },
+ 'group' => false,
+ 'strategy' => 'async',
+ ),
+
+ // Passing empty array as 5th arg.
+ 'empty_args_array' => array(
+ 'set_up' => static function ( $handle ) {
+ wp_register_script( $handle, '/defaults.js', array(), null, array() );
+ },
+ 'group' => false,
+ 'strategy' => false,
+ ),
+
+ // Passing no value as 5th arg.
+ 'undefined_args_param' => array(
+ 'set_up' => static function ( $handle ) {
+ wp_register_script( $handle, '/defaults.js', array(), null );
+ },
+ 'group' => false,
+ 'strategy' => false,
+ ),
+
+ // Test backward compatibility, passing $in_footer=true as 5th arg.
+ 'passing_bool_as_args_param' => array(
+ 'set_up' => static function ( $handle ) {
+ wp_enqueue_script( $handle, '/footer-async.js', array(), null, true );
+ },
+ 'group' => 1,
+ 'strategy' => false,
+ ),
+
+ // Test backward compatibility, passing $in_footer=true as 5th arg and setting strategy via wp_script_add_data().
+ 'bool_as_args_and_add_data' => array(
+ 'set_up' => static function ( $handle ) {
+ wp_register_script( $handle, '/footer-async.js', array(), null, true );
+ wp_script_add_data( $handle, 'strategy', 'defer' );
+ },
+ 'group' => 1,
+ 'strategy' => 'defer',
+ ),
+ );
+ }
+
+ /**
+ * Tests that scripts print in the correct group (head/footer) when using in_footer and assigning a strategy.
+ *
+ * @ticket 12009
+ *
+ * @covers ::wp_register_script
+ * @covers ::wp_enqueue_script
+ * @covers ::wp_script_add_data
+ *
+ * @dataProvider get_data_for_test_setting_in_footer_and_strategy
+ *
+ * @param callable $set_up Set up.
+ * @param int|false $expected_group Expected group.
+ * @param string|false $expected_strategy Expected strategy.
+ */
+ public function test_setting_in_footer_and_strategy( $set_up, $expected_group, $expected_strategy ) {
+ $handle = 'foo';
+ $set_up( $handle );
+ $this->assertSame( $expected_group, wp_scripts()->get_data( $handle, 'group' ) );
+ $this->assertSame( $expected_strategy, wp_scripts()->get_data( $handle, 'strategy' ) );
+ }
+
+ /**
+ * Tests that scripts print with no strategy when an incorrect strategy is passed during wp_register_script.
+ *
+ * For an invalid strategy defined during script registration, default to a blocking strategy.
+ *
+ * @ticket 12009
+ *
+ * @covers WP_Scripts::add_data
+ * @covers ::wp_register_script
+ * @covers ::wp_enqueue_script
+ *
+ * @expectedIncorrectUsage WP_Scripts::add_data
+ */
+ public function test_script_strategy_doing_it_wrong_via_register() {
+ wp_register_script( 'invalid-strategy', '/defaults.js', array(), null, array( 'strategy' => 'random-strategy' ) );
+ wp_enqueue_script( 'invalid-strategy' );
+
+ $this->assertSame(
+ "<script type='text/javascript' src='/defaults.js' id='invalid-strategy-js'></script>\n",
+ get_echo( 'wp_print_scripts' )
+ );
+ }
+
+ /**
+ * Tests that scripts print with no strategy when an incorrect strategy is passed via wp_script_add_data().
+ *
+ * For an invalid strategy defined during script registration, default to a blocking strategy.
+ *
+ * @ticket 12009
+ *
+ * @covers WP_Scripts::add_data
+ * @covers ::wp_script_add_data
+ * @covers ::wp_register_script
+ * @covers ::wp_enqueue_script
+ *
+ * @expectedIncorrectUsage WP_Scripts::add_data
+ */
+ public function test_script_strategy_doing_it_wrong_via_add_data() {
+ wp_register_script( 'invalid-strategy', '/defaults.js', array(), null );
+ wp_script_add_data( 'invalid-strategy', 'strategy', 'random-strategy' );
+ wp_enqueue_script( 'invalid-strategy' );
+
+ $this->assertSame(
+ "<script type='text/javascript' src='/defaults.js' id='invalid-strategy-js'></script>\n",
+ get_echo( 'wp_print_scripts' )
+ );
+ }
+
+ /**
+ * Tests that scripts print with no strategy when an incorrect strategy is passed during wp_enqueue_script.
+ *
+ * For an invalid strategy defined during script registration, default to a blocking strategy.
+ *
+ * @ticket 12009
+ *
+ * @covers WP_Scripts::add_data
+ * @covers ::wp_enqueue_script
+ *
+ * @expectedIncorrectUsage WP_Scripts::add_data
+ */
+ public function test_script_strategy_doing_it_wrong_via_enqueue() {
+ wp_enqueue_script( 'invalid-strategy', '/defaults.js', array(), null, array( 'strategy' => 'random-strategy' ) );
+
+ $this->assertSame(
+ "<script type='text/javascript' src='/defaults.js' id='invalid-strategy-js'></script>\n",
+ get_echo( 'wp_print_scripts' )
+ );
+ }
+
+ /**
+ * Tests that scripts registered with a deferred strategy are not included in the script concat loading query.
+ *
+ * @ticket 12009
+ *
+ * @covers WP_Scripts::do_item
+ * @covers ::wp_enqueue_script
+ * @covers ::wp_register_script
+ */
+ public function test_concatenate_with_defer_strategy() {
+ global $wp_scripts, $concatenate_scripts, $wp_version;
+
+ $old_value = $concatenate_scripts;
+ $concatenate_scripts = true;
+
+ $wp_scripts->do_concat = true;
+ $wp_scripts->default_dirs = array( $this->default_scripts_dir );
+
+ wp_register_script( 'one-concat-dep', $this->default_scripts_dir . 'script.js' );
+ wp_register_script( 'two-concat-dep', $this->default_scripts_dir . 'script.js' );
+ wp_register_script( 'three-concat-dep', $this->default_scripts_dir . 'script.js' );
+ wp_enqueue_script( 'main-defer-script', '/main-script.js', array( 'one-concat-dep', 'two-concat-dep', 'three-concat-dep' ), null, array( 'strategy' => 'defer' ) );
+
+ wp_print_scripts();
+ $print_scripts = get_echo( '_print_scripts' );
+
+ // Reset global before asserting.
+ $concatenate_scripts = $old_value;
+
+ $expected = "<script type='text/javascript' src='/wp-admin/load-scripts.php?c=0&load%5Bchunk_0%5D=one-concat-dep,two-concat-dep,three-concat-dep&ver={$wp_version}'></script>\n";
+ $expected .= "<script type='text/javascript' src='/main-script.js' id='main-defer-script-js' defer data-wp-strategy='defer'></script>\n";
+
+ $this->assertSame( $expected, $print_scripts, 'Scripts are being incorrectly concatenated when a main script is registered with a "defer" loading strategy. Deferred scripts should not be part of the script concat loading query.' );
+ }
+
+ /**
+ * Test script concatenation with `async` main script.
+ *
+ * @ticket 12009
+ *
+ * @covers WP_Scripts::do_item
+ * @covers ::wp_enqueue_script
+ * @covers ::wp_register_script
+ */
+ public function test_concatenate_with_async_strategy() {
+ global $wp_scripts, $concatenate_scripts, $wp_version;
+
+ $old_value = $concatenate_scripts;
+ $concatenate_scripts = true;
+
+ $wp_scripts->do_concat = true;
+ $wp_scripts->default_dirs = array( $this->default_scripts_dir );
+
+ wp_enqueue_script( 'one-concat-dep-1', $this->default_scripts_dir . 'script.js' );
+ wp_enqueue_script( 'two-concat-dep-1', $this->default_scripts_dir . 'script.js' );
+ wp_enqueue_script( 'three-concat-dep-1', $this->default_scripts_dir . 'script.js' );
+ wp_enqueue_script( 'main-async-script-1', '/main-script.js', array(), null, array( 'strategy' => 'async' ) );
+
+ wp_print_scripts();
+ $print_scripts = get_echo( '_print_scripts' );
+
+ // Reset global before asserting.
+ $concatenate_scripts = $old_value;
+
+ $expected = "<script type='text/javascript' src='/wp-admin/load-scripts.php?c=0&load%5Bchunk_0%5D=one-concat-dep-1,two-concat-dep-1,three-concat-dep-1&ver={$wp_version}'></script>\n";
+ $expected .= "<script type='text/javascript' src='/main-script.js' id='main-async-script-1-js' async data-wp-strategy='async'></script>\n";
+
+ $this->assertSame( $expected, $print_scripts, 'Scripts are being incorrectly concatenated when a main script is registered with an "async" loading strategy. Async scripts should not be part of the script concat loading query.' );
+ }
+
+ /**
+ * Tests that script concatenation remains correct when a main script is registered as deferred after other blocking
+ * scripts are registered.
+ *
+ * @ticket 12009
+ *
+ * @covers WP_Scripts::do_item
+ * @covers ::wp_enqueue_script
+ * @covers ::wp_register_script
+ */
+ public function test_concatenate_with_blocking_script_before_and_after_script_with_defer_strategy() {
+ global $wp_scripts, $concatenate_scripts, $wp_version;
+
+ $old_value = $concatenate_scripts;
+ $concatenate_scripts = true;
+
+ $wp_scripts->do_concat = true;
+ $wp_scripts->default_dirs = array( $this->default_scripts_dir );
+
+ wp_enqueue_script( 'one-concat-dep-2', $this->default_scripts_dir . 'script.js' );
+ wp_enqueue_script( 'two-concat-dep-2', $this->default_scripts_dir . 'script.js' );
+ wp_enqueue_script( 'three-concat-dep-2', $this->default_scripts_dir . 'script.js' );
+ wp_enqueue_script( 'deferred-script-2', '/main-script.js', array(), null, array( 'strategy' => 'defer' ) );
+ wp_enqueue_script( 'four-concat-dep-2', $this->default_scripts_dir . 'script.js' );
+ wp_enqueue_script( 'five-concat-dep-2', $this->default_scripts_dir . 'script.js' );
+ wp_enqueue_script( 'six-concat-dep-2', $this->default_scripts_dir . 'script.js' );
+
+ wp_print_scripts();
+ $print_scripts = get_echo( '_print_scripts' );
+
+ // Reset global before asserting.
+ $concatenate_scripts = $old_value;
+
+ $expected = "<script type='text/javascript' src='/wp-admin/load-scripts.php?c=0&load%5Bchunk_0%5D=one-concat-dep-2,two-concat-dep-2,three-concat-dep-2,four-concat-dep-2,five-concat-dep-2,six-concat-dep-2&ver={$wp_version}'></script>\n";
+ $expected .= "<script type='text/javascript' src='/main-script.js' id='deferred-script-2-js' defer data-wp-strategy='defer'></script>\n";
+
+ $this->assertSame( $expected, $print_scripts, 'Scripts are being incorrectly concatenated when a main script is registered as deferred after other blocking scripts are registered. Deferred scripts should not be part of the script concat loader query string. ' );
+ }
+
+ /**
</ins><span class="cx" style="display: block; padding: 0 10px"> * @ticket 42804
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><span class="cx" style="display: block; padding: 0 10px"> public function test_wp_enqueue_script_with_html5_support_does_not_contain_type_attribute() {
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ global $wp_version;
</ins><span class="cx" style="display: block; padding: 0 10px"> add_theme_support( 'html5', array( 'script' ) );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> $GLOBALS['wp_scripts'] = new WP_Scripts();
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -74,8 +1419,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> wp_enqueue_script( 'empty-deps-no-version', 'example.com' );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $ver = get_bloginfo( 'version' );
- $expected = "<script src='http://example.com?ver=$ver' id='empty-deps-no-version-js'></script>\n";
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $expected = "<script src='http://example.com?ver={$wp_version}' id='empty-deps-no-version-js'></script>\n";
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> $this->assertSame( $expected, get_echo( 'wp_print_scripts' ) );
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -83,37 +1427,37 @@
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="cx" style="display: block; padding: 0 10px"> * Test the different protocol references in wp_enqueue_script
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * @ticket 16560
+ *
</ins><span class="cx" style="display: block; padding: 0 10px"> * @global WP_Scripts $wp_scripts
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * @ticket 16560
</del><span class="cx" style="display: block; padding: 0 10px"> */
</span><span class="cx" style="display: block; padding: 0 10px"> public function test_protocols() {
</span><span class="cx" style="display: block; padding: 0 10px"> // Init.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- global $wp_scripts;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ global $wp_scripts, $wp_version;
</ins><span class="cx" style="display: block; padding: 0 10px"> $base_url_backup = $wp_scripts->base_url;
</span><span class="cx" style="display: block; padding: 0 10px"> $wp_scripts->base_url = 'http://example.com/wordpress';
</span><span class="cx" style="display: block; padding: 0 10px"> $expected = '';
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $ver = get_bloginfo( 'version' );
</del><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> // Try with an HTTP reference.
</span><span class="cx" style="display: block; padding: 0 10px"> wp_enqueue_script( 'jquery-http', 'http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js' );
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $expected .= "<script type='text/javascript' src='http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js?ver=$ver' id='jquery-http-js'></script>\n";
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $expected .= "<script type='text/javascript' src='http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js?ver={$wp_version}' id='jquery-http-js'></script>\n";
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> // Try with an HTTPS reference.
</span><span class="cx" style="display: block; padding: 0 10px"> wp_enqueue_script( 'jquery-https', 'https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js' );
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $expected .= "<script type='text/javascript' src='https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js?ver=$ver' id='jquery-https-js'></script>\n";
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $expected .= "<script type='text/javascript' src='https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js?ver={$wp_version}' id='jquery-https-js'></script>\n";
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> // Try with an automatic protocol reference (//).
</span><span class="cx" style="display: block; padding: 0 10px"> wp_enqueue_script( 'jquery-doubleslash', '//ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js' );
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $expected .= "<script type='text/javascript' src='//ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js?ver=$ver' id='jquery-doubleslash-js'></script>\n";
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $expected .= "<script type='text/javascript' src='//ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js?ver={$wp_version}' id='jquery-doubleslash-js'></script>\n";
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> // Try with a local resource and an automatic protocol reference (//).
</span><span class="cx" style="display: block; padding: 0 10px"> $url = '//my_plugin/script.js';
</span><span class="cx" style="display: block; padding: 0 10px"> wp_enqueue_script( 'plugin-script', $url );
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $expected .= "<script type='text/javascript' src='$url?ver=$ver' id='plugin-script-js'></script>\n";
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $expected .= "<script type='text/javascript' src='$url?ver={$wp_version}' id='plugin-script-js'></script>\n";
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> // Try with a bad protocol.
</span><span class="cx" style="display: block; padding: 0 10px"> wp_enqueue_script( 'jquery-ftp', 'ftp://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js' );
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $expected .= "<script type='text/javascript' src='{$wp_scripts->base_url}ftp://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js?ver=$ver' id='jquery-ftp-js'></script>\n";
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $expected .= "<script type='text/javascript' src='{$wp_scripts->base_url}ftp://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js?ver={$wp_version}' id='jquery-ftp-js'></script>\n";
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> // Go!
</span><span class="cx" style="display: block; padding: 0 10px"> $this->assertSame( $expected, get_echo( 'wp_print_scripts' ) );
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -129,20 +1473,19 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * Test script concatenation.
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><span class="cx" style="display: block; padding: 0 10px"> public function test_script_concatenation() {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- global $wp_scripts;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ global $wp_scripts, $wp_version;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> $wp_scripts->do_concat = true;
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $wp_scripts->default_dirs = array( '/directory/' );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $wp_scripts->default_dirs = array( $this->default_scripts_dir );
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- wp_enqueue_script( 'one', '/directory/script.js' );
- wp_enqueue_script( 'two', '/directory/script.js' );
- wp_enqueue_script( 'three', '/directory/script.js' );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ wp_enqueue_script( 'one', $this->default_scripts_dir . 'script.js' );
+ wp_enqueue_script( 'two', $this->default_scripts_dir . 'script.js' );
+ wp_enqueue_script( 'three', $this->default_scripts_dir . 'script.js' );
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> wp_print_scripts();
</span><span class="cx" style="display: block; padding: 0 10px"> $print_scripts = get_echo( '_print_scripts' );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $ver = get_bloginfo( 'version' );
- $expected = "<script type='text/javascript' src='/wp-admin/load-scripts.php?c=0&load%5Bchunk_0%5D=one,two,three&ver={$ver}'></script>\n";
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $expected = "<script type='text/javascript' src='/wp-admin/load-scripts.php?c=0&load%5Bchunk_0%5D=one,two,three&ver={$wp_version}'></script>\n";
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> $this->assertSame( $expected, $print_scripts );
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -205,7 +1548,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- * Testing `wp_script_add_data` with an anvalid key.
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Testing `wp_script_add_data` with an invalid key.
</ins><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * @ticket 16024
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -333,8 +1676,8 @@
</span><span class="cx" style="display: block; padding: 0 10px"> $expected_header .= "<script type='text/javascript' src='/child-head.js' id='child-head-js'></script>\n";
</span><span class="cx" style="display: block; padding: 0 10px"> $expected_footer = "<script type='text/javascript' src='/parent.js' id='parent-js'></script>\n";
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $this->assertSame( $expected_header, $header );
- $this->assertSame( $expected_footer, $footer );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $this->assertSame( $expected_header, $header, 'Expected same header markup.' );
+ $this->assertSame( $expected_footer, $footer, 'Expected same footer markup.' );
</ins><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -354,8 +1697,8 @@
</span><span class="cx" style="display: block; padding: 0 10px"> $expected_footer = "<script type='text/javascript' src='/child-footer.js' id='child-footer-js'></script>\n";
</span><span class="cx" style="display: block; padding: 0 10px"> $expected_footer .= "<script type='text/javascript' src='/parent.js' id='parent-js'></script>\n";
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $this->assertSame( $expected_header, $header );
- $this->assertSame( $expected_footer, $footer );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $this->assertSame( $expected_header, $header, 'Expected same header markup.' );
+ $this->assertSame( $expected_footer, $footer, 'Expected same footer markup.' );
</ins><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -385,8 +1728,8 @@
</span><span class="cx" style="display: block; padding: 0 10px"> $expected_footer .= "<script type='text/javascript' src='/child2-footer.js' id='child2-footer-js'></script>\n";
</span><span class="cx" style="display: block; padding: 0 10px"> $expected_footer .= "<script type='text/javascript' src='/parent-footer.js' id='parent-footer-js'></script>\n";
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $this->assertSame( $expected_header, $header );
- $this->assertSame( $expected_footer, $footer );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $this->assertSame( $expected_header, $header, 'Expected same header markup.' );
+ $this->assertSame( $expected_footer, $footer, 'Expected same footer markup.' );
</ins><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -416,7 +1759,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> $expected = "<script type='text/javascript' id='test-example-js-before'>\nconsole.log(\"before\");\n</script>\n";
</span><span class="cx" style="display: block; padding: 0 10px"> $expected .= "<script type='text/javascript' src='http://example.com' id='test-example-js'></script>\n";
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $this->assertSame( $expected, get_echo( 'wp_print_scripts' ) );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $this->assertEqualMarkup( $expected, get_echo( 'wp_print_scripts' ) );
</ins><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -429,7 +1772,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> $expected = "<script type='text/javascript' src='http://example.com' id='test-example-js'></script>\n";
</span><span class="cx" style="display: block; padding: 0 10px"> $expected .= "<script type='text/javascript' id='test-example-js-after'>\nconsole.log(\"after\");\n</script>\n";
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $this->assertSame( $expected, get_echo( 'wp_print_scripts' ) );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $this->assertEqualMarkup( $expected, get_echo( 'wp_print_scripts' ) );
</ins><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -444,7 +1787,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> $expected .= "<script type='text/javascript' src='http://example.com' id='test-example-js'></script>\n";
</span><span class="cx" style="display: block; padding: 0 10px"> $expected .= "<script type='text/javascript' id='test-example-js-after'>\nconsole.log(\"after\");\n</script>\n";
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $this->assertSame( $expected, get_echo( 'wp_print_scripts' ) );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $this->assertEqualMarkup( $expected, get_echo( 'wp_print_scripts' ) );
</ins><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -457,7 +1800,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> $expected = "<script type='text/javascript' id='test-example-js-before'>\nconsole.log(\"before\");\n</script>\n";
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $this->assertSame( $expected, get_echo( 'wp_print_scripts' ) );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $this->assertEqualMarkup( $expected, get_echo( 'wp_print_scripts' ) );
</ins><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -470,7 +1813,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> $expected = "<script type='text/javascript' id='test-example-js-after'>\nconsole.log(\"after\");\n</script>\n";
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $this->assertSame( $expected, get_echo( 'wp_print_scripts' ) );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $this->assertEqualMarkup( $expected, get_echo( 'wp_print_scripts' ) );
</ins><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -485,7 +1828,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> $expected = "<script type='text/javascript' id='test-example-js-before'>\nconsole.log(\"before\");\n</script>\n";
</span><span class="cx" style="display: block; padding: 0 10px"> $expected .= "<script type='text/javascript' id='test-example-js-after'>\nconsole.log(\"after\");\n</script>\n";
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $this->assertSame( $expected, get_echo( 'wp_print_scripts' ) );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $this->assertEqualMarkup( $expected, get_echo( 'wp_print_scripts' ) );
</ins><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -502,7 +1845,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> $expected .= "<script type='text/javascript' src='http://example.com' id='test-example-js'></script>\n";
</span><span class="cx" style="display: block; padding: 0 10px"> $expected .= "<script type='text/javascript' id='test-example-js-after'>\nconsole.log(\"after\");\nconsole.log(\"after\");\n</script>\n";
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $this->assertSame( $expected, get_echo( 'wp_print_scripts' ) );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $this->assertEqualMarkup( $expected, get_echo( 'wp_print_scripts' ) );
</ins><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -519,7 +1862,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> $expected .= "<script type='text/javascript' src='http://example.com' id='test-example-js'></script>\n";
</span><span class="cx" style="display: block; padding: 0 10px"> $expected .= "<script type='text/javascript' id='test-example-js-after'>\nconsole.log(\"after\");\n</script>\n";
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $this->assertSame( $expected, get_echo( 'wp_print_scripts' ) );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $this->assertEqualMarkup( $expected, get_echo( 'wp_print_scripts' ) );
</ins><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -526,26 +1869,25 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * @ticket 14853
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><span class="cx" style="display: block; padding: 0 10px"> public function test_wp_add_inline_script_before_with_concat() {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- global $wp_scripts;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ global $wp_scripts, $wp_version;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> $wp_scripts->do_concat = true;
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $wp_scripts->default_dirs = array( '/directory/' );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $wp_scripts->default_dirs = array( $this->default_scripts_dir );
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- wp_enqueue_script( 'one', '/directory/one.js' );
- wp_enqueue_script( 'two', '/directory/two.js' );
- wp_enqueue_script( 'three', '/directory/three.js' );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ wp_enqueue_script( 'one', $this->default_scripts_dir . 'one.js' );
+ wp_enqueue_script( 'two', $this->default_scripts_dir . 'two.js' );
+ wp_enqueue_script( 'three', $this->default_scripts_dir . 'three.js' );
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> wp_add_inline_script( 'one', 'console.log("before one");', 'before' );
</span><span class="cx" style="display: block; padding: 0 10px"> wp_add_inline_script( 'two', 'console.log("before two");', 'before' );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $ver = get_bloginfo( 'version' );
</del><span class="cx" style="display: block; padding: 0 10px"> $expected = "<script type='text/javascript' id='one-js-before'>\nconsole.log(\"before one\");\n</script>\n";
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $expected .= "<script type='text/javascript' src='/directory/one.js?ver={$ver}' id='one-js'></script>\n";
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $expected .= "<script type='text/javascript' src='{$this->default_scripts_dir}one.js?ver={$wp_version}' id='one-js'></script>\n";
</ins><span class="cx" style="display: block; padding: 0 10px"> $expected .= "<script type='text/javascript' id='two-js-before'>\nconsole.log(\"before two\");\n</script>\n";
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $expected .= "<script type='text/javascript' src='/directory/two.js?ver={$ver}' id='two-js'></script>\n";
- $expected .= "<script type='text/javascript' src='/directory/three.js?ver={$ver}' id='three-js'></script>\n";
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $expected .= "<script type='text/javascript' src='{$this->default_scripts_dir}two.js?ver={$wp_version}' id='two-js'></script>\n";
+ $expected .= "<script type='text/javascript' src='{$this->default_scripts_dir}three.js?ver={$wp_version}' id='three-js'></script>\n";
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $this->assertSame( $expected, get_echo( 'wp_print_scripts' ) );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $this->assertEqualMarkup( $expected, get_echo( 'wp_print_scripts' ) );
</ins><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -552,24 +1894,23 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * @ticket 14853
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><span class="cx" style="display: block; padding: 0 10px"> public function test_wp_add_inline_script_before_with_concat2() {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- global $wp_scripts;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ global $wp_scripts, $wp_version;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> $wp_scripts->do_concat = true;
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $wp_scripts->default_dirs = array( '/directory/' );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $wp_scripts->default_dirs = array( $this->default_scripts_dir );
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- wp_enqueue_script( 'one', '/directory/one.js' );
- wp_enqueue_script( 'two', '/directory/two.js' );
- wp_enqueue_script( 'three', '/directory/three.js' );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ wp_enqueue_script( 'one', $this->default_scripts_dir . 'one.js' );
+ wp_enqueue_script( 'two', $this->default_scripts_dir . 'two.js' );
+ wp_enqueue_script( 'three', $this->default_scripts_dir . 'three.js' );
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> wp_add_inline_script( 'one', 'console.log("before one");', 'before' );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $ver = get_bloginfo( 'version' );
</del><span class="cx" style="display: block; padding: 0 10px"> $expected = "<script type='text/javascript' id='one-js-before'>\nconsole.log(\"before one\");\n</script>\n";
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $expected .= "<script type='text/javascript' src='/directory/one.js?ver={$ver}' id='one-js'></script>\n";
- $expected .= "<script type='text/javascript' src='/directory/two.js?ver={$ver}' id='two-js'></script>\n";
- $expected .= "<script type='text/javascript' src='/directory/three.js?ver={$ver}' id='three-js'></script>\n";
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $expected .= "<script type='text/javascript' src='{$this->default_scripts_dir}one.js?ver={$wp_version}' id='one-js'></script>\n";
+ $expected .= "<script type='text/javascript' src='{$this->default_scripts_dir}two.js?ver={$wp_version}' id='two-js'></script>\n";
+ $expected .= "<script type='text/javascript' src='{$this->default_scripts_dir}three.js?ver={$wp_version}' id='three-js'></script>\n";
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $this->assertSame( $expected, get_echo( 'wp_print_scripts' ) );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $this->assertEqualMarkup( $expected, get_echo( 'wp_print_scripts' ) );
</ins><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -576,28 +1917,27 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * @ticket 14853
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><span class="cx" style="display: block; padding: 0 10px"> public function test_wp_add_inline_script_after_with_concat() {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- global $wp_scripts;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ global $wp_scripts, $wp_version;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> $wp_scripts->do_concat = true;
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $wp_scripts->default_dirs = array( '/directory/' );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $wp_scripts->default_dirs = array( $this->default_scripts_dir );
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- wp_enqueue_script( 'one', '/directory/one.js' );
- wp_enqueue_script( 'two', '/directory/two.js' );
- wp_enqueue_script( 'three', '/directory/three.js' );
- wp_enqueue_script( 'four', '/directory/four.js' );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ wp_enqueue_script( 'one', $this->default_scripts_dir . 'one.js' );
+ wp_enqueue_script( 'two', $this->default_scripts_dir . 'two.js' );
+ wp_enqueue_script( 'three', $this->default_scripts_dir . 'three.js' );
+ wp_enqueue_script( 'four', $this->default_scripts_dir . 'four.js' );
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> wp_add_inline_script( 'two', 'console.log("after two");' );
</span><span class="cx" style="display: block; padding: 0 10px"> wp_add_inline_script( 'three', 'console.log("after three");' );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $ver = get_bloginfo( 'version' );
- $expected = "<script type='text/javascript' src='/wp-admin/load-scripts.php?c=0&load%5Bchunk_0%5D=one&ver={$ver}'></script>\n";
- $expected .= "<script type='text/javascript' src='/directory/two.js?ver={$ver}' id='two-js'></script>\n";
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $expected = "<script type='text/javascript' src='/wp-admin/load-scripts.php?c=0&load%5Bchunk_0%5D=one&ver={$wp_version}'></script>\n";
+ $expected .= "<script type='text/javascript' src='{$this->default_scripts_dir}two.js?ver={$wp_version}' id='two-js'></script>\n";
</ins><span class="cx" style="display: block; padding: 0 10px"> $expected .= "<script type='text/javascript' id='two-js-after'>\nconsole.log(\"after two\");\n</script>\n";
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $expected .= "<script type='text/javascript' src='/directory/three.js?ver={$ver}' id='three-js'></script>\n";
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $expected .= "<script type='text/javascript' src='{$this->default_scripts_dir}three.js?ver={$wp_version}' id='three-js'></script>\n";
</ins><span class="cx" style="display: block; padding: 0 10px"> $expected .= "<script type='text/javascript' id='three-js-after'>\nconsole.log(\"after three\");\n</script>\n";
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $expected .= "<script type='text/javascript' src='/directory/four.js?ver={$ver}' id='four-js'></script>\n";
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $expected .= "<script type='text/javascript' src='{$this->default_scripts_dir}four.js?ver={$wp_version}' id='four-js'></script>\n";
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $this->assertSame( $expected, get_echo( 'wp_print_scripts' ) );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $this->assertEqualMarkup( $expected, get_echo( 'wp_print_scripts' ) );
</ins><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -626,7 +1966,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> wp_script_add_data( 'test-example', 'conditional', 'gte IE 9' );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> $this->assertSame( $expected_localized, get_echo( 'wp_print_scripts' ) );
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $this->assertSame( $expected, $wp_scripts->print_html );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $this->assertEqualMarkup( $expected, $wp_scripts->print_html );
</ins><span class="cx" style="display: block; padding: 0 10px"> $this->assertTrue( $wp_scripts->do_concat );
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -634,7 +1974,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * @ticket 36392
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><span class="cx" style="display: block; padding: 0 10px"> public function test_wp_add_inline_script_after_with_concat_and_core_dependency() {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- global $wp_scripts;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ global $wp_scripts, $wp_version;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> wp_default_scripts( $wp_scripts );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -641,8 +1981,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> $wp_scripts->base_url = '';
</span><span class="cx" style="display: block; padding: 0 10px"> $wp_scripts->do_concat = true;
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $ver = get_bloginfo( 'version' );
- $expected = "<script type='text/javascript' src='/wp-admin/load-scripts.php?c=0&load%5Bchunk_0%5D=jquery-core,jquery-migrate&ver={$ver}'></script>\n";
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $expected = "<script type='text/javascript' src='/wp-admin/load-scripts.php?c=0&load%5Bchunk_0%5D=jquery-core,jquery-migrate&ver={$wp_version}'></script>\n";
</ins><span class="cx" style="display: block; padding: 0 10px"> $expected .= "<script type='text/javascript' src='http://example.com' id='test-example-js'></script>\n";
</span><span class="cx" style="display: block; padding: 0 10px"> $expected .= "<script type='text/javascript' id='test-example-js-after'>\nconsole.log(\"after\");\n</script>\n";
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -652,7 +1991,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> wp_print_scripts();
</span><span class="cx" style="display: block; padding: 0 10px"> $print_scripts = get_echo( '_print_scripts' );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $this->assertSame( $expected, $print_scripts );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $this->assertEqualMarkup( $expected, $print_scripts );
</ins><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -659,7 +1998,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * @ticket 36392
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><span class="cx" style="display: block; padding: 0 10px"> public function test_wp_add_inline_script_after_with_concat_and_conditional_and_core_dependency() {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- global $wp_scripts;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ global $wp_scripts, $wp_version;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> wp_default_scripts( $wp_scripts );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -666,8 +2005,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> $wp_scripts->base_url = '';
</span><span class="cx" style="display: block; padding: 0 10px"> $wp_scripts->do_concat = true;
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $ver = get_bloginfo( 'version' );
- $expected = "<script type='text/javascript' src='/wp-admin/load-scripts.php?c=0&load%5Bchunk_0%5D=jquery-core,jquery-migrate&ver={$ver}'></script>\n";
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $expected = "<script type='text/javascript' src='/wp-admin/load-scripts.php?c=0&load%5Bchunk_0%5D=jquery-core,jquery-migrate&ver={$wp_version}'></script>\n";
</ins><span class="cx" style="display: block; padding: 0 10px"> $expected .= "<!--[if gte IE 9]>\n";
</span><span class="cx" style="display: block; padding: 0 10px"> $expected .= "<script type='text/javascript' src='http://example.com' id='test-example-js'></script>\n";
</span><span class="cx" style="display: block; padding: 0 10px"> $expected .= "<script type='text/javascript' id='test-example-js-after'>\nconsole.log(\"after\");\n</script>\n";
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -680,7 +2018,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> wp_print_scripts();
</span><span class="cx" style="display: block; padding: 0 10px"> $print_scripts = get_echo( '_print_scripts' );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $this->assertSame( $expected, $print_scripts );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $this->assertEqualMarkup( $expected, $print_scripts );
</ins><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -687,7 +2025,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * @ticket 36392
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><span class="cx" style="display: block; padding: 0 10px"> public function test_wp_add_inline_script_before_with_concat_and_core_dependency() {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- global $wp_scripts;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ global $wp_scripts, $wp_version;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> wp_default_scripts( $wp_scripts );
</span><span class="cx" style="display: block; padding: 0 10px"> wp_default_packages( $wp_scripts );
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -695,8 +2033,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> $wp_scripts->base_url = '';
</span><span class="cx" style="display: block; padding: 0 10px"> $wp_scripts->do_concat = true;
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $ver = get_bloginfo( 'version' );
- $expected = "<script type='text/javascript' src='/wp-admin/load-scripts.php?c=0&load%5Bchunk_0%5D=jquery-core,jquery-migrate&ver={$ver}'></script>\n";
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $expected = "<script type='text/javascript' src='/wp-admin/load-scripts.php?c=0&load%5Bchunk_0%5D=jquery-core,jquery-migrate&ver={$wp_version}'></script>\n";
</ins><span class="cx" style="display: block; padding: 0 10px"> $expected .= "<script type='text/javascript' id='test-example-js-before'>\nconsole.log(\"before\");\n</script>\n";
</span><span class="cx" style="display: block; padding: 0 10px"> $expected .= "<script type='text/javascript' src='http://example.com' id='test-example-js'></script>\n";
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -706,7 +2043,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> wp_print_scripts();
</span><span class="cx" style="display: block; padding: 0 10px"> $print_scripts = get_echo( '_print_scripts' );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $this->assertSame( $expected, $print_scripts );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $this->assertEqualMarkup( $expected, $print_scripts );
</ins><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -713,7 +2050,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * @ticket 36392
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><span class="cx" style="display: block; padding: 0 10px"> public function test_wp_add_inline_script_before_after_concat_with_core_dependency() {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- global $wp_scripts;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ global $wp_scripts, $wp_version;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> wp_default_scripts( $wp_scripts );
</span><span class="cx" style="display: block; padding: 0 10px"> wp_default_packages( $wp_scripts );
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -721,9 +2058,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> $wp_scripts->base_url = '';
</span><span class="cx" style="display: block; padding: 0 10px"> $wp_scripts->do_concat = true;
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $ver = get_bloginfo( 'version' );
- $suffix = wp_scripts_get_suffix();
- $expected = "<script type='text/javascript' src='/wp-admin/load-scripts.php?c=0&load%5Bchunk_0%5D=jquery-core,jquery-migrate,wp-polyfill-inert,regenerator-runtime,wp-polyfill,wp-dom-ready,wp-hooks&ver={$ver}'></script>\n";
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $expected = "<script type='text/javascript' src='/wp-admin/load-scripts.php?c=0&load%5Bchunk_0%5D=jquery-core,jquery-migrate,wp-polyfill-inert,regenerator-runtime,wp-polyfill,wp-dom-ready,wp-hooks&ver={$wp_version}'></script>\n";
</ins><span class="cx" style="display: block; padding: 0 10px"> $expected .= "<script type='text/javascript' id='test-example-js-before'>\nconsole.log(\"before\");\n</script>\n";
</span><span class="cx" style="display: block; padding: 0 10px"> $expected .= "<script type='text/javascript' src='http://example.com' id='test-example-js'></script>\n";
</span><span class="cx" style="display: block; padding: 0 10px"> $expected .= "<script type='text/javascript' src='/wp-includes/js/dist/i18n.min.js' id='wp-i18n-js'></script>\n";
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -758,7 +2093,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> $print_scripts // Printed scripts.
</span><span class="cx" style="display: block; padding: 0 10px"> );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $this->assertSameIgnoreEOL( $expected, $print_scripts );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $this->assertEqualMarkup( $expected, $print_scripts );
</ins><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -790,7 +2125,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> $print_scripts = $this->getActualOutput();
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> $tail = substr( $print_scripts, strrpos( $print_scripts, "<script type='text/javascript' src='/customize-dependency.js' id='customize-dependency-js'>" ) );
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $this->assertSame( $expected_tail, $tail );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $this->assertEqualMarkup( $expected_tail, $tail );
</ins><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -797,7 +2132,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * @ticket 36392
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><span class="cx" style="display: block; padding: 0 10px"> public function test_wp_add_inline_script_after_for_core_scripts_with_concat_is_limited_and_falls_back_to_no_concat() {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- global $wp_scripts;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ global $wp_scripts, $wp_version;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> $wp_scripts->do_concat = true;
</span><span class="cx" style="display: block; padding: 0 10px"> $wp_scripts->default_dirs = array( '/wp-admin/js/', '/wp-includes/js/' ); // Default dirs as in wp-includes/script-loader.php.
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -808,14 +2143,13 @@
</span><span class="cx" style="display: block; padding: 0 10px"> wp_enqueue_script( 'three', '/wp-includes/js/script3.js' );
</span><span class="cx" style="display: block; padding: 0 10px"> wp_enqueue_script( 'four', '/wp-includes/js/script4.js' );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $ver = get_bloginfo( 'version' );
- $expected = "<script type='text/javascript' src='/wp-includes/js/script.js?ver={$ver}' id='one-js'></script>\n";
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $expected = "<script type='text/javascript' src='/wp-includes/js/script.js?ver={$wp_version}' id='one-js'></script>\n";
</ins><span class="cx" style="display: block; padding: 0 10px"> $expected .= "<script type='text/javascript' id='one-js-after'>\nconsole.log(\"after one\");\n</script>\n";
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $expected .= "<script type='text/javascript' src='/wp-includes/js/script2.js?ver={$ver}' id='two-js'></script>\n";
- $expected .= "<script type='text/javascript' src='/wp-includes/js/script3.js?ver={$ver}' id='three-js'></script>\n";
- $expected .= "<script type='text/javascript' src='/wp-includes/js/script4.js?ver={$ver}' id='four-js'></script>\n";
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $expected .= "<script type='text/javascript' src='/wp-includes/js/script2.js?ver={$wp_version}' id='two-js'></script>\n";
+ $expected .= "<script type='text/javascript' src='/wp-includes/js/script3.js?ver={$wp_version}' id='three-js'></script>\n";
+ $expected .= "<script type='text/javascript' src='/wp-includes/js/script4.js?ver={$wp_version}' id='four-js'></script>\n";
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $this->assertSame( $expected, get_echo( 'wp_print_scripts' ) );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $this->assertEqualMarkup( $expected, get_echo( 'wp_print_scripts' ) );
</ins><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -822,7 +2156,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * @ticket 36392
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><span class="cx" style="display: block; padding: 0 10px"> public function test_wp_add_inline_script_before_third_core_script_prints_two_concat_scripts() {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- global $wp_scripts;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ global $wp_scripts, $wp_version;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> $wp_scripts->do_concat = true;
</span><span class="cx" style="display: block; padding: 0 10px"> $wp_scripts->default_dirs = array( '/wp-admin/js/', '/wp-includes/js/' ); // Default dirs as in wp-includes/script-loader.php.
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -833,16 +2167,120 @@
</span><span class="cx" style="display: block; padding: 0 10px"> wp_add_inline_script( 'three', 'console.log("before three");', 'before' );
</span><span class="cx" style="display: block; padding: 0 10px"> wp_enqueue_script( 'four', '/wp-includes/js/script4.js' );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $ver = get_bloginfo( 'version' );
- $expected = "<script type='text/javascript' src='/wp-admin/load-scripts.php?c=0&load%5Bchunk_0%5D=one,two&ver={$ver}'></script>\n";
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $expected = "<script type='text/javascript' src='/wp-admin/load-scripts.php?c=0&load%5Bchunk_0%5D=one,two&ver={$wp_version}'></script>\n";
</ins><span class="cx" style="display: block; padding: 0 10px"> $expected .= "<script type='text/javascript' id='three-js-before'>\nconsole.log(\"before three\");\n</script>\n";
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $expected .= "<script type='text/javascript' src='/wp-includes/js/script3.js?ver={$ver}' id='three-js'></script>\n";
- $expected .= "<script type='text/javascript' src='/wp-includes/js/script4.js?ver={$ver}' id='four-js'></script>\n";
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $expected .= "<script type='text/javascript' src='/wp-includes/js/script3.js?ver={$wp_version}' id='three-js'></script>\n";
+ $expected .= "<script type='text/javascript' src='/wp-includes/js/script4.js?ver={$wp_version}' id='four-js'></script>\n";
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $this->assertSame( $expected, get_echo( 'wp_print_scripts' ) );
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $this->assertEqualMarkup( $expected, get_echo( 'wp_print_scripts' ) );
</ins><span class="cx" style="display: block; padding: 0 10px"> }
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ * Data provider to test get_inline_script_data and get_inline_script_tag.
+ *
+ * @return array[]
+ */
+ public function data_provider_to_test_get_inline_script() {
+ return array(
+ 'before-blocking' => array(
+ 'position' => 'before',
+ 'inline_scripts' => array(
+ '/*before foo 1*/',
+ ),
+ 'delayed' => false,
+ 'expected_data' => '/*before foo 1*/',
+ 'expected_tag' => "<script id='foo-js-before' type='text/javascript'>\n/*before foo 1*/\n</script>\n",
+ ),
+ 'after-blocking' => array(
+ 'position' => 'after',
+ 'inline_scripts' => array(
+ '/*after foo 1*/',
+ '/*after foo 2*/',
+ ),
+ 'delayed' => false,
+ 'expected_data' => "/*after foo 1*/\n/*after foo 2*/",
+ 'expected_tag' => "<script id='foo-js-after' type='text/javascript'>\n/*after foo 1*/\n/*after foo 2*/\n</script>\n",
+ ),
+ 'before-delayed' => array(
+ 'position' => 'before',
+ 'inline_scripts' => array(
+ '/*before foo 1*/',
+ ),
+ 'delayed' => true,
+ 'expected_data' => '/*before foo 1*/',
+ 'expected_tag' => "<script id='foo-js-before' type='text/javascript'>\n/*before foo 1*/\n</script>\n",
+ ),
+ 'after-delayed' => array(
+ 'position' => 'after',
+ 'inline_scripts' => array(
+ '/*after foo 1*/',
+ '/*after foo 2*/',
+ ),
+ 'delayed' => true,
+ 'expected_data' => "/*after foo 1*/\n/*after foo 2*/",
+ 'expected_tag' => "<script id='foo-js-after' type='text/javascript'>\n/*after foo 1*/\n/*after foo 2*/\n</script>\n",
+ ),
+ );
+ }
+
+ /**
+ * Test getting inline scripts.
+ *
+ * @covers WP_Scripts::get_inline_script_data
+ * @covers WP_Scripts::get_inline_script_tag
+ * @covers WP_Scripts::print_inline_script
+ *
+ * @expectedDeprecated WP_Scripts::print_inline_script
+ *
+ * @dataProvider data_provider_to_test_get_inline_script
+ *
+ * @param string $position Position.
+ * @param string[] $inline_scripts Inline scripts.
+ * @param bool $delayed Delayed.
+ * @param string $expected_data Expected data.
+ * @param string $expected_tag Expected tag.
+ */
+ public function test_get_inline_script( $position, $inline_scripts, $delayed, $expected_data, $expected_tag ) {
+ global $wp_scripts;
+
+ $deps = array();
+ if ( $delayed ) {
+ $wp_scripts->add( 'dep', 'https://example.com/dependency.js', array(), false ); // TODO: Cannot pass strategy to $args e.g. array( 'strategy' => 'defer' )
+ $wp_scripts->add_data( 'dep', 'strategy', 'defer' );
+ $deps[] = 'dep';
+ }
+
+ $handle = 'foo';
+ $wp_scripts->add( $handle, 'https://example.com/foo.js', $deps );
+ if ( $delayed ) {
+ $wp_scripts->add_data( $handle, 'strategy', 'defer' );
+ }
+
+ $this->assertSame( '', $wp_scripts->get_inline_script_data( $handle, $position ) );
+ $this->assertSame( '', $wp_scripts->get_inline_script_tag( $handle, $position ) );
+ $this->assertFalse( $wp_scripts->print_inline_script( $handle, $position, false ) );
+ ob_start();
+ $output = $wp_scripts->print_inline_script( $handle, $position, true );
+ $this->assertSame( '', ob_get_clean() );
+ $this->assertFalse( $output );
+
+ foreach ( $inline_scripts as $inline_script ) {
+ $wp_scripts->add_inline_script( $handle, $inline_script, $position );
+ }
+
+ $this->assertSame( $expected_data, $wp_scripts->get_inline_script_data( $handle, $position ) );
+ $this->assertSame( $expected_data, $wp_scripts->print_inline_script( $handle, $position, false ) );
+ $this->assertEqualMarkup(
+ $expected_tag,
+ $wp_scripts->get_inline_script_tag( $handle, $position )
+ );
+ ob_start();
+ $output = $wp_scripts->print_inline_script( $handle, $position, true );
+ $this->assertEqualMarkup( $expected_tag, ob_get_clean() );
+ $this->assertEquals( $expected_data, $output );
+ }
+
+ /**
</ins><span class="cx" style="display: block; padding: 0 10px"> * @ticket 45103
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><span class="cx" style="display: block; padding: 0 10px"> public function test_wp_set_script_translations() {
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1043,6 +2481,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * Testing `wp_enqueue_code_editor` with file path.
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * @ticket 41871
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ *
</ins><span class="cx" style="display: block; padding: 0 10px"> * @covers ::wp_enqueue_code_editor
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><span class="cx" style="display: block; padding: 0 10px"> public function test_wp_enqueue_code_editor_when_php_file_will_be_passed() {
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1130,6 +2569,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * Testing `wp_enqueue_code_editor` with `compact`.
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * @ticket 41871
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ *
</ins><span class="cx" style="display: block; padding: 0 10px"> * @covers ::wp_enqueue_code_editor
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><span class="cx" style="display: block; padding: 0 10px"> public function test_wp_enqueue_code_editor_when_generated_array_by_compact_will_be_passed() {
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1213,6 +2653,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * Testing `wp_enqueue_code_editor` with `array_merge`.
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * @ticket 41871
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ *
</ins><span class="cx" style="display: block; padding: 0 10px"> * @covers ::wp_enqueue_code_editor
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><span class="cx" style="display: block; padding: 0 10px"> public function test_wp_enqueue_code_editor_when_generated_array_by_array_merge_will_be_passed() {
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1310,6 +2751,7 @@
</span><span class="cx" style="display: block; padding: 0 10px"> * Testing `wp_enqueue_code_editor` with `array`.
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * @ticket 41871
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ *
</ins><span class="cx" style="display: block; padding: 0 10px"> * @covers ::wp_enqueue_code_editor
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><span class="cx" style="display: block; padding: 0 10px"> public function test_wp_enqueue_code_editor_when_simple_array_will_be_passed() {
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1402,6 +2844,7 @@
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="cx" style="display: block; padding: 0 10px"> * @ticket 52534
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ *
</ins><span class="cx" style="display: block; padding: 0 10px"> * @covers ::wp_localize_script
</span><span class="cx" style="display: block; padding: 0 10px"> *
</span><span class="cx" style="display: block; padding: 0 10px"> * @dataProvider data_wp_localize_script_data_formats
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1456,10 +2899,11 @@
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> /**
</span><span class="cx" style="display: block; padding: 0 10px"> * @ticket 55628
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ *
</ins><span class="cx" style="display: block; padding: 0 10px"> * @covers ::wp_set_script_translations
</span><span class="cx" style="display: block; padding: 0 10px"> */
</span><span class="cx" style="display: block; padding: 0 10px"> public function test_wp_external_wp_i18n_print_order() {
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- global $wp_scripts;
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ global $wp_scripts, $wp_version;
</ins><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> $wp_scripts->do_concat = true;
</span><span class="cx" style="display: block; padding: 0 10px"> $wp_scripts->default_dirs = array( '/default/' );
</span><span class="lines" style="display: block; padding: 0 10px; color: #888">@@ -1480,11 +2924,50 @@
</span><span class="cx" style="display: block; padding: 0 10px"> );
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> // The non-default script should end concatenation and maintain order.
</span><del style="background-color: #fdd; text-decoration:none; display:block; padding: 0 10px">- $ver = get_bloginfo( 'version' );
- $expected = "<script type='text/javascript' src='/wp-admin/load-scripts.php?c=0&load%5Bchunk_0%5D=jquery-core&ver={$ver}'></script>\n";
</del><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+ $expected = "<script type='text/javascript' src='/wp-admin/load-scripts.php?c=0&load%5Bchunk_0%5D=jquery-core&ver={$wp_version}'></script>\n";
</ins><span class="cx" style="display: block; padding: 0 10px"> $expected .= "<script type='text/javascript' src='/plugins/wp-i18n.js' id='wp-i18n-js'></script>\n";
</span><span class="cx" style="display: block; padding: 0 10px"> $expected .= "<script type='text/javascript' src='/default/common.js' id='common-js'></script>\n";
</span><span class="cx" style="display: block; padding: 0 10px">
</span><span class="cx" style="display: block; padding: 0 10px"> $this->assertSame( $expected, $print_scripts );
</span><span class="cx" style="display: block; padding: 0 10px"> }
</span><ins style="background-color: #dfd; text-decoration:none; display:block; padding: 0 10px">+
+ /**
+ * Parse an HTML markup fragment.
+ *
+ * @param string $markup Markup.
+ * @return DOMElement Body element wrapping supplied markup fragment.
+ */
+ protected function parse_markup_fragment( $markup ) {
+ $dom = new DOMDocument();
+ $dom->loadHTML(
+ "<!DOCTYPE html><html><head><meta charset=utf8></head><body>{$markup}</body></html>"
+ );
+
+ /** @var DOMElement $body */
+ $body = $dom->getElementsByTagName( 'body' )->item( 0 );
+
+ // Trim whitespace nodes added before/after which can be added when parsing.
+ foreach ( array( $body->firstChild, $body->lastChild ) as $node ) {
+ if ( $node instanceof DOMText && '' === trim( $node->data ) ) {
+ $body->removeChild( $node );
+ }
+ }
+
+ return $body;
+ }
+
+ /**
+ * Assert markup is equal.
+ *
+ * @param string $expected Expected markup.
+ * @param string $actual Actual markup.
+ * @param string $message Message.
+ */
+ protected function assertEqualMarkup( $expected, $actual, $message = '' ) {
+ $this->assertEquals(
+ $this->parse_markup_fragment( $expected ),
+ $this->parse_markup_fragment( $actual ),
+ $message
+ );
+ }
</ins><span class="cx" style="display: block; padding: 0 10px"> }
</span></span></pre>
</div>
</div>
</body>
</html>