According to T248061 the basic support for IE8 is gone now meaning we
don't need to serve the snippet for html5shiv anymore.
Also dropping the html5shiv code.
Bug: T248061
Change-Id: I1a8dbd72ae68f518f52a76a80a3b54239720d20c
* Add a void return hint to methods that are not meant to return
anything. This helps catch accidental return statements in the
future, lets Phan better understand how methods are meant to be
used, and might also allow PHP to better optimise the compiled
code form (speculation).
I did not, however, add it to publicly extended methods as that
might mess with strict mode.
* Remove the internal getResourceLoader() method from MessageBlobStore.
This has been redundant since 3edaa0b37c.
The method was protected, and not considered stable to subclass
for extensions. Hence not a breaking change.
* Add Throwable typehint to formatException() and friends.
This is the narrowest one I could add given that the methods
called from here already enforce the same typehint.
Update the doc to match for now. There isn't a reason right now
to limit this only to Exception, and given this is the method
and not the catch statement itself, does not change behaviour.
* Remove unused ResourceLoader->getHookContainer().
Added within 1.35 cycle, safe to remove.
* Remove unexpected `@since` for `@internal` getHookRunner().
* Remove redundant `@internal` from ResourceLoaderMwUrlModule
methods, which itself is already `@internal`.
Change-Id: I68d33ff6feca7ef95282a7ff03eb9332adfde31c
This commit removes two `@phan-suppress` annotations that were
false negatives found in Dec 2019 from a Phan upgrade (598c4d7f),
which this new release fixes. They have to be removed as Phan
detects redundant suppressions.
Bug: T246490
Depends-On: Ib2ff7d187c7c28b82b8bef95aafe5bd718b74cc1
Change-Id: If776ce363deda46439a878b707423c581be8177d
It was previously creating a fresh context object, and then
manually imported some query parameters, and then *also* created
a derivative context object (so that it can copy over the
"getContentOverrideCallback" value and to allow the consumer
to also use setVersion/setModules).
The reason for this indirection was that I wanted to re-use the
query string parsing logic of ResourceLoaderContext::__construct,
instead of interpreting it here. However that extra indirection
is rather fragile as it could easily forget some other things to
inherit manually.
And, per T249189, it means there is no process cache shared between
the two. This is exactly what DerivativeResourceLoaderContext
is for, and if there is a missing feature in it, we should add it,
instead of working around it (note to self...). For now, though,
it can actually be used as-is.
Changes:
* Use DerivativeResourceLoaderContext directly.
* Set the 'only' and 'user' values directly using the setter
methods after creating the derivative object.
* Also set 'raw' correctly. This was previously handled by
$extraQuery being passed to ResourceLoaderContext::__construct,
but now needs to be done manually.
Bug: T249189
Change-Id: I4173ec75bef4fe9fee39663b1348c077414d3627
* Where possible and easy to figure out, change `array` to something like
`array<K,V>` or `V[]` for improved static analysis to catch/prevent
regressions in CI.
* Minor doc improvements:
- consistently use the imperative mood for method briefs,
- consistently use @internal instead of @private,
- explain in @throws why they happen to inform when they should be caught
(and remove if they are not meant to be caught/handled by any caller).
* Simplify addSources() implementation as a simple loop instead recursing
(not worth the complexity, only called once or twice at runtime).
* Use more granular exceptions to distinguish between errors that indicate
a mistake on the caller (logic/invalid arguments error), and runtime
errors (which are more circumstantial).
* Update register() unit test for bad 'moduleInfo' type to use
a nested value, given that the second-parameter level type is
now verified by the signature already.
Change-Id: Id98ba1f28cb7f1c72f0a3e82f4151bcbd0f3db77
Scalar casts are still allowed (for now), because there's a huge amount
of false positives. Ditto for invalid array offsets.
Thoughts about the rest: luckily, many false positives with array offsets
have gone. Moreover, since *Internal issues are suppressed in the base
config, we can remove inline suppressions.
Unfortunately, there are a couple of new issues about array additions
with only false positives, because apparently they don't take
branches into account.
Change-Id: I5a3913c6e762f77bfdae55051a395fae95d1f841
This is to make it behave in a more object orientied way. The
goal is to make it be easier to allow extensions to mark certain
pages as requiring a different policy (For example, CodeEditor
extension uses a blob: url with a WebWorker. We don't want to
include that on the policy of every page, but allow the extension
to mark it as required whenever needed).
This commit does not change code behaviour in any way.
Change-Id: I4bf53dabb6e6c5446cea99a64db68b300cef2fd4
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
The 'version' and 'modules' parameters are a somewhat problematic
part of the ResourceLoaderContext object as we often pass around
the context but may be dealing with only a subset of the modules
in the outer request, or even entirely different ones (e.g.
for OutputPage's fake context 'modules' and 'version' are both
null).
This is already visible in ClientHtml where we create a derivative
context just to call setModules() and have makeVersionQuery()
work. This is now fixed.
This change is in preparation for use in ResourceLoaderImage
(to fix T233343) where we'll need to compute a version for only
1 module of a larger set, and ideally without needing to create
another context.
Bug: T233343
Change-Id: Icc1a4fd1f58c4e49e58eee43ca4ba2de6cfffc76
* 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
This allows us to remove many suppressions for phan false positives.
Bug: T231636
Depends-On: I82a279e1f7b0fdefd3bb712e46c7d0665429d065
Change-Id: I5c251e9584a1ae9fb1577afcafb5001e0dcd41c7
Reduces output by not needlessly performing a change client-side
for which we already know the result server-side.
Bug: T231168
Change-Id: I4b8749f976d04d24f85236ddd641c7a4c7f6c23a
Modules that are never embedded, and not user-specific, should not be
excluded from the loader, even if they are empty.
Doing so has two problems:
1. Modules are expected to have their changes propagated within 5 minutes
through the startup module. This depends on the fact that in page view
HTML we queue the module by name, regardless of its current version.
If the module is known to be needed by a page, then we need to queue it,
even if the current version is empty. Otherwise, cached pages will be
missing the module, despite the older ParserOutput perfectly knowing
already that it was needed, which can cause bugs due to HTML not
matching the module queue it was generated with.
2. The isKnownEmpty method can sometimes require a database lookup.
The performance team tuned this with a preloader for the subset of
modules we need the information for (user modules and style modules).
In 0b1a7d4c59, I accidentally made the conditions nested the wrong
way, which made it call this much more frequently.
Bug: T230260
Bug: T176159
Change-Id: I4e6af2c833c92e1277713bdd0c68953d49c4dd9d
* Use nowdoc instead of heredoc syntax where variable expansion is not
wanted.
* Combine code paths for debug mode and normal mode.
Change-Id: Ic70d82aaec6396a31783e5a60419409f08c4ef73
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
The ResourceLoaderModule::isRaw() feature and the ability to magically
switch a regular load.php request into raw mode is being removed soon.
Instead, specify raw=1 in the request url where that behaviour is needed.
Bug: T201483
Change-Id: Ie4564ec8e26ad53f2de1a43330d18a35b0498a63
Turn these embedded function calls into variable declarations,
later consumed by startup.js.
This has a few benefits:
* Variables can be declared immediately, without needing to
defer it to after mw.loader arrives from startup, via an RLQ
callback. This makes the inline script simpler and a tiny
bit smaller.
* By moving the actual function calls to startup.js, they could
easily be re-arranged in the future or migrated in other ways
without needing to worry about HTML caching and keeping concurrent
compatibility with both orders of execution.
Change-Id: I1c995a9572d9eb3201a565341c19bdf81ab00eff
The addModuleScripts() methods were deprecated in 1.31 and 1.32,
these are now removed.
The getModuleScripts() are now deprecated as well, always returning
an empty array. To be removed in 1.34.
Depends on commits for bundled/wmf-deployed extensions that
remove the last few remaining callers to the deprecated functions
in: 3D, Collection, Flow, GlobalUserPage, and Wikibase.
Bug: T188689
Depends-On: If9f0bc6aef85117587fa1929f34f8861c8d80314
Depends-On: Ia8d41b97fbf6822f5f8f7ac889408acce1ac9a3a
Depends-On: I503b919739ea474ff33726815b0da55e2f7e2724
Depends-On: I236ef637fd03b810a46eb361e25067a037e9d183
Depends-On: I62e17779753b977a452cc0c9694947941e999cc3
Change-Id: I5a19b8f164ccf666485d2971202194b747f882df
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
This follows 80e5b160e0, which introduced ClientHtml::setModuleScripts()
and setModuleStyles() with @deprecated marks. There was a vague intention
to remove both at some point.
The commit did not deprecate the related methods in OutputPage and ParserOutput.
The plan that eventually formed at T188689 was to keep methods relating to
"setModuleStyles" for the time being, and focus first on the removal of the
methods relating to "setModuleScripts". The latter since been properly
marked as deprecated and removal is scheduled for 1.33.
There is no current plan to deprecate/remove addModuleStyles
from OutputPage and ParserOutput. As such, the internal helper method
that makes those possible, probably shouldn't me marked as deprecated.
Bug: T188689
Change-Id: Ia36c057b73fe834bcbb2e3e8993d1a793a12ab72
* Fix ResourceLoaderClientHtml to return what it was documented to
return, a WrappedStringList. It accidentally used the wrong join()
method, causing it to create a plain string too early.
* Update method documentations from ClientHtml::getBodyHtml to
BaseTemplate::getTrail for 'bottomscripts', and from
ResourceLoader::makeInlineScript for 'reporttime'.
* Update BaseTemplate::getTrail to join by new line instead of native string
concatenation.
This by itself would suffice for the most common case, but in order
to also account for the possibility of extensions using hooks for
'SkinAfterBottomScripts' that concatenate, update bottomScripts()
to pass a plain string to the hook and merge it later.
Change-Id: If0d227cb9db67229a27d489c082db790ea8e3840
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 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
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
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
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
The same variable index was set to the same value from two places,
one unconditionally, and two times within a conditional block after
the first one.
The second ones are a completely redundant remnant from a refactor
sometime last year.
Change-Id: Ia234d4aca398b1b365d457a439d9e449229f28fb
It was already supported for only=scripts and only=styles, but
not yet for general modules loaded as 'combined'.
This is especially useful for general modules that are private/embedded,
as this allows us to skip the loader.implement() boilerplate.
Bug: T176159
Change-Id: I83e9f74dad75867c10ebd0a94b87c31e4adbb57f
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
If a type=general module is enqueued, don't try to load it as a
stylesheet.
* Per a464d1d41d, state tracking is already disabled for
these loads (as otherwise we wrongly claim state=ready, when in
fact only the styles and not the scripts were loaded).
* The warning was added in a464d1d41d.
* Default install (tested in Vagrant), Wikimedia Beta cluster, and
Wikimedia production have seen zero violations of this warning
in the past 7 days.
Raise severity to ERROR and add the 'continue' statement so that
these are now not loaded at all.
Bug: T92459
Change-Id: I211d56ac2df479ebf5b98667c613ecf81489539b
Previously it was only in debug logs (which are enabled in Jenkins,
MediaWiki-Vagrant, Beta, and for mwdebug hosts in wmf-production).
Turning it into a warning() will log it for regular requests as well
which is the last step before we can consider hard enforcement.
Bug: T92459
Change-Id: I87c7794c5cfe35521bf76cc42f94907001e9d24b
It's unreasonable to expect newbies to know that "bug 12345" means "Task T14345"
except where it doesn't, so let's just standardise on the real numbers.
Change-Id: I6f59febaf8fc96e80f8cfc11f4356283f461142a
Previously, style modules were only in a predictable order for production mode.
In debug mode, the order was determined by order in which modules were added
to queue at run time. This made it sometimes hard to debug, especially when
dealing with gadgets that apply in a different order among each other.
Change-Id: I4bff0c91d127e4ad8015cd8c1775220fe460cbc3
Changes:
- uses int instead of number as param and return value type,
- uses stdClass instead of stdObject
- fixes ResourceLoaderClientHtml constructor's $target param type:
it is string|null, not an array (previously misspelled as "aray")
- changes the type of references to XML parser in XMP lib to resource
instead of not existing XMLParser
Change-Id: I98c363ebc6658d1f4dcabad97a9a92f3fcd7ea8c