Commit graph

158 commits

Author SHA1 Message Date
Reedy
9d1734fa91 resourceloader: Use AND instead of OR for upsert conds in saveFileDependencies()
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
2019-05-24 13:24:01 +00:00
Reedy
77c7f6391f Pass in __METHOD__ to upsert() in ResourceLoaderModule::saveFileDependencies()
Change-Id: I9cc7636d14dbfc57ad9f21a0d8bbd7dd4c86760d
2019-05-23 23:27:27 +00:00
Thiemo Kreuz
f0d5dceb2c Make some array type hints more specific
Change-Id: Ia9ed6fa851316baa47e73d9a5988a863d15f298c
2019-05-22 13:37:12 +02:00
Timo Tijhof
285a50ca0c resourceloader: Minor clean up in saveFileDependencies()
* Use early return instead of all-encapsulating conditional.

* Document why the try/catch is so big.

Change-Id: Ie19e18556e7ac0a12ad6b979367f8c6b786bbe31
2019-03-06 01:42:16 +00:00
jenkins-bot
2cf45d857e Merge "Avoid use of deprecated ObjectCache::getMainWANInstance method" 2019-03-01 02:58:34 +00:00
Aaron Schulz
a26eee40e0 Avoid use of deprecated ObjectCache::getMainWANInstance method
Change-Id: I429e68c8642a00afa812f5ae900c1fb4f8308528
2019-03-01 02:38:55 +00:00
Thiemo Kreuz
37b3383e8b Remove comments literally repeating the next line of code
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
2019-02-27 17:28:40 +00:00
Timo Tijhof
7a72b16e0f resourceloader: Ignore warnings in JSMinPlus parser
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
2019-02-13 02:11:37 +00:00
Roan Kattouw
fbbd65d2df ResourceLoader: Add support for packageFiles
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
2019-02-05 22:05:02 +00:00
Roan Kattouw
1ed0a109ec resourceloader: Add filter cache version to module version hash
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
2018-09-24 17:10:48 +00:00
Timo Tijhof
450da07f3a resourceloader: Remove MW cacheEpoch from module version hash
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
2018-09-24 17:10:35 +00:00
Timo Tijhof
e42837e977 resourceloader: Remove selective build optimisation from getModuleContent()
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
2018-08-30 21:02:57 +00:00
Timo Tijhof
dc3fc6cf81 resourceloader: Audit use of JSON encoding and use json_encode directly
* 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
2018-08-29 00:46:11 +00:00
Aryeh Gregor
90d4f56fe4 Mass conversion of $wgContLang to service
Brought to you by vim macros.

Bug: T200246
Change-Id: I79e919f4553e3bd3eb714073fed7a43051b4fb2a
2018-08-11 22:44:29 -06:00
Umherirrender
130ec2523d Fix PhanTypeMismatchDeclaredParam
Auto fix MediaWiki.Commenting.FunctionComment.DefaultNullTypeParam sniff

Change-Id: I865323fd0295aabd06f3e3c75e0e5043fb31069e
2018-07-07 00:34:30 +00:00
Timo Tijhof
96d25f6bcc resourceloader: Remove support for Module::getModifiedTime() and getModifiedHash()
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
2018-06-05 02:02:06 +01:00
Timo Tijhof
ee8a5e488e resourceloader: Apply safemode to startup module registry
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
2018-05-19 22:14:33 +02:00
Bartosz Dziewoński
febb1aefe0 resourceloader: Allow style-only modules to have deprecation warnings
The deprecation warning for the module 'mediawiki.ui' (used
e.g. on Special:UserLogin) is now actually shown.

Change-Id: If35a106c77622dbf7e8b5628fbea28f9e7ffd76d
2018-05-17 10:12:12 +00:00
Timo Tijhof
d8b0d0bb30 resourceloader: Remove getHashMtime() and getDefinitionMtime() methods
Deprecated since 1.26, no callers or implementors in Wikimedia Git.

Change-Id: Ie44b4be47db7a4799fe39d66294c41238c62f51f
2018-04-17 01:44:26 +01:00
Max Semenik
369b3fa977 Normalize PHPDoc attributes
Change-Id: I83e686d099de0ff0aacda7e332972e1c7ee49f04
2018-03-16 22:59:15 -07:00
Umherirrender
09cfb1269a resourceloader: Remove ResourceLoaderModule::getPosition
@deprecated since 1.29

Bug: T184257
Change-Id: I1a59a1f0a5fbedfea9f0b28bee8c298710557a8d
2018-02-14 23:50:09 +00:00
Reedy
39f0f919c5 Update suppressWarning()/restoreWarning() calls
Bug: T182273
Change-Id: I9e1b628fe5949ca54258424c2e45b2fb6d491d0f
2018-02-10 08:50:12 +00:00
Reedy
75f250ec55 Update RelPath calls
Bug: T182273
Change-Id: Ifd04e3b3ab72cc56bef48a1fc18fccb34b0af618
2018-01-21 04:34:18 +00:00
jenkins-bot
a18476eab3 Merge "Remove @param comments that literally repeat what the code says" 2018-01-11 23:48:03 +00:00
Thiemo Mättig
ef470ebf7f Remove @param comments that literally repeat what the code says
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
2018-01-10 14:14:26 +01:00
Thiemo Mättig
544122a6c2 Remove self-explaining "section heading" comments from classes
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
2017-12-28 16:12:08 +01:00
Timo Tijhof
3d342d4deb resourceloader: Add support for modules sending preload headers
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
2017-08-03 03:57:00 +00:00
Brad Jorsch
f6466732bb resourceloader: Add ResourceLoaderModule::shouldEmbedModule and use it
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
2017-07-21 17:57:34 +00:00
Umherirrender
b5cddfb27b Remove empty lines at begin of function, if, foreach, switch
Organize phpcs.xml a bit

Change-Id: Ifb767729b481b4b686e6d6444cf48b1f580cc478
2017-07-01 11:34:16 +00:00
Timo Tijhof
483f13b226 resourceloader: Use "\n" instead of ";" as separator for scripts
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
2017-06-28 03:59:05 +00:00
Timo Tijhof
3a748592f8 resourceloader: Add filename to validateScriptFile cache key
* 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
2017-05-13 00:24:40 +00:00
Timo Tijhof
702bce40d0 resourceloader: Simplify validateScriptFile() with getWithSetCallback
* Simplify by using early return and getWithSetCallback.
* Add TTL (previously indefinite, now 1 week).

Bug: T52919
Change-Id: Ic95ba392cdb3bcc8081c77d2c2a3240548bed366
2017-05-12 18:13:15 +00:00
jenkins-bot
aa5eca02b3 Merge "Replace deprecated Context::getStats() with MWServices::getStatsdDataFactory()" 2017-03-20 09:32:48 +00:00
Timo Tijhof
8a7fb8577f resourceloader: Fix broken 'deprecated' string messages
Some used a string value, others an array with 'message' property.
Standardise on the string value, which seems more intuitive.

Change-Id: I5caead7b7017d2bad660db02fb45a54a26bf3728
2017-03-17 17:23:34 -07:00
WMDE-Fisch
7b5f08e703 Replace deprecated Context::getStats() with MWServices::getStatsdDataFactory()
Change-Id: I1756f69ca2ebd301a5049bf758d1a87c37771fe6
2017-03-17 12:07:03 +01:00
Timo Tijhof
0c5b6ecc8f Clean up get_class() in /includes/filerepo and /includes/resourceloader
* get_class()        -> __CLASS__ (same as self::class)
* get_called_class() -> static::class
* get_class($this)   -> static::class

Change-Id: Ic4f9b150ddc35e25f51297de7fc12410d421be4d
2017-03-07 21:30:29 +00:00
jenkins-bot
17eda64357 Merge "includes: Replace implicit Bugzilla bug numbers with Phab ones" 2017-02-28 00:51:57 +00:00
Timo Tijhof
e2c4c40c96 resourceloader: Avoid endless module_deps write for the same value
Follows-up 047b60b96d (ref T111481).

The if-condition compared the expanded paths, not the relative paths.
This meant there were two conditions under which the code will perform
a useless write that inserts *literally* the exact same JSON value.

1. The base directory ($IP) changes after a branch upgrade.
2. Paths contain '../', '//' or other unnormalized paths.

The latter caused various Echo and ULS methods to keep writing the
same value because one of their images is referenced in CSS using
'../'. When inserted in the database as relative path and then
expanded again at run-time and compared to the input value, they
don't match ("$IP/foo/../bar.png" != "$IP/bar.png") and cause a write.

Bug: T158813
Change-Id: I223c232d3a8c4337d09ecf7ec6e5cd7cf7effbff
2017-02-22 22:32:45 +00:00
James D. Forrester
9635dda73a includes: Replace implicit Bugzilla bug numbers with Phab ones
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
2017-02-21 18:13:24 +00:00
Timo Tijhof
68c0eefc85 resourceloader: Limit module_deps write lock to unique index
Follows-up 1d15085bb3.

The column has a unique index for module name and skin/language pair.
Previously the write lock was on module name, which meant that
shortly after deployment, the following happens:

* Files change on disk.
* (1-5min pass)
* First startup module request after 5min http-cache expires. Detects
  one or more changes and updates the version hash of that module.
* Web client subsequently requests this module (if used on that page).
  The first time that request comes in, it's a varnish cache miss
  and will make RL load all files from disk related to that module
  and update the cache index in the module_deps table. At this point
  most popular skin/lang pairs fail, except one. As a result, the
  other rows remain stale.
* (7-30 days varnish expiry pass OR another change to the module deploys)
* Web client requests this module and tries to update its skin/lang pair
  for that module.

One simple change in January 2016 changes jquery.tablesorter to load
a PNG file instead of a GIF file. Now, over a year later, there are
still a dozen skin/lang pairs in enwiki.module_deps with stale data,
which is causing various suble bugs, as well as filesystem calls for
files that don't exist.

Ref T113916 (refactor module_deps).
Ref T158105 (stale cache bug).

Bug: T158105
Change-Id: Ib6c024bfa8d35ce2d622ba4242291daedb507d5e
2017-02-15 20:52:28 +00:00
Timo Tijhof
e7b57d881a resourceloader: Use upsert() instead of replace() for module_deps write
This should perform better and reduce internal lock contention on the
database server.

Bug: T158105
Change-Id: I1acfb0630946283b317cb929e8d7c3b2af757ecf
2017-02-15 20:52:19 +00:00
addshore
b12086b618 Get ConfigFactory & MainConfig from MediaWikiServices
Change-Id: Iafdd7e00747060572463ffb05aae4543f3a06163
2016-11-23 00:12:38 +00:00
Timo Tijhof
bc374082fa resourceloader: Remove top/bottom queue distinction
* The styles queue has always been top-only
  (except for a few months in 2015).
* The top queue loads asynchronous since mid-2015. (T107399)
  And LocalStorage eval, previously the last remaining non-async part
  of module loading, is also async as of October 2016. (T142129)

* This change merges the bottom 'mw.loader.load()' queue with the top queue.
  It also moves any other snippets potentially in the bottom queue still:
  - embed: I couldn't find any private modules with position=bottom
     (doesn't make sense due to their blocking nature). If any do exist,
     (third-party extensions?), they'll now be embedded in the <head>.
  - scripts: Any legacy 'only=scripts' requests will now initiate
     from the <head>.

Bug: T109837
Change-Id: I6c21e3e47c23df33a04c42ce94bd4c1964599c7f
2016-11-16 19:29:16 +00:00
Kunal Mehta
61adc1e146 Use namespaced ScopedCallback
The un-namespaced \ScopedCallback is deprecated.

Change-Id: Ie014d5a775ead66335a24acac9d339915884d1a4
2016-10-17 15:46:05 -07:00
Aaron Schulz
a2790b1b80 Remove wfGetCaller() dependency from DatabaseBase
Change-Id: I3e240b2eb5c1f6a21f1bc974c3d28f5755c7451a
2016-09-15 14:40:00 -07:00
Amir Sarabadani
d56829dca8 Clean up array() syntax from docs, part VI
Change-Id: Ib0eea494e2065c7ab356dc45fd174544a9c1c942
2016-09-12 14:36:37 +04:30
Aaron Schulz
fdd40afc42 Avoid "No transaction is active" saveFileDependencies() tests errors
Unit tests run in CLI mode without DBO_TRX

Change-Id: Icee9cf84cb9e057b329dd3960fcc9b238af478a3
2016-09-11 20:46:43 -07:00
Aaron Schulz
950cf6016c Rename DB_SLAVE constant to DB_REPLICA
This is more consistent with LoadBalancer, modern, and inclusive
of master/master mysql, NDB cluster, and MariaDB galera cluster.

The old constant is an alias now.

Change-Id: I0b37299ecb439cc446ffbe8c341365d1eef45849
2016-09-05 22:55:53 -07:00
Amir Sarabadani
6b221fa96a Clean up array() syntax in docs, part IV
Change-Id: If626409a93d31bf90c054c9bf7ba44a78ea9a621
2016-08-26 16:06:58 +04:30
jdlrobson
8af960e484 resourceloader: Implement 'deprecated' option for FileModule
ResourceLoader modules can now carry a 'deprecated' option which can
be a boolean or an object with message key. This message or a default
deprecation message will be show whenever that module is used in production.

Note: This will not work in debug mode for ResourceLoaderFile modules
and this is deemed acceptable for the time being. We can revisit later.

Bug: T137772
Change-Id: Ib9ebd2d39a59fd41d8537e06884699f77b03580c
2016-08-04 18:01:53 +00:00