Page MenuHomePhabricator

Upgrade MW's version of jQuery from 3.4.x to 3.6.0
Closed, ResolvedPublic

Event Timeline

Krinkle triaged this task as Medium priority.Apr 13 2020, 3:07 PM
Krinkle moved this task from Inbox to Accepted Enhancement on the MediaWiki-ResourceLoader board.

Change 593370 had a related patch set uploaded (by Krinkle; owner: Jforrester):
[mediawiki/core@master] resources: Upgrade jQuery from 3.4.1 to 3.5.1

https://gerrit.wikimedia.org/r/593370

Assigning to Timo as it relies on his approval now.

Copied here from my Gerrit comments at https://gerrit.wikimedia.org/r/593370


The breaking change to parsing of <tag/> in $('') calls is something we'll need to re-enable with jQuery.UNSAFE_restoreLegacyHtmlPrefilter() from the migrate plugin.

We could then give it a dedicated deprecation track name (separate from the generic jq_deprecated) and drive towards fixing that "enough" and popularise it through Tech News and then remove shortly after.

Right now though I'm pretty sure there's plenty of gadgets and user scripts, and even some QUnit code in our own test suites, that depends on this.

In a nut shell:

$('<div/>')

… this will now parseHTML <div/> literally, instead doing the non-standard transformation to '<div></div>' and then parsing it. This is fine for a single-element call like this because the result is the same.

$('<div> <span/> <p/> <u/> </div>')

This was commonly used in our code base, and still is commony used in gadgets as a short-cut for creating a <div>, with three children: SPAN, P and UL. This also matches the way Web Components, React and Vue work.

However, common as it might be, a browser would normally process <span/> as identical to <span>, leaving it open. The concept of self-closing elements doesn't exist in HTML. What exists is that '/' is tolerated everywhere, and that some elements like <input>, <link>, and <br> are considered "void" (or not "openeable" in the first place), so anything that follows them is naturally always a sibling, not a child.

In jQuery 3.5.1 "security" fix this is broken, instead producing:

<div>
   <span>
     <p>
       <u></u>
     </p>
   </span>
  </div>

The reason upstream removed it is that their regex for doing that shortcut transformation could be fooled if you allow arbitrary user input in the HTML string, to do things even more dangerous than the HTML string would normally do. I'm not sure whether this applies to us given that any such input is either unescaped and totally a security issue regardless, or property escaped through mw.html.escape() or mw.message().escape(). Eitehr way the "security issue" seems likely a non-issue in our case.

I don't think we need to break gadgets doing this with any rush. The migrate plugin provides the old behaviour, but does so via opt-in by calling jQuery.UNSAFE_restoreLegacyHtmlPrefilter(), which I suggest we do as appendix to jquery-migrate.js or in a separate file concatenated to it.

I've tried to find examples with a hacky code search, but it's quite difficult to match with regular expressions. I did find a handful, such as:

$root.html( '<div/><div class="wikibase-toolbar-container"/><div class="wikibase-toolbar-container"/>' );

And one from Global Search (link), as example (many others):

'<span class="listing-span_1_of_2">' +
		'<span class="wikidata-update" />' +
		'<a href="javascript:" class="syncSelect" name="wd" title="' + ListingEditor.Config.TRANSLATIONS.selectAll + '"><h4>Wikidata</h4></a>' +
	'</span>' +

Here span.wikidata-update would wrap <a>, instead of be in front of it.

Change 593370 had a related patch set uploaded (by Krinkle; owner: Jforrester):
[mediawiki/core@master] resources: Upgrade jQuery from 3.4.1 to 3.5.1

https://gerrit.wikimedia.org/r/593370

Upstream is now at 3.6.0: https://blog.jquery.com/2021/03/02/jquery-3-6-0-released/

3.6.0 doesn't appear to have many significant changes. The main ones are an edge case about triggering focus from a focus listener, and how JSONP errors are handled.

Upstream is now at 3.6.0: https://blog.jquery.com/2021/03/02/jquery-3-6-0-released/

3.6.0 doesn't appear to have many significant changes. The main ones are an edge case about triggering focus from a focus listener, and how JSONP errors are handled.

I've updated the patch to v3.6.0.

Change 593371 had a related patch set uploaded (by Krinkle; author: Jforrester):

[mediawiki/core@master] resources: Upgrade jquery-migrate from 3.1.0 (patched) to 3.3.2 (patched)

https://gerrit.wikimedia.org/r/593371

Change 593371 had a related patch set uploaded (by Krinkle; author: Jforrester):

[mediawiki/core@master] resources: Upgrade jquery-migrate from 3.1.0 (patched) to 3.3.2 (patched)

https://gerrit.wikimedia.org/r/593371

To unblock the jquery upgrade as-is (for the benefit of regular bug fixes and any new features), we need to append a call to UNSAFE_restoreLegacyHtmlPrefilter() at the end of our migrate.js file, so as to enable that migration option by default (it is disabled by default, but provided by upstream of use cases like ours).

That would be a quick way to move forward here, post-poning the breaking change in the HTML prefilter for a later time.

To unblock the jquery upgrade as-is (for the benefit of regular bug fixes and any new features), we need to append a call to UNSAFE_restoreLegacyHtmlPrefilter() at the end of our migrate.js file, so as to enable that migration option by default (it is disabled by default, but provided by upstream of use cases like ours).

That would be a quick way to move forward here, post-poning the breaking change in the HTML prefilter for a later time.

Sounds good. Done.

I do note that the patches together result in a ~5kB overall increase in transfer cost (minified+gzipped).

[mediawiki/core@master] resources: Upgrade jQuery from 3.4.1 to 3.6.0
https://gerrit.wikimedia.org/r/593370

Fresnel report:

transfer:
Total size of transfers during page load |  393 kB |  394 kB | +1.7 kB |
Transfer size of HTML document           | 14.9 kB | 14.9 kB |    0 B  |
Transfer size of CSS resources           | 38.5 kB | 38.5 kB |    0 B  |
Transfer size of JavaScript resources    |  311 kB |  312 kB | +1.7 kB |

[mediawiki/core@master] resources: Upgrade jquery-migrate from 3.1.0 (patched) to 3.3.2 (patched)
https://gerrit.wikimedia.org/r/593371

Fresnel report:

transfer:
Total size of transfers during page load |  394 kB |  397 kB | +2.9 kB |
Transfer size of HTML document           | 14.9 kB | 14.9 kB |    0 B  |
Transfer size of CSS resources           | 38.5 kB | 38.5 kB |    0 B  |
Transfer size of JavaScript resources    |  312 kB |  315 kB | +2.9 kB |

I'll see what we can squeeze from the migrate side of things, since I'd rather not patch jquery.js for now (and has already been very-well golfed upstream).

See also: T280944: Phase out jQuery Migrate v3

Change 593370 merged by jenkins-bot:

[mediawiki/core@master] resources: Upgrade jQuery from 3.4.1 to 3.6.0

https://gerrit.wikimedia.org/r/593370

Change 593371 merged by jenkins-bot:

[mediawiki/core@master] resources: Upgrade jquery-migrate from 3.1.0 (patched) to 3.3.2 (patched)

https://gerrit.wikimedia.org/r/593371

Jdforrester-WMF renamed this task from Upgrade MW's version of jQuery from 3.4.x to 3.5.x to Upgrade MW's version of jQuery from 3.4.x to 3.6.0.Apr 23 2021, 5:12 AM
Jdforrester-WMF closed this task as Resolved.
Jdforrester-WMF claimed this task.

Change 682178 had a related patch set uploaded (by Jforrester; author: Jforrester):

[mediawiki/core@REL1_36] resources: Upgrade jQuery from 3.4.1 to 3.6.0

https://gerrit.wikimedia.org/r/682178

Change 682179 had a related patch set uploaded (by Jforrester; author: Jforrester):

[mediawiki/core@REL1_36] resources: Upgrade jquery-migrate from 3.1.0 (patched) to 3.3.2 (patched)

https://gerrit.wikimedia.org/r/682179

Change 682178 merged by jenkins-bot:

[mediawiki/core@REL1_36] resources: Upgrade jQuery from 3.4.1 to 3.6.0

https://gerrit.wikimedia.org/r/682178

Change 682179 merged by jenkins-bot:

[mediawiki/core@REL1_36] resources: Upgrade jquery-migrate from 3.1.0 (patched) to 3.3.2 (patched)

https://gerrit.wikimedia.org/r/682179

Change 735742 had a related patch set uploaded (by Reedy; author: Jforrester):

[mediawiki/core@REL1_35] resources: Upgrade jQuery from 3.4.1 to 3.6.0

https://gerrit.wikimedia.org/r/735742

Change 735743 had a related patch set uploaded (by Reedy; author: Jforrester):

[mediawiki/core@REL1_35] resources: Upgrade jquery-migrate from 3.1.0 (patched) to 3.3.2 (patched)

https://gerrit.wikimedia.org/r/735743

Patches cherry picked after questions on IRC.

From reading the thread briefly, with the jquery-migrate picked too, this shouldn't be a breaking change...

Ack. Confirmed it's the same patch as we applied to master and 1.36+, and apart from 1 patch that improved stat counting (change 682228), there were no patches to migrate.js between this backported change and its removal a few weeks ago.

Change 735742 merged by jenkins-bot:

[mediawiki/core@REL1_35] resources: Upgrade jQuery from 3.4.1 to 3.6.0

https://gerrit.wikimedia.org/r/735742

Change 735743 merged by jenkins-bot:

[mediawiki/core@REL1_35] resources: Upgrade jquery-migrate from 3.1.0 (patched) to 3.3.2 (patched)

https://gerrit.wikimedia.org/r/735743