[mediawiki.loader] fix numerous bugs and edge cases discovered with Roan on Etherpad/Skype
* 'undefined' state removed:
State 'undefined' has been removed. This was half-supported, probably with the intention to support loading of modules that are registered server side after the startup module was loaded (either because the server had a deployment while the user was browsing the page, or because loader.load calls in HTML document or loader.register where cached and out of sync. That's not unlikely to happen after deployment, after which there is a 5 minute window of cached startup modules in peoples browser cache but fresh HTML documents.
Instead of filling in the missing registry with no information, simply don't support this. Shouldn't break anything as it wasn't supported all the way.
* Document state 'missing'. Used by the load.php when a requested module doesn't exist according to the server.
* Fix recurse(). Previously it failed to recognize circular dependencies, because "unresolved" started as an empty array (given by resolve(). See also test cases at bottom of commitmsg.
* Fix recurse() even more. It was using inArray as a parameter to [].splice(), which is bad as inArray can be -1, in which case splice(-1,1) will remove the last item in the array, instead of the one at the index. Fortunately this was never exploited as 'unresolved=[]' is starting point, so nothing to delete.
* Fix resolve(). Don't return an empty array, which is contrary to it's (now documented) behavior of including the requested module in the return array. Instead letting recurse() handle it.
* Add magic filter to filter() named "unregistered" which will reduce the set to only module names that are not in the registry.
* Removing call to request() from the bottom bottom of mw.loader.implement. This can't be needed as before load.php is called the toes implement, all dependencies are put in queue and set to "loading" state, this queue is build first and then the load requests happen. At point implement is called, it's dependencies must already be in the queue. If any unloaded dependencies at moment of implementation (which is very common), the next implement will call execute which does handlePending, which will execute previously implemented modules that were waiting for dependencies to arrive.
* Make load() and using() no longer return meaningless booleans, they were undocumented and meaningless as they are either used as voids or with callbacks.
* Bring consistency in handling input. If direct input to a loader function is invalid or contains inexistent modules, throw an exception. Otherwise use error callback.
-- with one exception, that is the raw module list passed to mw.loader.load, those are not related to each other and should continue even if there is an inexistent module in there.
-- For example if a deployment occurs, adding an extension with modules loaded on a particular page. The user will have a startup module in cache up to 5 minutes that doesn't have this module's registry yet. In that case the new modules should simply be ignored. Before this commit they were also silently ignored, but not by skipping them. previously inexistent/undefined modules would give ok-callback of using() instantly, because filter(['ready'], modules) is the same as modules when it contains nothing.