Page MenuHomePhabricator

ResourceLoader: User scripts should not execute in global scope
Closed, DeclinedPublic


TLDR: drop support for executing page.js scripts in the global scope.

If a user uses something like

window.windowDotSomething = true;
justSomething = true;

to declare a few variables they will be global variables, and if the user uses

var varSomething = true;

in a ResourceLoader-enabled gadget or in their new global.js provided by the GlobalCssJs extension, this will create a local variable (they are inside of a mw.loader.implement wrapper). This is the expected behavior.


var varSomething = true;

results in a *global* variable if inserted in user subpages like [[Special:MyPage/common.js]] or [[MediaWiki:Common.js]]:



Using "var" should not create a global variable in any case, and users should not rely in the current behavior when writing their scripts, because this usually causes bugs when porting user scripts to gadgets, due to the need to replace lots of "var example"s with explicitly declared globals like "window.example".

See Also:



Event Timeline

bzimport raised the priority of this task from to Low.Nov 22 2014, 3:10 AM
bzimport set Reference to bz63728.
bzimport added a subscriber: Unknown Object (MLST).

This will break badly written user scripts and the users will blame us. :)
Doesn't mean that it shouldn't be done, but it probably should be part of
a larger cleanup action. Also related: bug 33836, bug 33837.

Indeed. If this is ever implemented, there should be more than one announcement in as many channels as possible or something like that, and giving users a good amount of time to (at least ask how to) fix any scripts they care about.

And MediaWiki could also get this implemented under a $wgWrapScripts flag which could be set to false on WMF initially but could be true for MediaWiki software (for which there are release notes).

Removing blocker of tracking bug 9968 as this has nothing to do with the phasing out of MediaWiki global variables (specifically PHP, but those of JS as well).

This bug doesn't relate to the exposure or support of global interfaces. It just relates to a script executing in the global scope and thus producing local variables as globals.

Re-filing as low priority enhancement because them executing in the global scope right now is that way for legacy reasons and very much intentional, not a bug.

matmarex set Security to None.
matmarex removed a subscriber: Unknown Object (MLST).

All modules in ResourceLoader have a local (or "private") scope the only exceptions are the "user" and "site" module scripts, which are the way that they are for compatibility reasons.

All other modules (including those that come from wiki pages), such as gadgets and GlobalCssJs scripts, have been granted private scope.

I'm declining this feature request because breaking compatibility by changing this behaviour would be disruptive to the technical community for little to no benefit. Introducing a way to opt-out or opt-in would needlessly complicate these systems for end users and also add additional maintenance cost to all other things we develop going forward.

As for what private scope enables (creating JavaScript variables without those being visible to, or overlapping with, variables from other user scripts), this can be trivially accomplished with a JavaScript closure which user and site scripts are already allowed to enable. This can be seen an "opt-in".

Thus, there is nothing fundamentally impossible or difficult by not having private scope.