* @class mw.Map
*
* @constructor
- * @param {Object|boolean} [values] Value-bearing object to map, or boolean
- * true to map over the global object. Defaults to an empty object.
+ * @param {Object|boolean} [values] Value-bearing object to map, defaults to an empty object.
+ * For backwards-compatibility with mw.config, this can also be `true` in which case values
+ * will be copied to the Window object as global variables (T72470). Values are copied in one
+ * direction only. Changes to globals are not reflected in the map.
*/
function Map( values ) {
- this.values = values === true ? window : ( values || {} );
- return this;
+ if ( values === true ) {
+ this.values = {};
+
+ // Override #set to also set the global variable
+ this.set = function ( selection, value ) {
+ var s;
+
+ if ( $.isPlainObject( selection ) ) {
+ for ( s in selection ) {
+ setGlobalMapValue( this, s, selection[s] );
+ }
+ return true;
+ }
+ if ( typeof selection === 'string' && arguments.length ) {
+ setGlobalMapValue( this, selection, value );
+ return true;
+ }
+ return false;
+ };
+
+ return;
+ }
+
+ this.values = values || {};
+ }
+
+ /**
+ * Alias property to the global object.
+ *
+ * @private
+ * @static
+ * @param {mw.Map} map
+ * @param {string} key
+ * @param {Mixed} value
+ */
+ function setGlobalMapValue( map, key, value ) {
+ map.values[key] = value;
+ mw.log.deprecate(
+ window,
+ key,
+ value,
+ // Deprecation notice for mw.config globals (T58550, T72470)
+ map === mw.config && 'Use mw.config instead.'
+ );
}
Map.prototype = {
*
* @param {string|Object} selection String key to set value for, or object mapping keys to values.
* @param {Mixed} [value] Value to set (optional, only in use when key is a string)
- * @return {Boolean} This returns true on success, false on failure.
+ * @return {boolean} This returns true on success, false on failure.
*/
set: function ( selection, value ) {
var s;
}
return true;
}
- if ( typeof selection === 'string' && arguments.length > 1 ) {
+ if ( typeof selection === 'string' && arguments.length ) {
this.values[selection] = value;
return true;
}
} );
} catch ( err ) {
// IE8 can throw on Object.defineProperty
+ // Create a copy of the value to the object.
obj[key] = val;
}
};
this.restoreWarnings();
} );
- QUnit.test( 'mw.Map', 28, function ( assert ) {
+ QUnit.test( 'mw.Map', 34, function ( assert ) {
var arry, conf, funky, globalConf, nummy, someValues;
conf = new mw.Map();
conf.set( 'globalMapChecker', 'Hi' );
- assert.ok( 'globalMapChecker' in window === false, 'new mw.Map did not store its values in the global window object by default' );
+ assert.ok( ( 'globalMapChecker' in window ) === false, 'Map does not its store values in the window object by default' );
globalConf = new mw.Map( true );
globalConf.set( 'anotherGlobalMapChecker', 'Hello' );
- assert.ok( 'anotherGlobalMapChecker' in window, 'new mw.Map( true ) did store its values in the global window object' );
+ assert.ok( 'anotherGlobalMapChecker' in window, 'global Map stores its values in the window object' );
+
+ assert.equal( globalConf.get( 'anotherGlobalMapChecker' ), 'Hello', 'get value from global Map via get()' );
+ this.suppressWarnings();
+ assert.equal( window.anotherGlobalMapChecker, 'Hello', 'get value from global Map via window object' );
+ this.restoreWarnings();
+
+ // Change value via global Map
+ globalConf.set('anotherGlobalMapChecker', 'Again');
+ assert.equal( globalConf.get( 'anotherGlobalMapChecker' ), 'Again', 'Change in global Map reflected via get()' );
+ this.suppressWarnings();
+ assert.equal( window.anotherGlobalMapChecker, 'Again', 'Change in global Map reflected window object' );
+ this.restoreWarnings();
+
+ // Change value via window object
+ this.suppressWarnings();
+ window.anotherGlobalMapChecker = 'World';
+ assert.equal( window.anotherGlobalMapChecker, 'World', 'Change in window object works' );
+ this.restoreWarnings();
+ assert.equal( globalConf.get( 'anotherGlobalMapChecker' ), 'Again', 'Change in window object not reflected in global Map' );
// Whitelist this global variable for QUnit's 'noglobal' mode
if ( QUnit.config.noglobals ) {