Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Eliminate manual construction of script tags in WP_Scripts and pass other scripts through wp_print_inline_script_tag() #4773
Eliminate manual construction of script tags in WP_Scripts and pass other scripts through wp_print_inline_script_tag() #4773
Changes from 21 commits
0d3ae2d
86d74f0
61c877c
9ad9e6b
b52c335
8355a8c
b9ebf8b
d05efbe
3ac9a6e
adfef39
6ba21ef
c19f75d
50aafac
0e27a38
3b9b278
96b1e7a
96788c1
def2778
8bcd7a2
1194afe
205b8de
fd9028d
2db59e5
3ba5135
ecc29a9
832c315
3840c54
97ad256
File filter
Filter by extension
Conversations
Jump to
There are no files selected for viewing
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess this is out of scope for this PR, but looks like we could prevent some other corruption here by using
URLSearchParams
instead of string-searching the query of the URL. no need for DOM either.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah yes, this code dates back to a time before we could rely on
URL
orURLSearchParams
. I made a similar change recently towp-embed
(r56383). Probably should be put into a new defect.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Filed this in Core-59480
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
oops, we don't want to arbitrarily replace these tags. we know they exist at the front and back of the string, so by manually removing them we can avoid unintentional HTML syntax poisoning.
the
strlen
calls shouldn't add any overhead because that's stored in the string object, which here is a string literal, which we've already created in this patch inside the array.this change is both safer, deterministic, and more efficient, particularly in the worse-case, though given that we expect very short args here I would be surprised if it's a measurable impact. still, doing less is faster than doing more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great catch @dmsnell!
@westonruter IMO this is worth a quick follow up commit applying this throughout.
If we feel strongly about introducing a helper at this point, I wouldn't be opposed to that either. Though I think that should remain an
@access private
function if we add it.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Private helper function added in #5301
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
would it help to create a helper function for this specific task?
then these repetitive calls could be marginally nicer. even with the checks for the leading and trailing SCRIPT tags, this should still be faster than
str_replace()
, but more importantly, more secure and resilient against breaking syntax.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There's a syntax error in the
$has_both_empty_tags
condition. Could you fix and add comments explaining the conditions?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
sure; also just a note - all my examples are almost always wrong and are only meant to convey ideas. if you ever get the impulse, please never copy code of mine from a comment and paste it into a project. don't trust me 😄 I don't test these examples or vet them for WPCS' prefences.
Maybe it's best to return an empty string here if the syntax isn't a perfect match. Is this what you were asking for in "add comments explaining the conditions"?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks! I meant more the conditions for
$has_both_empty_tags
as I wasn't understanding exactly they were doing. But it seems that's because the logic wasn't quite right. Also seems worthwhile to normalize the prefix and suffix to upper case. So I believe the condition should actually be:It has both empty tags if:
$opener
, and$closer
When those conditions are satisfied, then
substr( $contents, strlen( $opener ), -strlen( $closer ) )
should be done.In testing, I see that the first line of the function should also be:
In regards to the comment comment before:
What do you think about actually just doing:
I'll note that this is actually the reverse of what
wp_add_inline_script()
does:wordpress-develop/src/wp-includes/functions.wp-scripts.php
Lines 133 to 145 in 6fa2ce4
Note also how it does the string replacement, so somewhat the naive approach which I originally committed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've implemented this in #5301
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Seems great. There's never a case to call this without the SCRIPT tags, so that makes sense to me. Make it visible as early as possible.
I have no strong opinion on this. Seems fine. The one thing is that
<sCRiPt>
is not exactly a string literal match, but that's fine. Whatever happens here I think it will work out, and if something goes awry, with the help of the_doing_it_wrong()
someone will figure it out quickly enough.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
PhpStorm flags the sprintf placeholder as a syntax error:
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is that why you added the
/** @lang JavaScript */
here? Is that standardized somehow? Asking since I haven't seen that before.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These are language injection comments. Supported by PhpStorm, at least: https://www.jetbrains.com/help/phpstorm/using-language-injections.html
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unless this is a standard, I think we should remove those annotations. We shouldn't change code to support arbitrary IDEs, unless this is something multiple independent tools use.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But I don't think it hurts, and I believe at least a majority of WP developers have used PhpStorm. Such annotations are also in #4824 by @spacedmonkey.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I get the reason for it, but I'm not sold on the justification to support an arbitrary IDE here. What if other IDEs also have a proprietary means for that that looks different? Would we add 2+ comments to those lines to satisfy all the IDEs? I don't think it's right for WP to "pick winners", which I think it does give preference to one by adding annotations that only that specific IDE benefits from.
It would be different if this was a standard pattern, but if it's not I'd prefer to remove it. I didn't spot it in #4824 before, but it applies there as well.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right, but I don't see this as being supporting an arbitrary IDE. If it's the most popular IDE for WP core development, it seems worthwhile.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Even if it's the most popular one, it's still arbitrary if there's no standard.
Maybe that is true, but we don't know that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Bard says it is 😄 https://g.co/bard/share/e9560a1c3ce5
Anyway, I'd like to get a second opinion.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've decided to move this into a new ticket: Core-59444
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
PhpStorm flags the sprintf placeholder as a syntax error:
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
presumably because of the
// language=JavaScript
comment, which shouldn't be there since this is still PHP?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same question here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These are language injection comments. Supported by PhpStorm, at least: https://www.jetbrains.com/help/phpstorm/using-language-injections.html
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
PhpStorm flags the placeholder as a syntax error:
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To ensure XML-compatibility, the
$javascript
string should have any instances of]]>
escaped. It's ugly, but apparently this is what has to be done:Nevertheless, it is likely exceedingly rare that a WordPress site is actually being served with
Content-Type: application/xhtml+xml
(true confessions, I used to do it, but the draconian XML parse error handling was painful). Still, it is unlikely for]]>
to occur in a script. I say this because if a site is being served asContent-Type: text/html
then the parser HTML parser will ignore theseCDATA
sections, and it could end up causing a parse error when the script is passed to the JS interpreter.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there any concern from adding this now in case the
$javascript
passed to this function is already wrapped with thatCDATA
markup? Very unlikely I assume, but we may want to add a check?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, good call. I've done this in ecc29a9. This shows that it is indeed necessary to do the escaping. Without the escaping, doing the following:
Results in the following output:
Pasting this into the W3C Validator as a fragment under the XHTML Strict doctype:
Results in an XML parse error:
However, when the escaping is present, the PHP outputs:
And this is valid:
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
something as bizarre as this could definitely use a link to an XML spec or the source of the reason why these have to be escaped. someone is going to look at that and "fix" it and "improve quality" by removing the escaping 🙃
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Even though there is a comment about the escaping?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yeah because it mentions that it should be compatible but not how or why.
like, how does this fix ensure compatibility?
when I saw it I immediately wondered what rule necessitates this or what breaks without it. I could imagine something like this, to see if I'm properly understanding the code.
yeah I know it's wordy and lengthy, but it was really confusing to me, and this code is now going to be responsible for general code generation, and may get a lot of eyes on it.
by the way it seems like this will not trigger if the HTTP
Content-type: text/html
is what serves the document. I could not uncover these failures without serving asContent-type: application/xhtml+xml
or by directly opening the file with a.xml
extension. The exact same file contents stored with.html
as its extension leads to HTML semantics, thus this doesn't effect it.Finally, and thankfully, it doesn't appear to be a security issue because Safari, Firefox, and Chrome all prevent escaping from the script using tricks like
</script>
. It will change those things into</script>
, but that leads to a JavaScript syntax error, or data corruption if it's found within a JS string.Including
<img>
was fun because that broke the entire page render. It became invalid XML. Again, if served as.html
or withContent-type: text/html
or anything but explicit out-of-band information that it's XML, none of these problem arise.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note: This needs to move up above the applying of the
wp_inline_script_attributes
filters so that the final$javascript
is available for computing a CSP hash.