Page MenuHomePhabricator

Execute MediaWiki:Group-*.js pages before user common.js pages
Closed, DeclinedPublic

Description

In ResourceLoaderUserModule, currently the execution order is:

  • user common.js page
  • user skin js page
  • MediaWiki:Group-*.js pages

I am proposing that the group-*.js pages be run earlier.

Usecases:

  • This allows customisations created by group js pages to be overridden in personal js.
  • Some wikis may want to create a shim or helper function around mw.loader.load in group-user.js to make it easier to load scripts. But as of now, any such function won't be available until after the user common.js has already executed.

Also, the ResourceLoaderSiteModule scripts (MW common.js and skin js), in practise, always appear to run before the user module scripts. So this change would make it consistent in that all site js is ran before user js.

Details

Event Timeline

Restricted Application added a subscriber: Aklapper. · View Herald Transcript

Change 734696 had a related patch set uploaded (by SD0001; author: SD0001):

[mediawiki/core@master] Execute MediaWiki:Group-*.js pages before user JS pages

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

This allows customisations created by group js pages to be overridden in personal js.

In my experience, when extensions or gadgets want to allow personal scripts to modify their behaviour, they use mw.loader.using( 'user' ).then( .. ), or declare a dependency on the user module, to ensure user customisations are loaded first. For example, HotCat and other gadgets read potential configuration changes from window.hotcat_* before initialising the user interface. VisualEditor processes its plugin registrations in a similar way.

This approach has the downside of being asynchronous, but the benefit is that it works between any two modules. Whether core, an extension, a gadget, or a user script, and as such is a commonly used method that can be applied anywhere. We generally prefer having a small number of mechanisms that work well, are easy to understand, and can be widely used, than to have many slightly different tailor-made ways for customisations to work that one would each need to learn about and remember (as well as additional maintenance, testing, and documentation cost for developers).

There are a number of different ways to read and/or merge confgurations, but here is a minimal way in which mw.loader.using can be used in plain JavaScript:

// myskin.js
window.hotcat_foo_enable = false;

// Gadget-thing.js
function init() {
  mw.loader.using( 'user' ).then( function () {
    if ( HotCat.config.foo && window.hotcat_foo_enable !== false ) {
      renderFoo();
    }
  } );
}

Another way, which might allow for easier integration and merging of data, would be to utilize mw.hook:

// myskin.js
mw.hook( 'hotcat.config' ).add( function ( config ) {
  config.foo = false;
} );

// Gadget-thing.js
function init() {
  mw.hook( 'hotcat.config' ).fire( HotCat.config );
  mw.loader.using( 'user' ).then( function () {
    if ( HotCat.config.foo ) {
      renderFoo();
    }
  } );
}

Some wikis may want to create a shim or helper function around mw.loader.load in group-user.js to make it easier to load scripts. But as of now, any such function won't be available until after the user common.js has already executed.

From what I have seen, such helpers are generally placed in MediaWiki:Common.js. I agree though, it would be interesting to move some of these to Group-user as a way to reduce their cost, if it can be assumed that they are only allowed to be used by personal scripts.

This would mean, however, that these helpers could not be used in gadgets, since gadgets may be enabled by default and thus be loaded by unregistered users as well. Is this a theoretical example, or is this a current request from a wiki community?

Also, as mentioned on the Gerrit patch, changing the order in this way is non-trivial as it constitutes a breaking change, and a rather tricky one as there is no natural way to deprecate this in a way that allows for migrating existing overrides in the other direction in a way that will keep working.

Do you have an idea for how we could maintain compatibility for, or allow a transition path, for wikis that have site scripts in Group-user.js that allow customisation from personal common.js/myskin.js currently by setting configuration settings ahead of time? This afaik the way that gadgets have historically supported customisations, and is likely relied upon. These customisations would stop working if we swap their order. We'd need to think of a way that users can change their personal scripts today, such that they work both today and after this change.

Krinkle triaged this task as Medium priority.
Krinkle moved this task from Inbox to Accepted Enhancement on the MediaWiki-ResourceLoader board.

In short:

In my experience, user customisations can be structured as coming first or as coming after. If the load order is user-first then you can't utilise the one that requires user-last. Likewise if the load order is user-last then you can't utilise the one that requires user-first. There isn't an obvious "better" way.

What I do find is that it can be quite difficult to support patterns where customisation comes later because this means the original script doesn't know what to wait for or how long to wait for or whether it will happen, which inherently limits what can be done. E.g. if you imagine an array of toolbar icons to display in a text editor, there is a point where that array is turned into a real interface. After that point, it cannot be modified in a meaningful way. This is why in our ecosystem, customisations tend to be loaded first, and then comes the original afterwards to make the decision and use it for something.

If an idea you have requires the group-script to load first, then this can be done today by providing a hook for the user script to subscribe to.

If we change the order, we can still do that, but we can no longer do the things we do today, so it seems what we do today offers more options.

I don't mind revisiting it, as it is a fairly small difference. If you still feel that something is harder or not possible unless this changes, let me know. I may have misunderstood the example, or I have have failed to explain properly how to make it work in an easy way.

Change 734696 abandoned by SD0001:

[mediawiki/core@master] Execute MediaWiki:Group-*.js pages before user JS pages

Reason:

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