About 1.5% of load.php wall-time is spent in isFileModule() calls
during the ServiceWiring/getResourceLoader/register call early on.
Reduce the overhead of this cost by moving that logic to the Module
class.
There are two costs that we save this way:
1. The inherent cost of applying the skinStyles.
This is now limited to only the modules that are constructed in a
given web request. Thus, apart from the startup response (which
constructs all modules), for regular load.php requests and all
index.php page views, the vast majority of modules will never need
to be constructed, and thus won't pay this cost.
2. The overhead of predicting (and class-loading) for whether a module
is (or will become) a FileModule object.
This is what isFileModule() does and is the main reason I wrote
this patch. It involves class loading, and checks and conditions that
run 1000+ times at WMF. This is eliminated now because we no longer
have to calculate this decision. Instead, the logic applies when
it needs to (due to FileModule implementing it), and doesn't
when it doesn't!
Change-Id: Ia2db14f930800c96e767b94ef62fb00e9d52725b
We’re appending at least a closing brace to the source code, so if that
code ends with a line comment, we need to have a line break between the
end of the code and our appended brace.
Bug: T286996
Change-Id: I4e93b10f31445f6dab76c1614e546fb41fd6c0f6
Follows-up c9318edc2 (in MW 1.34) which deprecated constructing the
ResourceLoader service without a Config object.
Bug: T32956
Change-Id: Ica3fb505bff365d69fe467db32495f5fcd8a702e
- JavaScriptMinifier: The public interface for this internal class is
ResourceLoader::filter which, except for one caller (minify.php)
is indeed consistently used already, no other callers need replacing.
- CSSMin: Idem for minification, however, this class has some other
method as well, which have a number of internal users, but none
outside core. These have all been replaced in this commit.
- Remove pear/net_url2 as own dependency as this was only used by CSSMin
and recently added there. This is now a dependency of wikimedia/minify
instead. This was not part of the public API and no longer mentioned
here in composer.json or RELEASE-NOTES. (It remains pinned in
mediawiki-vendor, however.)
Bug: T273247
Depends-On: Iadff8c2112d5e53bd994ab4882006e8c644a2379
Depends-On: Id3c6dcc0b952a9efe34b3a9ed88b716101a51f87
Depends-On: I589be910f57289fd908b22db87241b0e52da60d4
Change-Id: I8d71fc64aeecdb31db218b02e361ae9bb0d19b48
This is micro-optimization of closure code to avoid binding the closure
to $this where it is not needed.
Created by I25a17fb22b6b669e817317a0f45051ae9c608208
Change-Id: I0ffc6200f6c6693d78a3151cb8cea7dce7c21653
The canonical way to enable debug mode is and will remain
through via 'debug=true'.
During the transition debug=2 will opt you in to the experimental
newer way. Anything that needs to be pinned to the old way for
compat can already start doing so by using debug=1 explicitly.
Once v2 is "ready", the default will flip and debug=1 will remain
for the foreseeable future to trigger the legacy behaviours.
Bug: T85805
Change-Id: Ieaf04e0c289646dd5d5b027b4f1f8278167b2d57
- Restructure as a more readable and easier to scan list,
rather than with large sections.
- Move examples out to their own section, and remove or combine
trivial examples.
- Link to mediawiki.org docs for Package files,
and document when the feature was added (since 1.33).
- Document the "factory" option, and use the same format
for specifying when it was added.
- Add more @see references to this for discovery.
(The @see syntax is required for Doxygen to link variables,
unlike class names which can be linked bare from class/method
descriptions.)
Bug: T232566
Change-Id: Idb295d034c0afbd75cc1f57bbed163654bda2ab5
This includes fixing some mistakes, as well as removing
redundant text that doesn't add new information, either because
it literally repeats what the code already says, or is actually
duplicated.
Change-Id: I3a8dd8ce57192deda8916cc444c87d7ab1a36515
Also move ResourceLoaderRegisterModulesHook under the same
namespace. I forgot this one in commit b7ac554304.
This is mainly motivated by making the collaboration graph
on doc.wikimedia.org not huge by pulling in the full range
of core hook interfaces.
<https://doc.wikimedia.org/mediawiki-core/master/php/classResourceLoader.html>
Depends-On: Ifa53d96dd3e4592208dbc991e2af9e6b7598e44d
Depends-On: Ib4571d80f55a4716e28b76ba1d007f95b0fb2540
Change-Id: I576305a5edb36a2ffb513e6d557bbf1d337cb17e
Add the SkinLessImportPaths attribute for skin-specific LESS import
paths, which skins can use to override the mediawiki.skin.variables.less
file.
As a starting point, add the following 5 variables:
* device widths (3x)
To help phase out 'mediawiki.ui/variables'. These are
commonly used by MobileFrontend.
* @font-family-sans
Recommended by Volker. Used by multiple skins.
* @border-radius-base
Recommended by Volker as example of something that we currently
hardcode in MediaWiki core for Vector and OOUI/WikimediaUI
in 'mediawiki.widgets.datetime' but should instead be allowed
to vary by skin and OOUI theme.
Remove the hardcoded value for '@border-radius-base' in
various places in favour of importing from mediawiki.skin.
The default is a bare default of 0 (as border-radius is off
by default in the browser).
The value for Vector is restored there by I47da304667811.
The value for MonoBook is improved by I000f319ab31b.
Bug: T112747
Change-Id: Icf86c930a3b5524254bb549624737d3b9dccb032
Also fix the bug where the fallback in ResourceLoader::filter
did not work for the cache=false case.
Change-Id: Iffe4cdd7b847f2a22aeaff2cf61c2104ec217f04
* 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
Migrate all callers of Hooks::run() to use the new
HookContainer/HookRunner system.
General principles:
* Use DI if it is already used. We're not changing the way state is
managed in this patch.
* HookContainer is always injected, not HookRunner. HookContainer
is a service, it's a more generic interface, it is the only
thing that provides isRegistered() which is needed in some cases,
and a HookRunner can be efficiently constructed from it
(confirmed by benchmark). Because HookContainer is needed
for object construction, it is also needed by all factories.
* "Ask your friendly local base class". Big hierarchies like
SpecialPage and ApiBase have getHookContainer() and getHookRunner()
methods in the base class, and classes that extend that base class
are not expected to know or care where the base class gets its
HookContainer from.
* ProtectedHookAccessorTrait provides protected getHookContainer() and
getHookRunner() methods, getting them from the global service
container. The point of this is to ease migration to DI by ensuring
that call sites ask their local friendly base class rather than
getting a HookRunner from the service container directly.
* Private $this->hookRunner. In some smaller classes where accessor
methods did not seem warranted, there is a private HookRunner property
which is accessed directly. Very rarely (two cases), there is a
protected property, for consistency with code that conventionally
assumes protected=private, but in cases where the class might actually
be overridden, a protected accessor is preferred over a protected
property.
* The last resort: Hooks::runner(). Mostly for static, file-scope and
global code. In a few cases it was used for objects with broken
construction schemes, out of horror or laziness.
Constructors with new required arguments:
* AuthManager
* BadFileLookup
* BlockManager
* ClassicInterwikiLookup
* ContentHandlerFactory
* ContentSecurityPolicy
* DefaultOptionsManager
* DerivedPageDataUpdater
* FullSearchResultWidget
* HtmlCacheUpdater
* LanguageFactory
* LanguageNameUtils
* LinkRenderer
* LinkRendererFactory
* LocalisationCache
* MagicWordFactory
* MessageCache
* NamespaceInfo
* PageEditStash
* PageHandlerFactory
* PageUpdater
* ParserFactory
* PermissionManager
* RevisionStore
* RevisionStoreFactory
* SearchEngineConfig
* SearchEngineFactory
* SearchFormWidget
* SearchNearMatcher
* SessionBackend
* SpecialPageFactory
* UserNameUtils
* UserOptionsManager
* WatchedItemQueryService
* WatchedItemStore
Constructors with new optional arguments:
* DefaultPreferencesFactory
* Language
* LinkHolderArray
* MovePage
* Parser
* ParserCache
* PasswordReset
* Router
setHookContainer() now required after construction:
* AuthenticationProvider
* ResourceLoaderModule
* SearchEngine
Change-Id: Id442b0dbe43aba84bd5cf801d86dedc768b082c7
Follows-up I6da55e78d5. The makeKey() call was accidentally lost,
thus the locks became shared across all wikis.
Bug: T113916
Bug: T247028
Change-Id: Id459120965c9a6d3b68a028d2c69dc042277b5d2
Follows-up f5aaf75ad1.
* Improve some docs for these hooks.
* Add type hints.
* Add them as a subgroup within the ResourceLoader docgroup
for easy navigation.
Bug: T246855
Change-Id: I52f31e2b63dcf265b27e68ba8fd4f885d82088ac
This will make it easy to later allow the user to select which
component's specs to load and run (via CLI and GUI), e.g. for
an entire extension. We currently only have very narrow or very
wide selection mechanisms ('module' param for 1 module,
'rerun' for 1 test case, 'filter' param for global pattern match).
Bug: T250045
Depends-On: I55fe27e1c74972fcb3cdafefdc78e10e24f95b80
Change-Id: I5c01f720d787c3847228de511ce913284786ad66
Instead of exporting this as a global variable, export it as an extension
attribute.
The $wgResourceModuleSkinStyles configuration variable will continue
to be supported for its main purpose of setting skin styles. However
it may no longer be used to read these settings. The canonical copy
of this is now restricted to the ResourceLoader class and not (yet)
made publicly available (I found no use cases for it).
This opens the door to making it lazy-loaded attribute, which would help
reduce the size of the "main" APCu cache key for ExtensionRegistry.
This is not possible with global variables as those must be exported
unconditionally from Setup.php.
Bug: T32956
Bug: T247265
Change-Id: I4ecf558d9c630c91959786d2573c34e619223cef
This should be the exact same. Its more a style change than anything.
So why do it then?
* I believe this is much less confusing than code mentioning a weird
"standard class". Barely anybody knows what this is, and what the
difference between "object" and "stdClass" is.
* The code is shorter.
* It's even faster. In my micro benchmark it's twice as fast.
Change-Id: I7ee0e8ae6d9264a89b6cd1dd861f0466ae620ccc
* 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
This allows us to move things that are not used on every request (e.g.
'TrackingCategories') into separate cache entries to slim down the main
one.
At the same time, fold getLazyLoadedAttribute() into the standard and
already established getAttribute(), so that client code doesn't need to
be aware of whether something is lazy-loaded or not, it'll just work.
Everything is still cached using the load queue as part of the cache key
for instant invalidation, so if an extension.json file changes, the
lazy-loaded attribute cache will invalidate too.
The cache is populated whenever loadFromQueue() happens, but if it
happens to fall out of the cache, then getLazyLoadedAttribute() will
iterate over all the loaded extension/skin.json files to read that
value. Since we end up reading everything, we populate all of the
caches again.
The caching logic was split into two more private functions
(::getCache() and ::makeCacheKey()) for easier internal reuse.
Bug: T220994
Change-Id: I290926bbedfc964195d1f576a9e06349f9e5d5ea
This can be enabled via a configuration flag. Otherwise, SqlModuleDependencyStore
will be used in order to keep using the module_deps table.
Create a dependency store class, wrapping BagOStuff, that stores known module
dependencies. Inject it into ResourceLoader and inject the path lists into
ResourceLoaderModule directly and via callback.
Bug: T113916
Change-Id: I6da55e78d5554e30e5df6b4bc45d84817f5bea15
`$this->getModule()` returns a RL object or a null. The check above already
makes sure that $module is not null so we can just set file dependencies
from the RL object returned.
In addition, this is an optimization as we reduce repeated calls to
`$this->getModule()`. Similar logic already exist in the same file from
L#116 - L#118.
Change-Id: If50c28ff5cd8eb435c9fa4f277e2d1038b52ca74
This data isn't needed for startup, and we can shave off a few K from
startup by moving it to mediawiki.base instead.
It was requested that this be done as a "package file", which
necessitated some other minor structural changes to mediawiki.base as
well.
Bug: T235350
Change-Id: I525a5203533089d5a542f83a847be58a10cb6319
These attributes are only accessed at a time when performance isn't
critical (e.g. tests), so we can skip caching them and read each
extension.json file again when we do need them.
At the same time, we want to reduce the size of the array that we're
caching due to PHP 7 performance regressions with APC (T187154).
'QUnitModules' is the first attribute to be converted into a lazy-loaded
attribute.
Bug: T220994
Change-Id: I224cdace05dbac00ff947c41daecb74b07c967bb
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
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
These are almost only doc changes, with two exceptions:
1-In LinkHolderArray, int-alike array keys are now cast to int, to be uniform with what we do in other code paths
2-In ExtensionRegistration, changed a line to throw an Exception
immediately, instead of an ExtensionDependencyError. This is because the
latter takes an array with msg and type, but we were passing it a plain
string (and in fact the code was bugged).
Bug: T231636
Change-Id: I8b0ef50d279c2a87490dde6a467a4e22c0710afd
ResourceLoader::getLessVars is deprecated since ca510f742 included in
MW 1.32 and hard-deprecated since 1b32592d9 included in MW 1.34.
Bug: T140804
Change-Id: If88c71ed7fdf3c6a5cf89a50197e246c201ebaa2