This protected method was forgotten to be removed in MediaWiki 1.31,
when the public ResourceLoaderModule::getHashMtime() and ::getDefinitionMtime()
methods were removed (originally deprecated in MW 1.26).
Bug: T233059
Change-Id: Ia89d9b2fad99628e60063383a3f379db3fb49c47
Avoid use of wfTimestamp and wfDebugLog global functions.
Also simplify some of the error messages around processing of
'packageFiles' definitions and throw generic LogicException
instead of MWException.
Change-Id: I55ce1f107f53dfdfe673cbe4411b0a7c4e24b2ea
getDeprecationInformation without $context is deprecated since
commit 2fc229116d (I5341f18625209446a6d00).
Depends-On: Ifa1a3bb56b731b83864022a358916c6aca5d7c10
Change-Id: Idd4aba87c65101f9ec257a7ff745fe29ed19c7c9
It was mentioning what ResourceLoader needs to do with the method
internally (such as "call it from getVersionHash"), but that is
irrelevant to the developer implementing the method in sub classes.
Also update the rest and make it hopefully a bit easier to follow.
Change-Id: Idc73e344bb4ffc3f83e2efcd358ca34f98bc5443
This change allows to use the context in the functions.
The following internal static functions from ResourceLoader get now a
reference to the ResourceLoaderContext object:
* makeLoaderImplementScript
* makeLoaderStateScript
* makeLoaderRegisterScript
* makeLoaderSourcesScript
ResouceLoader::encodeJsonForScript is duplicated to
ResourceLoaderContext::encodeJson loading the debug mode from context.
ResourceLoader::encodeJsonForScript is kept for other usages without
context.
The debug mode is loaded from $context->getDebug() instead of from
ResourceLoader::inDebugMode(). This does not support to enable the debug
mode by setting the cookie 'resourceLoaderDebug' or the configuration
variable wgResourceLoaderDebug. Only the URL parameter debug=true
enables the debug mode. This should be sufficient for the subsequent
ResourceLoader requests. The tests don't need the global variable
wgResourceLoaderDebug anymore. The initial ResourceLoader context in
OutputPage still uses ResourceLoader::inDebugMode() with cookie and
global configuration variable.
This change adds the parameter $context with a ResourceLoaderContext
object to ResourceLoaderModule::getDeprecationInformation and deprecates
omitting the parameter. Ifa1a3bb56b731b83864022a358916c6aca5d7c10
updates this in extension ExtJSBase.
Bug: T229311
Change-Id: I5341f18625209446a6d006f60244990f65530319
* Add license header where missing.
* Add missing `@since` (1.17 for most classes), except
ResourceLoaderLessVarFileModule since 1.32 (1bc62c548c).
* Remove duplicate file-level description for class-only files,
merge with the class description instead.
* Remove my own `@author` annotation from one file.
* Mark core's own FileModule subclasses as `@internal`, except
for the following which we support use of in extensions:
ResourceLoaderLessVarFileModule,
ResourceLoaderOOUIIconPackModule, and
ResourceLoaderWikiModule.
Change-Id: I336af2e4ccdbe2512594e8861b72628d24194e41
Being a raw module means that when it is requested from load.php with
"only=scripts" set, then the output is *not* wrapped in an
'mw.loader.implement' closure *and* there no 'mw.loader.state()' appendix.
Instead, it is served "raw".
Before 2018, the modules 'mediawiki' and 'jquery' were raw modules.
They were needed before the client could define 'mw.loader.implement', and
could never be valid dependencies. Module 'mediawiki' merged to 'startup',
and 'jquery' became a regular module (T192623). Based on the architecture
of modules being deliverable bundles, it doesn't make sense for there to
ever be raw modules again. Anything that 'startup' needs should be bundled
with it. Anything else is a regular module.
On top of that, we never actually needed this feature because specifying
the 'only=scripts' and 'raw=1' parameters does the same thing.
The only special bit about marking modules (not requests) as "raw" was that
it allowed the client to forget to specify "raw=1" and the server would
automatically omit the 'mw.loader.state()' appendix based on whether the
module is marked as raw. As of Ie4564ec8e26ad53f2, the two remaining use
cases for raw responses now specify the 'raw=1' request parameter, and we
can get rid of the "raw module" feature and all the complexity around it.
== Startup module
In the startup module there was an interesting use of isRaw() that has
little to do with the above. The "ATTENTION" warning there applies to the
startup module only, not raw modules in general. This is now fixed by
explicitly checking for StartupModule.
Above that warning, it talked about saving bytes, which was an optimisation
given that "raw" modules don't communicate with mw.loader, they also don't
need to be registered there because even if mw.loader would try to load
them, the server would never inform mw.loader about the module having
arrived. There are now no longer any such modules.
Bug: T201483
Change-Id: I8839036e7b2b76919b6cd3aa42ccfde4d1247899
Remove use of a complete "namespace" for grouping and instead use dashes
within the first key segment for that.
This way, we can leverage the various features WANObjectCache provides
for statistics relating to a particular kind of thing being cached.
These statistics are currently combined for all of resourceloader,
which isn't useful. Mildly related to T223647.
Change-Id: I5df69e46ac436d04e765726a36fc3eb70697a7ed
Follows-up e7b57d881a, which changed it from replace() to upsert()
but lost one of the wrapping arrays in doing so.
Previously updated many more rows than expected on Postgresql, when it
should only be updating individual rows, not all rows that match either
criteria.
SQL query before:
WHERE ((md_module = 'jquery.makeCollapsible.styles') OR (md_skin = 'vector|en-gb'))
SQL query after:
WHERE ((md_module = 'jquery.makeCollapsible.styles' AND md_skin = 'vector|en-gb'))
Not a problem on MySQL as upsert() is implemented differently there.
Bug: T222385
Change-Id: If8a458bf4543b297b3a06f31e09c0e77666bf7e6
* Use early return instead of all-encapsulating conditional.
* Document why the try/catch is so big.
Change-Id: Ie19e18556e7ac0a12ad6b979367f8c6b786bbe31
I would argue that these comments do not add any information that
would not be there already. Having them adds mental overhead, because
one needs to read both the comment and the next line of code first to
understand they say the exact same. I don't find this helpful, but
more distracting.
Change-Id: I39c98f25225947ebffdcc2fd8f0243e7a6c070d7
It's old and unmaintained. The only thing we care about is if it
was able to parse the script and if not, what its error is. Its
return value or broken inner workings are insignificant at this
point and only cause noise.
Bug: T77169
Change-Id: Ie357ccfcc6141f894b452eb3996e168c1526990f
Package files are files that are part of a module, but are not
immediately executed when the module executes. Instead, they are
lazy-excecuted when require() is called on them. Package files can be
scripts (JS) or data (JSON), and can be real files on the file system,
or virtual files generated by a callback.
Using virtual data files, server-side data and config variables can be
bundled with a module. Support for file-based require() allows us to
import npm modules into ResourceLoader more easily.
The require function passed to each script execution context, which was
previously a reference to the global mw.loader.require() function, is
changed to one that is scoped to the module and the file being executed.
This is needed to support relative paths: require( '../foo.js' ) can
mean a different file depending on the path of the calling file.
The results of require()ing each file (i.e. the value of module.exports
after executing it) are stored, and calling require() on the same file a
second time won't execute it again, but will return the stored value.
Miscellaneous changes:
- Add XmlJsCode::encodeObject(), which combines an associative array of
XmlJsCode objects into one larger XmlJsCode object. This is needed for
encoding the packageFiles parameter in mw.loader.implement() calls.
Bug: T133462
Change-Id: I78cc86e626de0720397718cd2bed8ed279579112
We already had a $filterCacheVersion variable, but it was
only used for the internal cache for JS and CSS minification,
which is not enough. If there is a breaking change in either
of these processes, we also need to invalidate version hashes.
This commit renames ResourceLoader::$filterCacheVersion to
ResourceLoader::CACHE_VERSION and takes it into account in
getVersionHash(). Adding it to getDefinitionSummary() is not
sufficient, because content-hashed modules also need to be
invalidated when there's a breaking change in the minifiers.
This cache version can also be incremented when there's a
breaking change in image embedding or LESS compilation,
although content hashing deals with that already, so we
could also add a separate cache version for those that's
only added to getDefinitionSummary().
Bug: T176884
Change-Id: Ife6efa71f310c90b9951afa02212b2cb6766e76d
This seems quite nuclear. I'd actually like to deprecate the
wgCacheEpoch variable more generally in favour of a handful
of more specific version constants, but as starting point,
remove it from the hash used for load.php urls and localStorage
keys.
The latter is also controlled by wgResourceLoaderStorageVersion
already.
Also ref T32956 about a more standalone ResourceLoader.
Change-Id: I913f846090e82d3d822653b9b7ce22233cdb5e90
This follows 5ddd7f91c7, which factored out response building
from ResourceLoader.php to ResourceLoaderModule::buildContent.
As optimisation, I made this method only return the array keys
needed for the current response; based $context->getOnly().
The reason for this refactoring was the creation of the
'enableModuleContentVersion' option to getVersionHash(), which
would use this method to create a module response, and hash it.
During the implementation of that option, I ran into a problem.
getVersionHash() is called by the startup module for each
registered module, to create the manifest. The context for the
StartupModule request itself has "only=scripts". But, we must
still compute the version hashes for whole modules, not just
their scripts.
I worked around that problem in aac831f9fa by creating a mock
context in getVersionHash() that stubs out the 'only' parameter.
This worked, but made the assumption that the scripts and styles
of a module cannot differ based on the 'only' parameter.
This assumption was wrong, because the 'only' parameter is part
of ResourceLoaderContext and available to all getters to vary on.
Fortunately, the 'enableModuleContentVersion' option is off by
default and nobody currently using it was differing its output
by the 'only' parameter.
I intend to make use of the 'enableModuleContentVersion' option
in StartupModule to fix T201686. And StartupModule outputs a
manifest if the request specifies only=scripts, and outputs
a warning otherwise. As such, it cannot compute its version
if the 'only' parameter is stubbed out.
* Remove the 'only' parameter stubbing.
* Remove the selective building from the buildContent() method.
This was not very useful because we need to build the whole
module regardless when computing the version.
As benefit, this means the in-process cache is now shared between
the call from getVersionHash and the call from makeModuleResponse.
Bug: T201686
Change-Id: I8a17888f95f86ac795bc2de43086225b8a8f4b78
* Remove use of MediaWiki's FormatJson class. Ref T32956.
* FormatJson::decode() was a direct alias of json_decode.
* FormatJson::encode() is a wrapper for json_encode that
sets `JSON_UNESCAPED_SLASHES | JSON_HEX_TAG | JSON_HEX_AMP`
by default, plus a boolean parameter to add JSON_PRETTY_PRINT.
Instead, use json_encode() directly. By default json_encode() escapes
slashes and non-ASCII unicode.
* Audit our uses of JSON encoding, document their needs, and set flags
as needed.
* Remove $mapToJson abstraction from ResourceLoaderStartUpModule.
* Always pretty-print the list of module names in the error message,
regardless of debug mode.
* Remove hacky indentation-adder from ResourceLoaderStartUpModule.
This was relying on there not being line breaks in the json output
outside debug mode, and adding a level of indentation to roughly
match the code in the JSON is substituted. This didn't match and
just generally doesn't seem worth it.
Change-Id: I3e09ddeb4d53c8980195c1855303c0ee25bd4c20
Deprecated since 1.26. No subclasses in Wikimedia Git define these methods,
no calls to methods by this name in Wikimedia Git.
If a module subclass were to still define such a method, it is simply
not called anymore. The version hash system introduced in 1.26 will
still invalidate modules based on wgCacheEpoch.
Bug: T94074
Change-Id: I65b2a625a30f22c8a9d14a3505605546fa5bab83
This effectively applies safemode to the mw.loader client,
without the client itself needing specific knowledge of safemode.
Test Plan:
* Unchanged: When viewing a page in safemode, the 'user' and
'site' modules are still not queued by OutputPage.
* New: mw.loader.getState('site'), previously would yield
'registered', but will now yield null.
* New: mw.loader.load('site'), previously loaded the module,
it now logs a dependency warning for unknown module, like for
any other unknown module.
* New: mw.loader.using('site'), previously resolved, it is now
rejected.
Bug: T185303
Change-Id: I672e3891c8e1b3c2d13655fa134d0f1d031b8247
The deprecation warning for the module 'mediawiki.ui' (used
e.g. on Special:UserLogin) is now actually shown.
Change-Id: If35a106c77622dbf7e8b5628fbea28f9e7ffd76d
These comments do not add anything. I argue they are worse than having
no comments, because I have to read them first to understand they
actually don't explain anything. Removing them makes room for actual
improvements in the future (if needed).
Change-Id: Iee70aad681b3385e9af282d5581c10addbb91ac4
I can see that "parent::__construct" literally calls the parent
constructor. I can see that stuff preceeded by the keyword "protected"
is protected. I really (really) don't need comments explaining such.
Change-Id: I7458e714976a6acd3ba6a7c93fdc27d03903df83
ResourceLoaderModule objects gain a new method getPreloadLinks() which
returns an array with the meta data required to build a Link rel=preload
header according to the current draft for W3C Preload.
<https://w3c.github.io/preload/>
Another implementation of this is already in use in OutputPage for
preloading the logo image.
This array is formatted by the ResourceLoaderModule::getHeaders method,
which is implemented as "final" at this time, thus restricting use to
the Link rel=preload header.
Headers are exposed and process-cached, like all other content
(scripts, styles, etc.), through ResourceLoaderModule::getModuleContent,
and aggregated by ResoureLoader::makeModuleResponse.
I had hoped for the getPreloadLinks to be stateless (not vary on $context).
Whether something should be preloaded and what, should not vary on the
skin or language. However, while that conceptually holds true, the exact
url for any given resource may still vary. Even the main use case for this
feature (T164299, preloading base modules request) require $context to pass
down skin and lang to the load.php url.
Add full test coverage and example documentation.
Bug: T164299
Change-Id: I2bfe0796ceaa0c82579c501f5b10e931f2175681
Rather than only the 'private' group triggering embedding, allow modules
to explicitly specify if they should be embedded.
The default is still to only embed when the group is 'private', and the
'private' group is still special in that ResourceLoader::respond() will
still refuse to serve it from load.php.
Change-Id: Ib9a043c566822e278baecc15e87f9c5cebc2eb98
This fixes two bugs:
* 1) When two modules are requested, and the first one ends with ";"
inside a comment, the second module might become part of
that comment.
* 2) A request with script=only where the requested module content
ends in a statement without ";", but has a comment after it
that does ends with a semicolon, then in debug=false, mw.loader.state()
would be appended directly after the semicolon-less statement because
the check is performed before minification.
Previously:
script> foo()
script> // bar();
states> mw.loader.state( {} );
Became (minified separately):
script> foo()
states> mw.loader.state({});
Became (concatenated)
> foo()mw.loader.state();
Which is invalid code.
Both of these are now fixed.
Bug: T162719
Change-Id: Ic8114c46ce232f5869400eaa40d3027003550533
* Add fileName to cache key to fix T52919. The cached parsed error
message contains the filename, this should be part of the cache
key as otherwise two identical user scripts may report the same
error message, including " on line X of page Y" where Y is whichever
of the two pages first created the cache entry.
* Make the cache key global instead of per-wiki. There is no need
for this to be per-wiki.
Bug: T52919
Change-Id: I6c2718c53be7f6384a6486a4a8718ae7f423d216
* Simplify by using early return and getWithSetCallback.
* Add TTL (previously indefinite, now 1 week).
Bug: T52919
Change-Id: Ic95ba392cdb3bcc8081c77d2c2a3240548bed366