2 * Base library for MediaWiki.
9 var con = window.console;
13 * @classdesc Collection of values by string keys.
15 * This is an internal class that backs the mw.config and mw.messages APIs.
17 * It allows reading and writing to the collection via public methods,
18 * and allows batch iteraction for all its methods.
20 * For mw.config, scripts sometimes choose to "import" a set of keys locally,
24 * var conf = mw.config.get( [ 'wgServerName', 'wgUserName', 'wgPageName' ] );
25 * conf.wgServerName; // "example.org"
28 * Check the existence ("AND" condition) of multiple keys:
31 * if ( mw.config.exists( [ 'wgFoo', 'wgBar' ] ) );
34 * For mw.messages, the {@link mw.Map#set} method allows mw.loader and mw.Api to essentially
35 * extend the object, and batch-apply all their loaded values in one go:
38 * mw.messages.set( { "mon": "Monday", "tue": "Tuesday" } );
44 this.values = Object.create( null );
47 Map.prototype = /** @lends mw.Map.prototype */ {
51 * Get the value of one or more keys.
53 * If called with no arguments, all values are returned.
55 * @param {string|Array} [selection] Key or array of keys to retrieve values for.
56 * @param {any} [fallback=null] Value for keys that don't exist.
57 * @return {any|Object|null} If selection was a string, returns the value,
58 * If selection was an array, returns an object of key/values.
59 * If no selection is passed, a new object with all key/values is returned.
61 get: function ( selection, fallback ) {
62 if ( arguments.length < 2 ) {
66 if ( typeof selection === 'string' ) {
67 return selection in this.values ?
68 this.values[ selection ] :
73 if ( Array.isArray( selection ) ) {
75 for ( var i = 0; i < selection.length; i++ ) {
76 if ( typeof selection[ i ] === 'string' ) {
77 results[ selection[ i ] ] = selection[ i ] in this.values ?
78 this.values[ selection[ i ] ] :
85 if ( selection === undefined ) {
87 for ( var key in this.values ) {
88 results[ key ] = this.values[ key ];
93 // Invalid selection key
98 * Set one or more key/value pairs.
100 * @param {string|Object} selection Key to set value for, or object mapping keys to values
101 * @param {any} [value] Value to set (optional, only in use when key is a string)
102 * @return {boolean} True on success, false on failure
104 set: function ( selection, value ) {
105 // Use `arguments.length` because `undefined` is also a valid value.
106 if ( arguments.length > 1 ) {
108 if ( typeof selection === 'string' ) {
109 this.values[ selection ] = value;
112 } else if ( typeof selection === 'object' ) {
114 for ( var key in selection ) {
115 this.values[ key ] = selection[ key ];
123 * Check if a given key exists in the map.
125 * @param {string} selection Key to check
126 * @return {boolean} True if the key exists
128 exists: function ( selection ) {
129 return typeof selection === 'string' && selection in this.values;
134 * Write a verbose message to the browser's console in debug mode.
136 * In ResourceLoader debug mode, this writes to the browser's console.
137 * In production mode, it is a no-op.
139 * See {@link mw.log} for other logging methods.
143 * @param {...string} msg Messages to output to console.
145 var log = function () {
150 * Write a message to the browser console's warning channel.
154 * @param {...string} msg Messages to output to console
156 log.warn = Function.prototype.bind.call( con.warn, con );
159 * Base library for MediaWiki.
161 * Exposed globally as `mw`, with `mediaWiki` as alias. `mw` code can be considered stable and follows the
162 * [frontend stable interface policy](https://www.mediawiki.org/wiki/Special:MyLanguage/Stable_interface_policy/Frontend).
166 var mw = /** @lends mw */ {
168 * Get the current time, measured in milliseconds since January 1, 1970 (UTC).
170 * On browsers that implement the Navigation Timing API, this function will produce
171 * floating-point values with microsecond precision that are guaranteed to be monotonic.
172 * On all other browsers, it will fall back to using `Date`.
174 * @return {number} Current time
177 // Optimisation: Cache and re-use the chosen implementation.
178 // Optimisation: Avoid startup overhead by re-defining on first call instead of IIFE.
179 var perf = window.performance;
180 var navStart = perf && perf.timing && perf.timing.navigationStart;
182 // Define the relevant shortcut
183 mw.now = navStart && perf.now ?
185 return navStart + perf.now();
193 * List of all analytic events emitted so far.
195 * Exposed only for use by mediawiki.base.
203 * Track `'resourceloader.exception'` event and send it to the window console.
205 * This exists for internal use by mw.loader only, to remember and buffer
206 * very early events for `mw.trackSubscribe( 'resourceloader.exception' )`
207 * even while `mediawiki.base` and `mw.track` are still in-flight.
210 * @param {Object} data
211 * @param {Error} [data.exception]
212 * @param {string} data.source Error source
213 * @param {string} [data.module] Name of module which caused the error
215 trackError: function ( data ) {
217 mw.track( 'resourceloader.exception', data );
219 mw.trackQueue.push( { topic: 'resourceloader.exception', args: [ data ] } );
222 // Log an error message to window.console, even in production mode.
223 var e = data.exception;
224 var msg = ( e ? 'Exception' : 'Error' ) +
225 ' in ' + data.source +
226 ( data.module ? ' in module ' + data.module : '' ) +
231 // If we have an exception object, log it to the warning channel to trigger
232 // proper stacktraces in browsers that support it.
242 * Map of configuration values.
244 * Check out [the complete list of configuration values](https://www.mediawiki.org/wiki/Manual:Interface/JavaScript#mw.config)
252 * Store for messages.
259 * Store for templates associated with a module.
263 templates: new Map(),
268 // mw.loader is defined in a separate file that is appended to this
271 // Attach to window and globally alias
272 window.mw = window.mediaWiki = mw;
274 $CODE.undefineQUnit();