Also do so in various other test classes.
Follows-up 170c49d61c. Fixes Travis CI regression:
> 1) MediaWiki\Tests\Revision\MutableRevisionRecordTest::testSetGetPageId
> Failed asserting that 2 is identical to 0.
> tests/phpunit/includes/Revision/MutableRevisionRecordTest.php:129
Change-Id: I41c8bda8e620ebe7608a393d81f3b0f13af68ba7
Expose this constant for internal use by Navigation Timing,
so that it can compute mwLoadEnd based on when these modules
finish loading.
The way mwLoadEnd is currently computed is by building a list
of all registered module names, and narrowing it down to the
ones in 'loading' state at the time that ext.navigationTiming.js
executes. The problem with doing that, is that it is includes
various lazy-loaded modules that aren't critical to the page and
aren't meant to be tracked by that metric. For example:
* Preloading of modules from various extensions (including VE,
and Popups).
* Background chains for EventLogging schemas from mw.loader.using,
including the one started by Navigation Timing itself.
On my local install, the list of filtered down modules always
includes 'schema.SaveTiming', '...rumSpeedIndex', etc.
Exporting the list passed to the initial load() call as constant
will enable Navigation Timing to instead only await only those
modules (and their dependneices).
Bug: T204426
Change-Id: Ida134b4dfee218db16c2d1f88d4f26e8d761e154
* There is only a single non-test caller to this method in the entire
codebase, and no callers elsewhere (Wikimedia Git, Codesearch).
It's only used with an array, so remove the other unused code paths,
and mark it internal (to my knowledge, nothing ever used it outside
RL in the past, either).
* Add test coverage for the module indexing logic.
Change-Id: I9e0f95416d5b2fdd87323288231ee6d8c85d88e7
Added spaces around .
Removed empty return statement which are not required
Removed return after phpunit markTestIncomplete,
which is throwing to exit the test, no need for a return
Change-Id: I2c80b965ee52ba09949e70ea9e7adfc58a1d89ce
Follows-up b7b84d55d4, which embedded the whole of the three 'mediawiki'
JS files inside of startup.js, but did so inside of the pre-existing
closure that was there.
This adds some overhead we don't get value of, so best to remove
it and embed it as a sibling of startup.js in the same top-level
scope.
In local testing (Chrome stable, CPU 1/6th) this reduced startup
run-time from 73-78ms to 63-65ms.
Also:
* Declare isCompatible() as a normal function.
Disable the implicit-globals warning given this isn't a regular module,
this file is intentionally in the global scope.
* Unfold the private startUp() function to its call site.
Change-Id: Ida51ab20898c9e4ae6cbf7ad2968d88d824a1483
The PHP interface still supports it without deprecation, but there
is no need for the client to support it given it is only ever called
from the startup module, which always passes it an object.
Follows-up 6815e35575, which did the same for `state(key, val)`.
Also simplify the implementation to avoid extra calls and optimise
for the only signature.
Mark the method as @private, and change the existing use of
@protected to @private (doesn't really make sense in JavaScript).
Change-Id: I24786f90bcfb256b2e7c37f7760bba1a5e399443
This significantly simplifies the getVersionHash implementation for
StartupModule, and fixes a couple of bugs.
Previously, the startup module's E-Tag was determined by the
'getDefinitionSummary' method, which combined the E-Tag values
from all registered modules, plus what we thought is all information
used by 'getScript' (config vars, embedded script files, list
of base modules, ...)
However, this were various things part of the manifest that it
forgot about, including:
* Changes to the list of dependencies of a module.
* Changes to the name of module.
* Changes to the cache group of module.
* Adding or removing a foreign module source (mw.loader.addSource).
These are all quite rare, and when they do change, they usually
also involve a change that *was* tracked already. But, sometimes
they don't and that's when bugs happened.
Instead of the tracking array of getDefinitionSummary, we now
use the 'enableModuleContentVersion' option for StartupModule,
which simply calls the actual getScript() method and hashes that.
Of note: When an exception happens with the version computation of
any individual module, we catch it, log it, and continue with the
rest. Previously, the first time such error was discovered at
run-time would be in the getCombinedVersion() call from
StartupModule::getAllModuleHashes(). That public getCombinedVersion()
method of ResourceLoader had the benefit of also outputting details
of that exception in the HTTP response output. In order to keep that
behaviour, I made outputErrorAndLog() public so that StartupModule
can call it directly now. This is covered by
ResourceLoaderTest::testMakeModuleResponseStartupError.
Bug: T201686
Change-Id: I8e8d3a2cd2ccd68d2d78e988bcdd0d77fbcbf1d4
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
This existed for internal use by OutputPage, which is no longer
the case as of I11b390f2e4f5e7db.
Also move the unit tests from OutputPageTest,
to ResourceLoaderSkinModuleTest.
Change-Id: I8b23f976f5f89b1005b387a827f75031f5c96141
The use of global variables was deprecated in favour of
ResourceLoaderModule::getLessVars() on a per-module basis.
Also moved testLessFileCompilation case to the appropiate file as it
covers ResourceLoaderFileModule.php, not ResourceLoader.php.
Bug: T140804
Depends-On: Ib1b2808df2384473bfac47f53a5d25d7c9bbca2b
Depends-On: I96047f69d01c4736306df2719267e6347daf556f
Change-Id: If708087c85c80355c7e78f1768529b5f2e16ed07
Add @covers for various helper methods used by public methods, where the helper
methods actually contain most of the logic being tested in FileModuleTest.
I've changed these methods from protected to private (confirmed no usage)
to further pin down that their contract doesn't matter beyond making the
public methods work.
Change-Id: I2aef0d322b38bc3595e7d2c2339112b16fc66b8d
Unable to reproduce the failure locally with Quibble.
The failure never made sense to begin with, as the only thing I could
conclude after ruling out all other possibilities was that PHP was
somehow forgetting/losing a key in a plain array in HashBagOStuff.
Bug: T176097
Change-Id: Ia438d5a929d7bd5dccf09387980ba92207616db0
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
Find: /isset\(\s*([^()]+?)\s*\)\s*\?\s*\1\s*:\s*/
Replace with: '\1 ?? '
(Everywhere except includes/PHPVersionCheck.php)
(Then, manually fix some line length and indentation issues)
Then manually reviewed the replacements for cases where confusing
operator precedence would result in incorrect results
(fixing those in I478db046a1cc162c6767003ce45c9b56270f3372).
Change-Id: I33b421c8cb11cdd4ce896488c9ff5313f03a38cf
- Cover case of simple module load.
The bulk of this use case is already covered by a lower-level
test for makeModuleResponse(). The added case here exists
to cover the wrapper method, ResourceLoader::respond().
- Cover logic for catching and logging internal errors.
Change-Id: I4315bb00137ff80ee2b790c6b4d4b5fbd93f6bc1
The last remaining users of this feature were MobileFrontend and Minerva,
which have been migrated to direct imports.
Bug: T140807
Change-Id: I1a66a2ad314bde332297798520e5ec3e0e3d4c9b
Adds coverage for line 1049-1056.
Also, follow-up 6292d54dff by simpliying the regex by using /s modifier to
enable PCRE_DOTALL which includes matching of new lines.
Change-Id: Icec34dfe107d418951b3d155234295c79410ffaa
This prevents cache churn when the wiki-global LESS variables vary
between wikis because the cache key is used as a "global" instead of
db-local. This is good for the common case, but should still explicitly
vary if the vars differ between wikis.
Bug: T191937
Change-Id: If12fd07a7062792205384150d6f5fd9a83f996cc
Follows-up If35a106c7. These log messages are not criticial and
should not be in the <head> competing with stylesheets and article
content. Move them to the end of <body> instead, nearby other
low-priority script tags.
The getBodyHtml() method from ClientHtml was empty, but has been
non-empty in the past. It's fine to repopulate.
Also, while ClientHtml::getBodyHtml was empty, there are additional
RLQ scripts created by OutputPage that do exist even without this.
Namely, there is a <script> for wgPageParseReport, and one for
wgBackendResponseTime etc.
Change-Id: Ibda7091bdcd5ed207395b20196cdc33df926a24c
This was previously covered implicitly by an unrelated test.
Change that test (dependency.less) to use ../ to access the file
directly so that that test case is only about tracking dependencies
and testing the parser.
Then, add a second case that tests the use of import dirs.
Bug: T140807
Change-Id: Ie85abffe313922c03b3e146422f36b1d6a79743d
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 first argument to the function is supposed to be an object, or null if
the method is static.
Otherwise on PHP 7.2 the tests fail with:
ReflectionMethod::invoke() expects parameter 1 to be object, string given
Change-Id: I7002be5809f9dfbee0788907fe85139d05c0e1fc
Follows-up 70941efd35 which broke various public
signatures of the ClientHtml class that I'd prefer to handle
differently.
This commit mainly restores support for all previously public
signatures, and either removes the need for a parameter, or moves
it to the end of the original signature (as optional param).
* ClientHtml::getHeadHtml: Remove the positional/required parameter
that was added. Restoring the method to being a stateless computer
that requires no parameters. Pass the option via construct instead.
* ClientHtml::makeLoad:
- Make $nonce optional.
- Restore $extraQuery as optional.
* ResourceLoader::makeInlineScript: Document $nonce as optional
(matching the implementation).
Change-Id: Iaf33f2a060048e6606fba8d875b6d2953b21ef45
The deprecation warning for the module 'mediawiki.ui' (used
e.g. on Special:UserLogin) is now actually shown.
Change-Id: If35a106c77622dbf7e8b5628fbea28f9e7ffd76d
The primary goal here is a defense in depth measure to
stop an attacker who found a bug in the parser allowing
them to insert malicious attributes.
This wouldn't stop someone who could insert a full
script tag (since at current it can't distinguish between
malicious and legit user js). It also would not prevent
DOM-based or reflected XSS for anons, as the nonce value
is guessable for anons when receiving a response cached
by varnish. However, the limited protection of just stopping
stored XSS where the attacker only has control of attributes,
is still a big win in my opinion. (But it wouldn't prevent
someone who has that type of xss from abusing things like
data-ooui attribute).
This will likely break many gadgets. Its expected that any
sort of rollout on Wikimedia will be done very slowly, with
lots of testing and the report-only option to begin with.
This is behind feature flags that are off by default, so
merging this patch should not cause any change in default
behaviour.
This may break some extensions (The most obvious one
is charinsert (See fe648d41005), but will probably need
some testing in report-only mode to see if anything else breaks)
This uses the unsafe-eval option of CSP, in order to
support RL's local storage thingy. For better security,
we may want to remove some of the sillier uses of eval
(e.g. jquery.ui.datepicker.js).
For more info, see spec: https://www.w3.org/TR/CSP2/
Additionally see:
https://www.mediawiki.org/wiki/Requests_for_comment/Content-Security-Policy
Bug: T135963
Change-Id: I80f6f469ba4c0b608385483457df96ccb7429ae5
* Ignore getLogoData() which is a one-line proxy to ::getLogo,
that can't really be tested because static methods can't be stubbed.
It exists so that this method can be stubbed instead. The actual
method is already covered.
* Simplify @covers for getStyles() to allow indirect coverage within
the class because it's intended as a higher-level integration tests.
The other tests in the suite still cover a specific method only.
Change-Id: I1445a016c1f12a6d8ceaaf745023a28cf20e5371
Verify that calling register() twice does not throw, but warns,
and that the last registration wins.
This behaviour was actually surprising to me because it used to
throw, and I'd assume that when we added the warning, the behaviour
would go from fatal to non-fatal, but keep that the last one is
at fault/unsupported.
Perhaps b1ea0612 / d3e3bcfd6 (T116628) should've added a return
statement. Oh well, we can consider changing that later, but at
least test for it.
Change-Id: I955132868146ea5bf88c9b9e648c84d8196cb1f9
This ResourceLoader module provides a way to ship
messages to CSS variables.
We will need this going forward to deal with flash of
unstyled content in various JavaScript based UIs that
are subject to i18n such as table sorting and
collapsible elements.
To avoid overhead of hitting the database to fetch and
transform localisation messages we make use of the MessageBlobStore
making use of `messages` definition already inside
ResourceLoaderFileModule. Given this resource is only intended
for render blocking styles without JavaScript this should be okay
(although if requested in JavaScript will also ship associated
messages)
Bug: T42812
Change-Id: I2bf12cdc848478889acbe9a7a970e46f8aefa287
There has long been a hack for previewing edits to user JS/CSS, where
OutputPage would pass an 'excludepage' parameter to
ResourceLoaderUserModule to tell it not to load one particular page and
would instead embed that page statically. That's nice, but there are
other places where we could use the same thing.
This patch generalizes it:
* DerivativeResourceLoaderContext may now contain a callback for mapping
titles to replacement Content objects.
* ResourceLoaderWikiModule::getContent() uses the overrides, and
requests embedding when they're used. All subclasses in Gerrit should
pick it up automatically.
* OutputPage gains methods for callers to add to the override mapping,
which it passes on to RL. It loses a bunch of the special casing it
had for the 'user' and 'user.styles' modules.
* EditPage sets the overrides on OutputPage when doing the preview, as
does ApiParse for prop=headhtml. TemplateSandbox does too in I83fa0856.
* OutputPage::userCanPreview() gets less specific to editing user CSS
and JS, since RL now handles the embedding based on the actual
modules' dependencies and EditPage only requests it on preview.
ApiParse also gets a new hook to support TemplateSandbox's API
integration (used in I83fa0856).
Bug: T112474
Change-Id: Ib9d2ce42931c1de8372e231314a1f672d7e2ac0e
If a module itself is empty, it must consider any dependencies
it has before bailing out as empty.
Bug: T191596
Change-Id: I2b45b948a6f78060e53513d3b4b77f48d7bf4a6b
These are deprecated for extensions to implement, but still
supported and already triggered by the test cases. Previously
not mentioned because they were ignored by PHPUnit, but not anymore.
Change-Id: I594788e322bfd83be1e7847d3272d57c549f3e8b
* Document the structure of the in-process $titleInfo cache.
Specifically, specify that it is not the value from getTitleInfo(),
but rather a container for zero or more versions of such values.
The reason this is fragmented is because ResourceLoaderContext
is a parameter to most methods and as such, makes everything
variable. Tracked as T99107.
* Make various bits easier to understand by consistently refering
to the container keys as "batchKey", and referring to the internal
keys as "titleKey".
* Centralise title key logic by moving to private method.
* Replace the internal creation of titleKey to be based on LinkTarget
with plain namespace IDs and db keys, instead of invoking the
expensive getPrefixedTitle function which involves quite a lot
of overhead (TitleCodec, GenderCache, Database, Language,
LocalisationCache, ..).
Change-Id: I701e5156ef7815a0e36caefae5871524eff3f688
When a module has group=user specified, it means that its module contents
can vary by user. These kinds of requests have two special needs:
1) They need an additional "user" parameter in their load.php request,
so that the response knows which user-context to use.
2) They need to have their 'version' hash pre-computed based on which assets
will be loaded for this user. The general 'version' hash associated with
this module name in the main registry (modules=startup) will be "wrong"
as that is computed based on logged-out status.
We do this by omitting the module name from the `mw.load.load(Array modules)`
call in the HTML, and instead output a request for the full url.
This currently works fine for most cases, such as the 'user' module loaded
by MediaWiki core. The branch in getData() dealing with legacy 'only=scripts'
behaviour also covers this case.
But the case of an extension registering a group=user module and loading it the
general way (e.g. not with legacy only=scripts behaviour), would currently end
up in the Array-queue and dynamically loaded by the client-side without knowing
the correct version hash. Fortunately, no code exists that I know of that meets
these three critera (extension registered, group=user, non-legacy). However,
for the GlobalCssJs extension to migrate from legacy to non-legacy, they will
need to start doing this. This commit makes sure that that will work.
The makeLoad() method in ClientHtml has code ensuring the full-url form (with
pre-computed 'version' hash) is used for any modules with group=user. Before
this patch, we didn't get to call makeLoad() because getData() was assuming
that we only need makeLoad() when either the module should be embedded (group=private),
or when it is a style/scripts-only module. It didn't consider group=user.
Bug: T188689
Change-Id: Iaab15e5f5c12e7e28b8c81beab90948cd07cd352
In preparation for passing down 'safemode' from OutputPage.
Only used in one place in Wikimedia Git: OutputPage::getRlClient().
Bug: T185303
Change-Id: If01eca96986ff8d7dcdaab6910bf183ba7c7311f