r77011 MediaWiki - Code Review archive

Repository:MediaWiki
Revision:r77010‎ | r77011 | r77012 >
Date:10:41, 19 November 2010
Author:tstarling
Status:resolved (Comments)
Tags:
Comment:
* Made Resources.php return a pure-data array instead of an ugly mix of data and code. This allows the class code to be lazy-loaded with the autoloader, for a performance advantage especially on non-APC installs. And using the convention where if the class is omitted, ResourceLoaderFileModule is assumed, the registration code becomes shorter and simpler.
* Modified ResourceLoader to lazy-initialise module objects, for a further performance advantage.
* Deleted ResourceLoader::getModules(), provided getModuleNames() instead. Although the startup module needs this functionality, it's slow to generate, so to avoid misuse, it's better to provide a foolproof fast interface and let the startup module do the slow thing itself.
* Modified ResourceLoader::register() to optionally accept an info array instead of an object.
* Added $wgResourceModules, allowing extensions to efficiently define their own resource loader modules. The trouble with hooks is that they contain code, and code is slow. We've been through all this before with i18n. Hooks are useful as a performance tool only if you call them very rarely.
* Moved ResourceLoader settings to their own section in DefaultSettings.php
* Added options to ResourceLoaderFileModule equivalent to the $localBasePath and $remoteBasePath parameters, to allow it to be instantiated via the new array style. Also added remoteExtPath, which allows modules to be registered before $wgExtensionAssetsPath is known.
* Added OutputPage::getResourceLoader(), mostly for debugging.
* The time saving at the moment is about 5ms per request with no extensions, which is significant already with 6 load.php requests for a cold cache page view. This is a much more scalable interface; the relative saving will grow as more extensions are added which use this interface, especially for non-APC installs.

Although the interface is backwards compatible, extension updates will follow in a subsequent commit.
Modified paths:
  • /trunk/phase3/includes/DefaultSettings.php (modified) (history)
  • /trunk/phase3/includes/OutputPage.php (modified) (history)
  • /trunk/phase3/includes/resourceloader/ResourceLoader.php (modified) (history)
  • /trunk/phase3/includes/resourceloader/ResourceLoaderFileModule.php (modified) (history)
  • /trunk/phase3/includes/resourceloader/ResourceLoaderStartUpModule.php (modified) (history)
  • /trunk/phase3/resources/Resources.php (modified) (history)

Diff [purge]

Index: trunk/phase3/includes/OutputPage.php
@@ -2290,6 +2290,16 @@
22912291 }
22922292
22932293 /**
 2294+ * Get a ResourceLoader object associated with this OutputPage
 2295+ */
 2296+ public function getResourceLoader() {
 2297+ if ( is_null( $this->mResourceLoader ) ) {
 2298+ $this->mResourceLoader = new ResourceLoader();
 2299+ }
 2300+ return $this->mResourceLoader;
 2301+ }
 2302+
 2303+ /**
22942304 * TODO: Document
22952305 * @param $skin Skin
22962306 * @param $modules Array/string with the module name
@@ -2301,9 +2311,6 @@
23022312 global $wgUser, $wgLang, $wgLoadScript, $wgResourceLoaderUseESI,
23032313 $wgResourceLoaderInlinePrivateModules;
23042314 // Lazy-load ResourceLoader
2305 - if ( is_null( $this->mResourceLoader ) ) {
2306 - $this->mResourceLoader = new ResourceLoader();
2307 - }
23082315 // TODO: Should this be a static function of ResourceLoader instead?
23092316 // TODO: Divide off modules starting with "user", and add the user parameter to them
23102317 $query = array(
@@ -2335,8 +2342,9 @@
23362343
23372344 // Create keyed-by-group list of module objects from modules list
23382345 $groups = array();
 2346+ $resourceLoader = $this->getResourceLoader();
23392347 foreach ( (array) $modules as $name ) {
2340 - $module = $this->mResourceLoader->getModule( $name );
 2348+ $module = $resourceLoader->getModule( $name );
23412349 $group = $module->getGroup();
23422350 if ( !isset( $groups[$group] ) ) {
23432351 $groups[$group] = array();
@@ -2352,15 +2360,15 @@
23532361 }
23542362 // Support inlining of private modules if configured as such
23552363 if ( $group === 'private' && $wgResourceLoaderInlinePrivateModules ) {
2356 - $context = new ResourceLoaderContext( $this->mResourceLoader, new FauxRequest( $query ) );
 2364+ $context = new ResourceLoaderContext( $resourceLoader, new FauxRequest( $query ) );
23572365 if ( $only == 'styles' ) {
23582366 $links .= Html::inlineStyle(
2359 - $this->mResourceLoader->makeModuleResponse( $context, $modules )
 2367+ $resourceLoader->makeModuleResponse( $context, $modules )
23602368 );
23612369 } else {
23622370 $links .= Html::inlineScript(
23632371 ResourceLoader::makeLoaderConditionalScript(
2364 - $this->mResourceLoader->makeModuleResponse( $context, $modules )
 2372+ $resourceLoader->makeModuleResponse( $context, $modules )
23652373 )
23662374 );
23672375 }
@@ -2371,7 +2379,7 @@
23722380 // we can ensure cache misses on change
23732381 if ( $group === 'user' || $group === 'site' ) {
23742382 // Create a fake request based on the one we are about to make so modules return correct times
2375 - $context = new ResourceLoaderContext( $this->mResourceLoader, new FauxRequest( $query ) );
 2383+ $context = new ResourceLoaderContext( $resourceLoader, new FauxRequest( $query ) );
23762384 // Get the maximum timestamp
23772385 $timestamp = 1;
23782386 foreach ( $modules as $module ) {
Index: trunk/phase3/includes/resourceloader/ResourceLoader.php
@@ -32,6 +32,8 @@
3333
3434 /** Array: List of module name/ResourceLoaderModule object pairs */
3535 protected $modules = array();
 36+ /** Associative array mapping module name to info associative array */
 37+ protected $moduleInfos = array();
3638
3739 /* Protected Methods */
3840
@@ -67,7 +69,7 @@
6870 // Set modules' dependecies
6971 $modulesWithDeps = array();
7072 foreach ( $res as $row ) {
71 - $this->modules[$row->md_module]->setFileDependencies( $skin,
 73+ $this->getModule( $row->md_module )->setFileDependencies( $skin,
7274 FormatJson::decode( $row->md_deps, true )
7375 );
7476 $modulesWithDeps[] = $row->md_module;
@@ -75,14 +77,14 @@
7678
7779 // Register the absence of a dependency row too
7880 foreach ( array_diff( $modules, $modulesWithDeps ) as $name ) {
79 - $this->modules[$name]->setFileDependencies( $skin, array() );
 81+ $this->getModule( $name )->setFileDependencies( $skin, array() );
8082 }
8183
8284 // Get message blob mtimes. Only do this for modules with messages
8385 $modulesWithMessages = array();
8486 $modulesWithoutMessages = array();
8587 foreach ( $modules as $name ) {
86 - if ( count( $this->modules[$name]->getMessages() ) ) {
 88+ if ( count( $this->getModule( $name )->getMessages() ) ) {
8789 $modulesWithMessages[] = $name;
8890 } else {
8991 $modulesWithoutMessages[] = $name;
@@ -95,11 +97,11 @@
9698 ), __METHOD__
9799 );
98100 foreach ( $res as $row ) {
99 - $this->modules[$row->mr_resource]->setMsgBlobMtime( $lang, $row->mr_timestamp );
 101+ $this->getModule( $row->mr_resource )->setMsgBlobMtime( $lang, $row->mr_timestamp );
100102 }
101103 }
102104 foreach ( $modulesWithoutMessages as $name ) {
103 - $this->modules[$name]->setMsgBlobMtime( $lang, 0 );
 105+ $this->getModule( $name )->setMsgBlobMtime( $lang, 0 );
104106 }
105107 }
106108
@@ -172,7 +174,7 @@
173175 * Registers core modules and runs registration hooks.
174176 */
175177 public function __construct() {
176 - global $IP;
 178+ global $IP, $wgResourceModules;
177179
178180 wfProfileIn( __METHOD__ );
179181
@@ -180,6 +182,7 @@
181183 $this->register( include( "$IP/resources/Resources.php" ) );
182184 // Register extension modules
183185 wfRunHooks( 'ResourceLoaderRegisterModules', array( &$this ) );
 186+ $this->register( $wgResourceModules );
184187
185188 wfProfileOut( __METHOD__ );
186189 }
@@ -188,30 +191,27 @@
189192 * Registers a module with the ResourceLoader system.
190193 *
191194 * @param $name Mixed: Name of module as a string or List of name/object pairs as an array
192 - * @param $object ResourceLoaderModule: Module object (optional when using
193 - * multiple-registration calling style)
 195+ * @param $info Module info array. For backwards compatibility with 1.17alpha,
 196+ * this may also be a ResourceLoaderModule object. Optional when using
 197+ * multiple-registration calling style.
194198 * @throws MWException: If a duplicate module registration is attempted
195199 * @throws MWException: If something other than a ResourceLoaderModule is being registered
196200 * @return Boolean: False if there were any errors, in which case one or more modules were not
197201 * registered
198202 */
199 - public function register( $name, ResourceLoaderModule $object = null ) {
200 -
 203+ public function register( $name, $info = null ) {
201204 wfProfileIn( __METHOD__ );
202205
203206 // Allow multiple modules to be registered in one call
204 - if ( is_array( $name ) && !isset( $object ) ) {
 207+ if ( is_array( $name ) ) {
205208 foreach ( $name as $key => $value ) {
206209 $this->register( $key, $value );
207210 }
208 -
209 - wfProfileOut( __METHOD__ );
210 -
211211 return;
212212 }
213213
214214 // Disallow duplicate registrations
215 - if ( isset( $this->modules[$name] ) ) {
 215+ if ( isset( $this->moduleInfos[$name] ) ) {
216216 // A module has already been registered by this name
217217 throw new MWException(
218218 'ResourceLoader duplicate registration error. ' .
@@ -219,26 +219,32 @@
220220 );
221221 }
222222
223 - // Validate the input (type hinting lets null through)
224 - if ( !( $object instanceof ResourceLoaderModule ) ) {
225 - throw new MWException( 'ResourceLoader invalid module error. ' .
226 - 'Instances of ResourceLoaderModule expected.' );
 223+ // Attach module
 224+ if ( is_object( $info ) ) {
 225+ // Old calling convention
 226+ // Validate the input
 227+ if ( !( $info instanceof ResourceLoaderModule ) ) {
 228+ throw new MWException( 'ResourceLoader invalid module error. ' .
 229+ 'Instances of ResourceLoaderModule expected.' );
 230+ }
 231+
 232+ $this->moduleInfos[$name] = array( 'object' => $info );
 233+ $this->modules[$name] = $info;
 234+ } else {
 235+ // New calling convention
 236+ $this->moduleInfos[$name] = $info;
227237 }
228238
229 - // Attach module
230 - $this->modules[$name] = $object;
231 - $object->setName( $name );
232 -
233239 wfProfileOut( __METHOD__ );
234240 }
235241
236 - /**
237 - * Gets a map of all modules and their options
 242+ /**
 243+ * Get a list of module names
238244 *
239 - * @return Array: List of modules keyed by module name
 245+ * @return Array: List of module names
240246 */
241 - public function getModules() {
242 - return $this->modules;
 247+ public function getModuleNames() {
 248+ return array_keys( $this->moduleInfos );
243249 }
244250
245251 /**
@@ -248,7 +254,29 @@
249255 * @return Mixed: ResourceLoaderModule if module has been registered, null otherwise
250256 */
251257 public function getModule( $name ) {
252 - return isset( $this->modules[$name] ) ? $this->modules[$name] : null;
 258+ if ( !isset( $this->modules[$name] ) ) {
 259+ if ( !isset( $this->moduleInfos[$name] ) ) {
 260+ // No such module
 261+ return null;
 262+ }
 263+ // Construct the requested object
 264+ $info = $this->moduleInfos[$name];
 265+ if ( isset( $info['object'] ) ) {
 266+ // Object given in info array
 267+ $object = $info['object'];
 268+ } else {
 269+ if ( !isset( $info['class'] ) ) {
 270+ $class = 'ResourceLoaderFileModule';
 271+ } else {
 272+ $class = $info['class'];
 273+ }
 274+ $object = new $class( $info );
 275+ }
 276+ $object->setName( $name );
 277+ $this->modules[$name] = $object;
 278+ }
 279+
 280+ return $this->modules[$name];
253281 }
254282
255283 /**
@@ -265,8 +293,8 @@
266294 $modules = array();
267295 $missing = array();
268296 foreach ( $context->getModules() as $name ) {
269 - if ( isset( $this->modules[$name] ) ) {
270 - $modules[$name] = $this->modules[$name];
 297+ if ( isset( $this->moduleInfos[$name] ) ) {
 298+ $modules[$name] = $this->getModule( $name );
271299 } else {
272300 $missing[] = $name;
273301 }
@@ -376,7 +404,7 @@
377405 if ( $context->shouldIncludeStyles() ) {
378406 $styles = $module->getStyles( $context );
379407 // Flip CSS on a per-module basis
380 - if ( $styles && $this->modules[$name]->getFlip( $context ) ) {
 408+ if ( $styles && $module->getFlip( $context ) ) {
381409 foreach ( $styles as $media => $style ) {
382410 $styles[$media] = $this->filter( 'flip-css', $style );
383411 }
Index: trunk/phase3/includes/resourceloader/ResourceLoaderFileModule.php
@@ -105,6 +105,12 @@
106106 *
107107 * @example $options
108108 * array(
 109+ * // Base path to prepend to all local paths in $options. Defaults to $IP
 110+ * 'localBasePath' => [base path],
 111+ * // Base path to prepend to all remote paths in $options. Defaults to $wgScriptPath
 112+ * 'remoteBasePath' => [base path],
 113+ * // Equivalent of remoteBasePath, but relative to $wgExtensionAssetsPath
 114+ * 'remoteExtPath' => [base path],
109115 * // Scripts to always include
110116 * 'scripts' => [file path string or array of file path strings],
111117 * // Scripts to include in specific language contexts
@@ -139,6 +145,12 @@
140146 global $IP, $wgScriptPath;
141147 $this->localBasePath = $localBasePath === null ? $IP : $localBasePath;
142148 $this->remoteBasePath = $remoteBasePath === null ? $wgScriptPath : $remoteBasePath;
 149+
 150+ if ( isset( $options['remoteExtPath'] ) ) {
 151+ global $wgExtensionAssetsPath;
 152+ $this->remoteBasePath = $wgExtensionAssetsPath . '/' . $options['remoteExtPath'];
 153+ }
 154+
143155 foreach ( $options as $member => $option ) {
144156 switch ( $member ) {
145157 // Lists of file paths
@@ -175,6 +187,8 @@
176188 break;
177189 // Single strings
178190 case 'group':
 191+ case 'localBasePath':
 192+ case 'remoteBasePath':
179193 $this->{$member} = (string) $option;
180194 break;
181195 // Single booleans
Index: trunk/phase3/includes/resourceloader/ResourceLoaderStartUpModule.php
@@ -101,7 +101,9 @@
102102
103103 $out = '';
104104 $registrations = array();
105 - foreach ( $context->getResourceLoader()->getModules() as $name => $module ) {
 105+ $resourceLoader = $context->getResourceLoader();
 106+ foreach ( $resourceLoader->getModuleNames() as $name ) {
 107+ $module = $resourceLoader->getModule( $name );
106108 // Support module loader scripts
107109 $loader = $module->getLoaderScript();
108110 if ( $loader !== false ) {
@@ -193,7 +195,9 @@
194196 // infinite recursion - think carefully before making changes to this
195197 // code!
196198 $time = wfTimestamp( TS_UNIX, $wgCacheEpoch );
197 - foreach ( $context->getResourceLoader()->getModules() as $module ) {
 199+ $loader = $context->getResourceLoader();
 200+ foreach ( $loader->getModuleNames() as $name ) {
 201+ $module = $loader->getModule( $name );
198202 $time = max( $time, $module->getModifiedTime( $context ) );
199203 }
200204 return $this->modifiedTime[$hash] = $time;
Index: trunk/phase3/includes/DefaultSettings.php
@@ -1646,42 +1646,6 @@
16471647 */
16481648 $wgClockSkewFudge = 5;
16491649
1650 -/**
1651 - * Maximum time in seconds to cache resources served by the resource loader
1652 - */
1653 -$wgResourceLoaderMaxage = array(
1654 - 'versioned' => array(
1655 - // Squid/Varnish but also any other public proxy cache between the client and MediaWiki
1656 - 'server' => 30 * 24 * 60 * 60, // 30 days
1657 - // On the client side (e.g. in the browser cache).
1658 - 'client' => 30 * 24 * 60 * 60, // 30 days
1659 - ),
1660 - 'unversioned' => array(
1661 - 'server' => 5 * 60, // 5 minutes
1662 - 'client' => 5 * 60, // 5 minutes
1663 - ),
1664 -);
1665 -
1666 -/**
1667 - * Whether to embed private modules inline with HTML output or to bypass
1668 - * caching and check the user parameter against $wgUser to prevent
1669 - * unauthorized access to private modules.
1670 - */
1671 -$wgResourceLoaderInlinePrivateModules = true;
1672 -
1673 -/**
1674 - * The default debug mode (on/off) for of ResourceLoader requests. This will still
1675 - * be overridden when the debug URL parameter is used.
1676 - */
1677 -$wgResourceLoaderDebug = false;
1678 -
1679 -/**
1680 - * Enable embedding of certain resources using Edge Side Includes. This will
1681 - * improve performance but only works if there is something in front of the
1682 - * web server (e..g a Squid or Varnish server) configured to process the ESI.
1683 - */
1684 -$wgResourceLoaderUseESI = false;
1685 -
16861650 /** @} */ # end of cache settings
16871651
16881652 /************************************************************************//**
@@ -2320,6 +2284,65 @@
23212285 /** @} */ # End of output format settings }
23222286
23232287 /*************************************************************************//**
 2288+ * @name Resource loader settings
 2289+ * @{
 2290+ */
 2291+
 2292+/**
 2293+ * Client-side resource modules. Extensions should add their module definitions
 2294+ * here.
 2295+ *
 2296+ * Example:
 2297+ * $wgResourceModules['ext.myExtension'] = array(
 2298+ * 'scripts' => 'myExtension.js',
 2299+ * 'styles' => 'myExtension.css',
 2300+ * 'dependencies' => array( 'jquery.cookie', 'jquery.tabIndex' ),
 2301+ * 'localBasePath' => dirname( __FILE ),
 2302+ * 'remoteExtPath' => 'MyExtension',
 2303+ * );
 2304+ */
 2305+$wgResourceModules = array();
 2306+
 2307+/**
 2308+ * Maximum time in seconds to cache resources served by the resource loader
 2309+ */
 2310+$wgResourceLoaderMaxage = array(
 2311+ 'versioned' => array(
 2312+ // Squid/Varnish but also any other public proxy cache between the client and MediaWiki
 2313+ 'server' => 30 * 24 * 60 * 60, // 30 days
 2314+ // On the client side (e.g. in the browser cache).
 2315+ 'client' => 30 * 24 * 60 * 60, // 30 days
 2316+ ),
 2317+ 'unversioned' => array(
 2318+ 'server' => 5 * 60, // 5 minutes
 2319+ 'client' => 5 * 60, // 5 minutes
 2320+ ),
 2321+);
 2322+
 2323+/**
 2324+ * Whether to embed private modules inline with HTML output or to bypass
 2325+ * caching and check the user parameter against $wgUser to prevent
 2326+ * unauthorized access to private modules.
 2327+ */
 2328+$wgResourceLoaderInlinePrivateModules = true;
 2329+
 2330+/**
 2331+ * The default debug mode (on/off) for of ResourceLoader requests. This will still
 2332+ * be overridden when the debug URL parameter is used.
 2333+ */
 2334+$wgResourceLoaderDebug = false;
 2335+
 2336+/**
 2337+ * Enable embedding of certain resources using Edge Side Includes. This will
 2338+ * improve performance but only works if there is something in front of the
 2339+ * web server (e..g a Squid or Varnish server) configured to process the ESI.
 2340+ */
 2341+$wgResourceLoaderUseESI = false;
 2342+
 2343+/** @} */ # End of resource loader settings }
 2344+
 2345+
 2346+/*************************************************************************//**
23242347 * @name Page title and interwiki link settings
23252348 * @{
23262349 */
Index: trunk/phase3/resources/Resources.php
@@ -4,89 +4,85 @@
55
66 /* Special resources who have their own classes */
77
8 - 'site' => new ResourceLoaderSiteModule,
9 - 'startup' => new ResourceLoaderStartUpModule,
10 - 'user' => new ResourceLoaderUserModule,
11 - 'user.options' => new ResourceLoaderUserOptionsModule,
 8+ 'site' => array( 'class' => 'ResourceLoaderSiteModule' ),
 9+ 'startup' => array( 'class' => 'ResourceLoaderStartUpModule' ),
 10+ 'user' => array( 'class' => 'ResourceLoaderUserModule' ),
 11+ 'user.options' => array( 'class' => 'ResourceLoaderUserOptionsModule' ),
1212
1313 /* Skins */
1414
15 - 'skins.vector' => new ResourceLoaderFileModule(
16 - array( 'styles' => array( 'skins/vector/screen.css' => array( 'media' => 'screen' ) ) )
 15+ 'skins.vector' => array(
 16+ 'styles' => array( 'skins/vector/screen.css' => array( 'media' => 'screen' ) )
1717 ),
18 - 'skins.monobook' => new ResourceLoaderFileModule(
19 - array( 'styles' => array(
20 - 'skins/monobook/main.css' => array( 'media' => 'screen' ),
21 - // Honor $wgHandheldStyle. This is kind of evil
22 - //$GLOBALS['wgHandheldStyle'] => array( 'media' => 'handheld' )
23 - )
 18+ 'skins.monobook' => array(
 19+ 'styles' => array(
 20+ 'skins/monobook/main.css' => array( 'media' => 'screen' ),
 21+ // Honor $wgHandheldStyle. This is kind of evil
 22+ //$GLOBALS['wgHandheldStyle'] => array( 'media' => 'handheld' )
2423 )
2524 ),
2625
2726 /* jQuery */
2827
29 - 'jquery' => new ResourceLoaderFileModule(
30 - array( 'scripts' => 'resources/jquery/jquery.js', 'debugRaw' => false )
 28+ 'jquery' => array(
 29+ 'scripts' => 'resources/jquery/jquery.js',
 30+ 'debugRaw' => false
3131 ),
3232
3333 /* jQuery Plugins */
3434
35 - 'jquery.async' => new ResourceLoaderFileModule(
36 - array( 'scripts' => 'resources/jquery/jquery.async.js' )
 35+ 'jquery.async' => array(
 36+ 'scripts' => 'resources/jquery/jquery.async.js'
3737 ),
38 - 'jquery.autoEllipsis' => new ResourceLoaderFileModule(
39 - array( 'scripts' => 'resources/jquery/jquery.autoEllipsis.js' )
 38+ 'jquery.autoEllipsis' => array(
 39+ 'scripts' => 'resources/jquery/jquery.autoEllipsis.js'
4040 ),
41 - 'jquery.checkboxShiftClick' => new ResourceLoaderFileModule(
42 - array( 'scripts' => 'resources/jquery/jquery.checkboxShiftClick.js' )
 41+ 'jquery.checkboxShiftClick' => array(
 42+ 'scripts' => 'resources/jquery/jquery.checkboxShiftClick.js'
4343 ),
44 - 'jquery.client' => new ResourceLoaderFileModule(
45 - array( 'scripts' => 'resources/jquery/jquery.client.js' )
 44+ 'jquery.client' => array(
 45+ 'scripts' => 'resources/jquery/jquery.client.js',
4646 ),
47 - 'jquery.collapsibleTabs' => new ResourceLoaderFileModule(
48 - array( 'scripts' => 'resources/jquery/jquery.collapsibleTabs.js' )
 47+ 'jquery.collapsibleTabs' => array(
 48+ 'scripts' => 'resources/jquery/jquery.collapsibleTabs.js'
4949 ),
50 - 'jquery.color' => new ResourceLoaderFileModule(
51 - array( 'scripts' => 'resources/jquery/jquery.color.js' )
 50+ 'jquery.color' => array(
 51+ 'scripts' => 'resources/jquery/jquery.color.js'
5252 ),
53 - 'jquery.cookie' => new ResourceLoaderFileModule(
54 - array( 'scripts' => 'resources/jquery/jquery.cookie.js' )
 53+ 'jquery.cookie' => array(
 54+ 'scripts' => 'resources/jquery/jquery.cookie.js'
5555 ),
56 - 'jquery.delayedBind' => new ResourceLoaderFileModule(
57 - array( 'scripts' => 'resources/jquery/jquery.delayedBind.js' )
 56+ 'jquery.delayedBind' => array(
 57+ 'scripts' => 'resources/jquery/jquery.delayedBind.js'
5858 ),
59 - 'jquery.expandableField' => new ResourceLoaderFileModule(
60 - array( 'scripts' => 'resources/jquery/jquery.expandableField.js' )
 59+ 'jquery.expandableField' => array(
 60+ 'scripts' => 'resources/jquery/jquery.expandableField.js'
6161 ),
62 - 'jquery.highlightText' => new ResourceLoaderFileModule(
63 - array( 'scripts' => 'resources/jquery/jquery.highlightText.js' )
 62+ 'jquery.highlightText' => array(
 63+ 'scripts' => 'resources/jquery/jquery.highlightText.js'
6464 ),
65 - 'jquery.placeholder' => new ResourceLoaderFileModule(
66 - array( 'scripts' => 'resources/jquery/jquery.placeholder.js' )
 65+ 'jquery.placeholder' => array(
 66+ 'scripts' => 'resources/jquery/jquery.placeholder.js'
6767 ),
68 - 'jquery.suggestions' => new ResourceLoaderFileModule(
69 - array(
70 - 'scripts' => 'resources/jquery/jquery.suggestions.js',
71 - 'styles' => 'resources/jquery/jquery.suggestions.css',
72 - )
 68+ 'jquery.suggestions' => array(
 69+ 'scripts' => 'resources/jquery/jquery.suggestions.js',
 70+ 'styles' => 'resources/jquery/jquery.suggestions.css',
7371 ),
74 - 'jquery.tabIndex' => new ResourceLoaderFileModule(
75 - array( 'scripts' => 'resources/jquery/jquery.tabIndex.js' )
 72+ 'jquery.tabIndex' => array(
 73+ 'scripts' => 'resources/jquery/jquery.tabIndex.js'
7674 ),
77 - 'jquery.textSelection' => new ResourceLoaderFileModule(
78 - array( 'scripts' => 'resources/jquery/jquery.textSelection.js' )
 75+ 'jquery.textSelection' => array(
 76+ 'scripts' => 'resources/jquery/jquery.textSelection.js'
7977 ),
80 - 'jquery.tipsy' => new ResourceLoaderFileModule(
81 - array(
82 - 'scripts' => 'resources/jquery.tipsy/jquery.tipsy.js',
83 - 'styles' => 'resources/jquery.tipsy/jquery.tipsy.css',
84 - )
 78+ 'jquery.tipsy' => array(
 79+ 'scripts' => 'resources/jquery.tipsy/jquery.tipsy.js',
 80+ 'styles' => 'resources/jquery.tipsy/jquery.tipsy.css',
8581 ),
8682
8783 /* jQuery UI */
8884
8985 // Core
90 - 'jquery.ui.core' => new ResourceLoaderFileModule( array(
 86+ 'jquery.ui.core' => array(
9187 'scripts' => 'resources/jquery.ui/jquery.ui.core.js',
9288 'skinStyles' => array(
9389 'default' => array(
@@ -99,74 +95,74 @@
10096 ),
10197 ),
10298 'dependencies' => 'jquery',
103 - ) ),
104 - 'jquery.ui.widget' => new ResourceLoaderFileModule( array(
 99+ ),
 100+ 'jquery.ui.widget' => array(
105101 'scripts' => 'resources/jquery.ui/jquery.ui.widget.js',
106 - ) ),
107 - 'jquery.ui.mouse' => new ResourceLoaderFileModule( array(
 102+ ),
 103+ 'jquery.ui.mouse' => array(
108104 'scripts' => 'resources/jquery.ui/jquery.ui.mouse.js',
109105 'dependencies' => 'jquery.ui.widget',
110 - ) ),
111 - 'jquery.ui.position' => new ResourceLoaderFileModule( array(
 106+ ),
 107+ 'jquery.ui.position' => array(
112108 'scripts' => 'resources/jquery.ui/jquery.ui.position.js',
113 - ) ),
 109+ ),
114110 // Interactions
115 - 'jquery.ui.draggable' => new ResourceLoaderFileModule( array(
 111+ 'jquery.ui.draggable' => array(
116112 'scripts' => 'resources/jquery.ui/jquery.ui.draggable.js',
117113 'dependencies' => array( 'jquery.ui.core', 'jquery.ui.mouse', 'jquery.ui.widget' ),
118 - ) ),
119 - 'jquery.ui.droppable' => new ResourceLoaderFileModule( array(
 114+ ),
 115+ 'jquery.ui.droppable' => array(
120116 'scripts' => 'resources/jquery.ui/jquery.ui.droppable.js',
121117 'dependencies' => array(
122118 'jquery.ui.core', 'jquery.ui.mouse', 'jquery.ui.widget', 'jquery.ui.draggable'
123119 ),
124 - ) ),
125 - 'jquery.ui.resizable' => new ResourceLoaderFileModule( array(
 120+ ),
 121+ 'jquery.ui.resizable' => array(
126122 'scripts' => 'resources/jquery.ui/jquery.ui.resizable.js',
127123 'skinStyles' => array(
128124 'default' => 'resources/jquery.ui/themes/default/jquery.ui.resizable.css',
129125 'vector' => 'resources/jquery.ui/themes/vector/jquery.ui.resizable.css',
130126 ),
131127 'dependencies' => array( 'jquery.ui.core', 'jquery.ui.widget', 'jquery.ui.mouse' ),
132 - ) ),
133 - 'jquery.ui.selectable' => new ResourceLoaderFileModule( array(
 128+ ),
 129+ 'jquery.ui.selectable' => array(
134130 'scripts' => 'resources/jquery.ui/jquery.ui.selectable.js',
135131 'skinStyles' => array(
136132 'default' => 'resources/jquery.ui/themes/default/jquery.ui.selectable.css',
137133 'vector' => 'resources/jquery.ui/themes/vector/jquery.ui.selectable.css',
138134 ),
139135 'dependencies' => array( 'jquery.ui.core', 'jquery.ui.widget', 'jquery.ui.mouse' ),
140 - ) ),
141 - 'jquery.ui.sortable' => new ResourceLoaderFileModule( array(
 136+ ),
 137+ 'jquery.ui.sortable' => array(
142138 'scripts' => 'resources/jquery.ui/jquery.ui.sortable.js',
143139 'dependencies' => array( 'jquery.ui.core', 'jquery.ui.widget', 'jquery.ui.mouse' ),
144 - ) ),
 140+ ),
145141 // Widgets
146 - 'jquery.ui.accordion' => new ResourceLoaderFileModule( array(
 142+ 'jquery.ui.accordion' => array(
147143 'scripts' => 'resources/jquery.ui/jquery.ui.accordion.js',
148144 'dependencies' => array( 'jquery.ui.core', 'jquery.ui.widget' ),
149145 'skinStyles' => array(
150146 'default' => 'resources/jquery.ui/themes/default/jquery.ui.accordion.css',
151147 'vector' => 'resources/jquery.ui/themes/vector/jquery.ui.accordion.css',
152148 ),
153 - ) ),
154 - 'jquery.ui.autocomplete' => new ResourceLoaderFileModule( array(
 149+ ),
 150+ 'jquery.ui.autocomplete' => array(
155151 'scripts' => 'resources/jquery.ui/jquery.ui.autocomplete.js',
156152 'dependencies' => array( 'jquery.ui.core', 'jquery.ui.widget', 'jquery.ui.position' ),
157153 'skinStyles' => array(
158154 'default' => 'resources/jquery.ui/themes/default/jquery.ui.autocomplete.css',
159155 'vector' => 'resources/jquery.ui/themes/vector/jquery.ui.autocomplete.css',
160156 ),
161 - ) ),
162 - 'jquery.ui.button' => new ResourceLoaderFileModule( array(
 157+ ),
 158+ 'jquery.ui.button' => array(
163159 'scripts' => 'resources/jquery.ui/jquery.ui.button.js',
164160 'dependencies' => array( 'jquery.ui.core', 'jquery.ui.widget' ),
165161 'skinStyles' => array(
166162 'default' => 'resources/jquery.ui/themes/default/jquery.ui.button.css',
167163 'vector' => 'resources/jquery.ui/themes/vector/jquery.ui.button.css',
168164 ),
169 - ) ),
170 - 'jquery.ui.datepicker' => new ResourceLoaderFileModule( array(
 165+ ),
 166+ 'jquery.ui.datepicker' => array(
171167 'scripts' => 'resources/jquery.ui/jquery.ui.datepicker.js',
172168 'dependencies' => 'jquery.ui.core',
173169 'skinStyles' => array(
@@ -227,8 +223,8 @@
228224 'zh-hk' => 'resources/jquery.ui/i18n/jquery.ui.datepicker-zh-HK.js',
229225 'zh-tw' => 'resources/jquery.ui/i18n/jquery.ui.datepicker-zh-TW.js'
230226 ),
231 - ) ),
232 - 'jquery.ui.dialog' => new ResourceLoaderFileModule( array(
 227+ ),
 228+ 'jquery.ui.dialog' => array(
233229 'scripts' => 'resources/jquery.ui/jquery.ui.dialog.js',
234230 'dependencies' => array(
235231 'jquery.ui.core',
@@ -243,112 +239,112 @@
244240 'default' => 'resources/jquery.ui/themes/default/jquery.ui.dialog.css',
245241 'vector' => 'resources/jquery.ui/themes/vector/jquery.ui.dialog.css',
246242 ),
247 - ) ),
248 - 'jquery.ui.progressbar' => new ResourceLoaderFileModule( array(
 243+ ),
 244+ 'jquery.ui.progressbar' => array(
249245 'scripts' => 'resources/jquery.ui/jquery.ui.progressbar.js',
250246 'dependencies' => array( 'jquery.ui.core', 'jquery.ui.widget' ),
251247 'skinStyles' => array(
252248 'default' => 'resources/jquery.ui/themes/default/jquery.ui.progressbar.css',
253249 'vector' => 'resources/jquery.ui/themes/vector/jquery.ui.progressbar.css',
254250 ),
255 - ) ),
256 - 'jquery.ui.slider' => new ResourceLoaderFileModule( array(
 251+ ),
 252+ 'jquery.ui.slider' => array(
257253 'scripts' => 'resources/jquery.ui/jquery.ui.slider.js',
258254 'dependencies' => array( 'jquery.ui.core', 'jquery.ui.widget', 'jquery.ui.mouse' ),
259255 'skinStyles' => array(
260256 'default' => 'resources/jquery.ui/themes/default/jquery.ui.slider.css',
261257 'vector' => 'resources/jquery.ui/themes/vector/jquery.ui.slider.css',
262258 ),
263 - ) ),
264 - 'jquery.ui.tabs' => new ResourceLoaderFileModule( array(
 259+ ),
 260+ 'jquery.ui.tabs' => array(
265261 'scripts' => 'resources/jquery.ui/jquery.ui.tabs.js',
266262 'dependencies' => array( 'jquery.ui.core', 'jquery.ui.widget' ),
267263 'skinStyles' => array(
268264 'default' => 'resources/jquery.ui/themes/default/jquery.ui.tabs.css',
269265 'vector' => 'resources/jquery.ui/themes/vector/jquery.ui.tabs.css',
270266 ),
271 - ) ),
 267+ ),
272268 // Effects
273 - 'jquery.effects.core' => new ResourceLoaderFileModule( array(
 269+ 'jquery.effects.core' => array(
274270 'scripts' => 'resources/jquery.effects/jquery.effects.core.js',
275271 'dependencies' => 'jquery',
276 - ) ),
277 - 'jquery.effects.blind' => new ResourceLoaderFileModule( array(
 272+ ),
 273+ 'jquery.effects.blind' => array(
278274 'scripts' => 'resources/jquery.effects/jquery.effects.blind.js',
279275 'dependencies' => 'jquery.effects.core',
280 - ) ),
281 - 'jquery.effects.bounce' => new ResourceLoaderFileModule( array(
 276+ ),
 277+ 'jquery.effects.bounce' => array(
282278 'scripts' => 'resources/jquery.effects/jquery.effects.bounce.js',
283279 'dependencies' => 'jquery.effects.core',
284 - ) ),
285 - 'jquery.effects.clip' => new ResourceLoaderFileModule( array(
 280+ ),
 281+ 'jquery.effects.clip' => array(
286282 'scripts' => 'resources/jquery.effects/jquery.effects.clip.js',
287283 'dependencies' => 'jquery.effects.core',
288 - ) ),
289 - 'jquery.effects.drop' => new ResourceLoaderFileModule( array(
 284+ ),
 285+ 'jquery.effects.drop' => array(
290286 'scripts' => 'resources/jquery.effects/jquery.effects.drop.js',
291287 'dependencies' => 'jquery.effects.core',
292 - ) ),
293 - 'jquery.effects.explode' => new ResourceLoaderFileModule( array(
 288+ ),
 289+ 'jquery.effects.explode' => array(
294290 'scripts' => 'resources/jquery.effects/jquery.effects.explode.js',
295291 'dependencies' => 'jquery.effects.core',
296 - ) ),
297 - 'jquery.effects.fold' => new ResourceLoaderFileModule( array(
 292+ ),
 293+ 'jquery.effects.fold' => array(
298294 'scripts' => 'resources/jquery.effects/jquery.effects.fold.js',
299295 'dependencies' => 'jquery.effects.core',
300 - ) ),
301 - 'jquery.effects.highlight' => new ResourceLoaderFileModule( array(
 296+ ),
 297+ 'jquery.effects.highlight' => array(
302298 'scripts' => 'resources/jquery.effects/jquery.effects.highlight.js',
303299 'dependencies' => 'jquery.effects.core',
304 - ) ),
305 - 'jquery.effects.pulsate' => new ResourceLoaderFileModule( array(
 300+ ),
 301+ 'jquery.effects.pulsate' => array(
306302 'scripts' => 'resources/jquery.effects/jquery.effects.pulsate.js',
307303 'dependencies' => 'jquery.effects.core',
308 - ) ),
309 - 'jquery.effects.scale' => new ResourceLoaderFileModule( array(
 304+ ),
 305+ 'jquery.effects.scale' => array(
310306 'scripts' => 'resources/jquery.effects/jquery.effects.scale.js',
311307 'dependencies' => 'jquery.effects.core',
312 - ) ),
313 - 'jquery.effects.shake' => new ResourceLoaderFileModule( array(
 308+ ),
 309+ 'jquery.effects.shake' => array(
314310 'scripts' => 'resources/jquery.effects/jquery.effects.shake.js',
315311 'dependencies' => 'jquery.effects.core',
316 - ) ),
317 - 'jquery.effects.slide' => new ResourceLoaderFileModule( array(
 312+ ),
 313+ 'jquery.effects.slide' => array(
318314 'scripts' => 'resources/jquery.effects/jquery.effects.slide.js',
319315 'dependencies' => 'jquery.effects.core',
320 - ) ),
321 - 'jquery.effects.transfer' => new ResourceLoaderFileModule( array(
 316+ ),
 317+ 'jquery.effects.transfer' => array(
322318 'scripts' => 'resources/jquery.effects/jquery.effects.transfer.js',
323319 'dependencies' => 'jquery.effects.core',
324 - ) ),
 320+ ),
325321
326322 /* MediaWiki */
327323
328 - 'mediawiki' => new ResourceLoaderFileModule( array(
 324+ 'mediawiki' => array(
329325 'scripts' => 'resources/mediawiki/mediawiki.js',
330326 'debugScripts' => 'resources/mediawiki/mediawiki.log.js',
331327 'debugRaw' => false
332 - ) ),
333 - 'mediawiki.util' => new ResourceLoaderFileModule( array(
 328+ ),
 329+ 'mediawiki.util' => array(
334330 'scripts' => 'resources/mediawiki.util/mediawiki.util.js',
335331 'dependencies' => array( 'jquery.checkboxShiftClick', 'jquery.client' ),
336332 'debugScripts' => 'resources/mediawiki.util/mediawiki.util.test.js',
337 - ) ),
338 - 'mediawiki.action.view.rightClickEdit' => new ResourceLoaderFileModule( array(
 333+ ),
 334+ 'mediawiki.action.view.rightClickEdit' => array(
339335 'scripts' => 'resources/mediawiki.action/mediawiki.action.view.rightClickEdit.js',
340 - ) ),
341 - 'mediawiki.special.preferences' => new ResourceLoaderFileModule( array(
 336+ ),
 337+ 'mediawiki.special.preferences' => array(
342338 'scripts' => 'resources/mediawiki.special/mediawiki.special.preferences.js',
343339 'styles' => 'resources/mediawiki.special/mediawiki.special.preferences.css',
344 - ) ),
345 - 'mediawiki.special.search' => new ResourceLoaderFileModule( array(
 340+ ),
 341+ 'mediawiki.special.search' => array(
346342 'scripts' => 'resources/mediawiki.special/mediawiki.special.search.js',
347 - ) ),
348 - 'mediawiki.action.history' => new ResourceLoaderFileModule( array(
 343+ ),
 344+ 'mediawiki.action.history' => array(
349345 'scripts' => 'resources/mediawiki.action/mediawiki.action.history.js',
350346 'dependencies' => 'mediawiki.legacy.history',
351 - ) ),
352 - 'mediawiki.language' => new ResourceLoaderFileModule( array(
 347+ ),
 348+ 'mediawiki.language' => array(
353349 'scripts' => 'resources/mediawiki.language/mediawiki.language.js',
354350 'languageScripts' => array(
355351 'am' => 'resources/mediawiki.language/languages/am.js',
@@ -397,111 +393,111 @@
398394 'uk' => 'resources/mediawiki.language/languages/uk.js',
399395 'wa' => 'resources/mediawiki.language/languages/wa.js',
400396 ),
401 - ) ),
 397+ ),
402398
403399 /* mediawiki Legacy */
404400
405 - 'mediawiki.legacy.ajax' => new ResourceLoaderFileModule( array(
 401+ 'mediawiki.legacy.ajax' => array(
406402 'scripts' => 'skins/common/ajax.js',
407403 'messages' => array(
408404 'watch', 'unwatch', 'watching', 'unwatching', 'tooltip-ca-watch',
409405 'tooltip-ca-unwatch'
410406 ),
411407 'dependencies' => 'mediawiki.legacy.wikibits',
412 - ) ),
413 - 'mediawiki.legacy.ajaxwatch' => new ResourceLoaderFileModule( array(
 408+ ),
 409+ 'mediawiki.legacy.ajaxwatch' => array(
414410 'scripts' => 'skins/common/ajaxwatch.js',
415411 'dependencies' => 'mediawiki.legacy.wikibits',
416 - ) ),
417 - 'mediawiki.legacy.block' => new ResourceLoaderFileModule( array(
 412+ ),
 413+ 'mediawiki.legacy.block' => array(
418414 'scripts' => 'skins/common/block.js',
419415 'dependencies' => 'mediawiki.legacy.wikibits',
420 - ) ),
421 - 'mediawiki.legacy.changepassword' => new ResourceLoaderFileModule( array(
 416+ ),
 417+ 'mediawiki.legacy.changepassword' => array(
422418 'scripts' => 'skins/common/changepassword.js',
423419 'dependencies' => 'mediawiki.legacy.wikibits',
424 - ) ),
425 - 'mediawiki.legacy.commonPrint' => new ResourceLoaderFileModule( array(
 420+ ),
 421+ 'mediawiki.legacy.commonPrint' => array(
426422 'styles' => array( 'skins/common/commonPrint.css' => array( 'media' => 'print' ) ),
427 - ) ),
428 - 'mediawiki.legacy.config' => new ResourceLoaderFileModule( array(
 423+ ),
 424+ 'mediawiki.legacy.config' => array(
429425 'scripts' => 'skins/common/config.js',
430426 'styles' => array( 'skins/common/config.css', 'skins/common/config-cc.css' ),
431427 'dependencies' => 'mediawiki.legacy.wikibits',
432 - ) ),
433 - 'mediawiki.legacy.diff' => new ResourceLoaderFileModule( array(
 428+ ),
 429+ 'mediawiki.legacy.diff' => array(
434430 'scripts' => 'skins/common/diff.js',
435431 'styles' => 'skins/common/diff.css',
436432 'dependencies' => 'mediawiki.legacy.wikibits',
437 - ) ),
438 - 'mediawiki.legacy.edit' => new ResourceLoaderFileModule( array(
 433+ ),
 434+ 'mediawiki.legacy.edit' => array(
439435 'scripts' => 'skins/common/edit.js',
440436 'dependencies' => 'mediawiki.legacy.wikibits',
441 - ) ),
442 - 'mediawiki.legacy.enhancedchanges' => new ResourceLoaderFileModule( array(
 437+ ),
 438+ 'mediawiki.legacy.enhancedchanges' => array(
443439 'scripts' => 'skins/common/enhancedchanges.js',
444440 'dependencies' => 'mediawiki.legacy.wikibits',
445 - ) ),
446 - 'mediawiki.legacy.history' => new ResourceLoaderFileModule( array(
 441+ ),
 442+ 'mediawiki.legacy.history' => array(
447443 'scripts' => 'skins/common/history.js',
448444 'dependencies' => 'mediawiki.legacy.wikibits',
449 - ) ),
450 - 'mediawiki.legacy.htmlform' => new ResourceLoaderFileModule( array(
 445+ ),
 446+ 'mediawiki.legacy.htmlform' => array(
451447 'scripts' => 'skins/common/htmlform.js',
452448 'dependencies' => 'mediawiki.legacy.wikibits',
453 - ) ),
454 - 'mediawiki.legacy.IEFixes' => new ResourceLoaderFileModule( array(
 449+ ),
 450+ 'mediawiki.legacy.IEFixes' => array(
455451 'scripts' => 'skins/common/IEFixes.js',
456452 'dependencies' => 'mediawiki.legacy.wikibits',
457 - ) ),
458 - 'mediawiki.legacy.metadata' => new ResourceLoaderFileModule( array(
 453+ ),
 454+ 'mediawiki.legacy.metadata' => array(
459455 'scripts' => 'skins/common/metadata.js',
460456 'dependencies' => 'mediawiki.legacy.wikibits',
461457 'messages' => array( 'metadata-expand', 'metadata-collapse' ),
462 - ) ),
463 - 'mediawiki.legacy.mwsuggest' => new ResourceLoaderFileModule( array(
 458+ ),
 459+ 'mediawiki.legacy.mwsuggest' => array(
464460 'scripts' => 'skins/common/mwsuggest.js',
465461 'dependencies' => 'mediawiki.legacy.wikibits',
466462 'messages' => array( 'search-mwsuggest-enabled', 'search-mwsuggest-disabled' ),
467 - ) ),
468 - 'mediawiki.legacy.password' => new ResourceLoaderFileModule( array(
 463+ ),
 464+ 'mediawiki.legacy.password' => array(
469465 'scripts' => 'skins/common/password.js',
470466 'styles' => 'skins/common/password.css',
471467 'dependencies' => 'mediawiki.legacy.wikibits',
472 - ) ),
473 - 'mediawiki.legacy.prefs' => new ResourceLoaderFileModule( array(
 468+ ),
 469+ 'mediawiki.legacy.prefs' => array(
474470 'scripts' => 'skins/common/prefs.js',
475471 'dependencies' => array( 'mediawiki.legacy.wikibits', 'mediawiki.legacy.htmlform' ),
476 - ) ),
477 - 'mediawiki.legacy.preview' => new ResourceLoaderFileModule( array(
 472+ ),
 473+ 'mediawiki.legacy.preview' => array(
478474 'scripts' => 'skins/common/preview.js',
479475 'dependencies' => 'mediawiki.legacy.wikibits',
480 - ) ),
481 - 'mediawiki.legacy.protect' => new ResourceLoaderFileModule( array(
 476+ ),
 477+ 'mediawiki.legacy.protect' => array(
482478 'scripts' => 'skins/common/protect.js',
483479 'dependencies' => 'mediawiki.legacy.wikibits',
484 - ) ),
485 - 'mediawiki.legacy.search' => new ResourceLoaderFileModule( array(
 480+ ),
 481+ 'mediawiki.legacy.search' => array(
486482 'scripts' => 'skins/common/search.js',
487483 'styles' => 'skins/common/search.css',
488484 'dependencies' => 'mediawiki.legacy.wikibits',
489 - ) ),
490 - 'mediawiki.legacy.shared' => new ResourceLoaderFileModule( array(
 485+ ),
 486+ 'mediawiki.legacy.shared' => array(
491487 'styles' => array( 'skins/common/shared.css' => array( 'media' => 'screen' ) ),
492 - ) ),
493 - 'mediawiki.legacy.oldshared' => new ResourceLoaderFileModule( array(
 488+ ),
 489+ 'mediawiki.legacy.oldshared' => array(
494490 'styles' => array( 'skins/common/oldshared.css' => array( 'media' => 'screen' ) ),
495 - ) ),
496 - 'mediawiki.legacy.upload' => new ResourceLoaderFileModule( array(
 491+ ),
 492+ 'mediawiki.legacy.upload' => array(
497493 'scripts' => 'skins/common/upload.js',
498494 'dependencies' => 'mediawiki.legacy.wikibits',
499 - ) ),
500 - 'mediawiki.legacy.wikibits' => new ResourceLoaderFileModule( array(
 495+ ),
 496+ 'mediawiki.legacy.wikibits' => array(
501497 'scripts' => 'skins/common/wikibits.js',
502498 'dependencies' => 'mediawiki.language',
503499 'messages' => array( 'showtoc', 'hidetoc' ),
504 - ) ),
505 - 'mediawiki.legacy.wikiprintable' => new ResourceLoaderFileModule( array(
 500+ ),
 501+ 'mediawiki.legacy.wikiprintable' => array(
506502 'styles' => array( 'skins/common/wikiprintable.css' => array( 'media' => 'print' ) ),
507 - ) ),
 503+ ),
508504 );

Follow-up revisions

RevisionCommit summaryAuthorDate
r77020Updated extensions for r77011:...tstarling13:59, 19 November 2010
r77178testRegisteringNullModuleThrowsAnException - $this->markTestIncomplete( "Brok...reedy19:57, 23 November 2010
r77645Spaces to tabs in r77011catrope13:04, 3 December 2010
r79254ResourceLoader::register() works differently since r77011....platonides16:16, 30 December 2010

Comments

#Comment by Hashar (talk | contribs)   08:59, 20 November 2010

Broke test ResourceLoaderTest::testRegisteringNullModuleThrowsAnException()

http://ci.tesla.usability.wikimedia.org/cruisecontrol/buildresults/mw?log=log20101119104706

#Comment by Catrope (talk | contribs)   13:06, 3 December 2010
-
-			wfProfileOut( __METHOD__ );
-
 			return;

Why was this profileout call removed? It looks like this function can now leave profile in/out calls unmatched.

Rest of the revision looks OK to me. I know Trevor has his reservations with these changes, but I'm mostly indifferent towards them.

Oh and please fix the tests you broke.

#Comment by MZMcBride (talk | contribs)   00:46, 6 January 2011

This should be reverted if the issues aren't addressed soon. It's been about seven weeks since this revision was committed. In addition to the issues mentioned above in Catrope's comment, there is no updated documentation for these changes, making life difficult for other developers.

#Comment by Tim Starling (talk | contribs)   00:57, 6 January 2011

I updated the doc comments. I was afraid to run the tests since I thought they would probably destroy my database.

#Comment by Trevor Parscal (WMF) (talk | contribs)   00:59, 6 January 2011
#Comment by Brion VIBBER (talk | contribs)   01:33, 6 January 2011

I made some updates to ResourceLoader/Documentation/Using_with_extensions; it looks about right to me now, give a shout if anything's still off.

#Comment by Catrope (talk | contribs)   12:40, 6 January 2011

This is not going to be reverted. The issues should be easy to fix.

#Comment by Trevor Parscal (WMF) (talk | contribs)   00:31, 14 January 2011

I'm opposed to this change (and the subsequent changes in r77020).

Yes, some of the designs of ResourceLoader are different from the typical MediaWiki way of doing things - but that was not by accident, it was part of an effort to incrementally change MediaWiki into what it should and could be, rather than maintain the status quo, and continue writing software using flawed development practices in the name of consistency.

I'm specifically opposed to how this change...

1. Adds global state to a system that didn't used to have global state, making it far more difficult to unit test for instance. 2. Makes module registration messier, involving either tons of code duplication, or the creation of a global "template" variable which is used over and over again throughout the creation of an array. 3. Only noticeably affects the performance of installs which do not use PHP caching.

This is micro-optimization at the cost of quality. However, I am marking it OK because...

1. We have bigger problems to deal with. 2. I've stated my case directly, and Tim was unwilling to negotiate. 3. If this is what it takes for Tim to cooperate with ResourceLoader development, then it's worth it because the overall benefits of ResourceLoader far outweigh any of the set-backs presented by this patch.

#Comment by QuestPC (talk | contribs)   09:10, 1 February 2011

Will the 'ResourceLoaderRegisterModules' hook stay in 1.17 release, or shall I modify my extensions to use $wgResourceModules instead? I am thinking of using $wgResourceModules, because that is supposed to run faster but affraid of possible reversion.

#Comment by Catrope (talk | contribs)   12:39, 1 February 2011

$wgResourceModules will not be reverted. The hook will stay in the 1.17 release.

#Comment by 😂 (talk | contribs)   12:51, 1 February 2011

Is the hook going into 1.18?

Status & tagging log