Page MenuHomePhabricator

Embeddable ResourceLoader modules (user.options, user.tokens) should be loaded in <head> for proper dependency resolution
Closed, ResolvedPublic

Description

user.tokens and user.options are inlined all the way at the bottom of the page. This is causing bugs when modules depend on user.tokens (which none do yet, which is kind of bad when you think about it), because the following happens:

  • loader resolves dependencies for foo
  • loader loads foo|user.tokens
  • mw.implement( 'user.tokens', ... ) is called
  • foo is loaded normally and can use mw.user.tokens
  • the inlined <script> tag call mw.implement( 'user.tokens', ... ) again, resulting in an exception

There is no good reason for user.tokens and user.options to be inlined at the /bottom/. We should inline them at the top, before the top-load queue.


Version: 1.17.x
Severity: normal

Details

Reference
bz30914

Event Timeline

bzimport raised the priority of this task from to Medium.Nov 21 2014, 11:57 PM
bzimport set Reference to bz30914.

yeah, that goes for any embedded module for that matter. Anything embedded in the html cannot be removed from the 'load queue' since it's stuck in the HTML, so it needs to be in the top of the document before the first loader.load.

One thing to keep in mind though is that user.tokens depends on 'mediawiki.user' (obviously).

We just need to verify that "mw.loader.implement('user.tokens')" doesn't do anything (i.e. it should not trigger an ajax request to get 'mediawiki.user', because 1) nobody asked for 'user.tokens', so no need to resolve dependencies, 2) because 'mediawiki.user' is expected to be in the next loader.load call

(In reply to comment #1)

yeah, that goes for any embedded module for that matter. Anything embedded in
the html cannot be removed from the 'load queue' since it's stuck in the HTML,
so it needs to be in the top of the document before the first loader.load.

Yup, that's right.

One thing to keep in mind though is that user.tokens depends on
'mediawiki.user' (obviously).

That's not a problem. If we load it inside an implement() call, normal dependency resolution will take care of this.

We just need to verify that "mw.loader.implement('user.tokens')" doesn't do
anything (i.e. it should not trigger an ajax request to get 'mediawiki.user',
because 1) nobody asked for 'user.tokens', so no need to resolve dependencies,

  1. because 'mediawiki.user' is expected to be in the next loader.load call

I'm not at all worried about that, that's fundamentally not what implement() does. implement() means "look here's the code for this new module, you may or may not be able to run it now depending on the status of its dependencies".

Okay, so no issues left to resolve.

Looks like first usage has come along. mw.Api module is using this as of r107350.

I'll go ahead and move those to the head and see what happens.