From the fall out of bug 47457's resolution:

(bug 47457 comment #63 by Liangent)
> (bug 47457 comment #54 by Krinkle)
> > Change-Id: Ic3d0c937268d0943d2f770f3ca18bcf4e1eed346
> 
> This fix causes breakage of any user of site scripts which assume that
> they're
> loaded before $(document).ready(). Maybe someone can move jQuery.ready() call
> to a position just before </body> and after all other script references?

(bug 47457 comment #64 by matma.rex)
> And it also breaks the old 'mwCustomEditButtons' interface to add custom
> buttons to the old edit toolbar, which apparently everyone and their dog are
> using across the wikis. (Since the user JS is loaded from the bottom queue,
> but
> the toolbar script either from the top or using inline <script> tags with
> $.ready inside.)
> 
> Reopening. Moving the jQuery.ready() call after the bottom queue seems like a
> good idea.


(bug 47457 comment #66 by Brad Jorsch)
> (bug 47457 comment #63 by Liangent)
> > Maybe someone can move jQuery.ready() call to a position just before 
> > </body> and after all other script references?
> 
> (bug 47457 comment #64 by matma.rex)
> > Moving the jQuery.ready() call after the bottom queue seems like a good idea.
> 
> We tried that, see patchset 5 in https://gerrit.wikimedia.org/r/#/c/61057/5.
> It didn't work.
> 
> But unless the browsers were delaying the DOMContentLoaded event until after
> the async-loaded scripts in the bottom queue were loaded, I don't know how
> this wasn't already a problem. Krinkle, any ideas?

A few important questions I'd like answered:

@Liangent: Can you given an example where it matters for a user script whether the document becomes ready before or after they are loaded? The user scripts are loaded from the bottom of the <body> before </body>. Practically the document is already ready at this point, just $(document).ready() hasn't fired yet. Any user script code that isn't wrapped in $(document).ready() will still execute at exactly the same time. Any user script code that *is* wrapped in $(document).ready() will now execute immediately after loading instead of... immediately after loading. Exactly the same, not?

@Matma.rex: You mean the fact that the deprecated mwCustomEditButtons global (unlike the mw.toolbar interface) is inspected only once by mediawiki.action.edit.js, namely at the domready event. And if it is triggered before the user script, adding to that array will become a no-op.

Though there is a lot of usage of this feature, lets not forget the context:

* The mwCustomEditButtons interface is for the classic toolbar (aka "Monobook editor", though Vector users can also disable WikiEditor to get to it). This is already a large minority of users.
* The mwCustomEditButtons interace has been deprecated in favour of mw.toolbar.addButton, which I created especially for the legacy toolbar users last year to address the many declined bug reports for mwCustomEditButtons which could not be otherwise addressed because mwCustomEditButtons is beyond repair, it is a flawed concept and it keeps breaking for many reasons.

I don't think anything related to mwCustomEditButtons can justify a change of any kind unless it comes at absolutely no overhead and downside.

@Brad Jorsch: It seems that the Firefox bug with document.write being disabled before DOMContentReady is worse than we thought. It is disabled even before the end of the </body> has been reached. We found through trial-and-error that placing it after the main content but before the bottom queue worked.

As Brad pointed out, $.ready being triggered earlier makes no difference for the bottom queue because they are loaded asynchronously, they always execute without blocking the parser or the DOM ready event. In fact (while designing this) Roan and I made very sure to test this across the entire board of browsers we even remotely support (IE6-10, FF2-17, Chrome10-23, Opera9-11.x). And in any browser that we couldn't load it async, we scheduled the addScript to after dom-ready manually (only in Opera).

However note that the user scripts (like the site scripts) are *not* loaded through mw.loader because we still support legacy global scope for them. They are loaded by a hardcoded script tag in the DOM. Which means they are blocking and used to block dom-ready, and now they run after dom-ready (well, they still block dom-ready, but we trigger that callback queue earlier).

--------------------------
**Version**: 1.22.0
**Severity**: minor
**See Also**:
https://bugzilla.wikimedia.org/show_bug.cgi?id=50310