Krinkle has uploaded a new change for review.
https://gerrit.wikimedia.org/r/312557
Change subject: resourceloader: Deprecate mw.Map
......................................................................
resourceloader: Deprecate mw.Map
This has never been used outside mediawiki.js for things like mw.config,
and mw.messages.
The public API of those objects will remain, but the constructor will
no longer be supported in the future in order to allow these to be
backed by native Map in the future (with a minimal polyfill rather than
a complete one).
* Remove 'mw.Map(valuesObject)'. (follows-up 63f8d7b9e5).
This is incompatible with native Map and isn't actually used anywhere.
* Deprecate mw.Map#values. Undocumented and considered private.
A few uses have appeared in the wild so keep a short deprecation period.
* Update the MediaWiki QUnit runner to construct new maps in setup/teardown
instead of swapping the internal values object directly.
Also update the runner to update mediawiki.jqueryMsg's parser default since
it kept a reference to the first mw.messages object.
* Add 'logName' parameter to mw.log.deprecate(). Default logName
of property key made sense for its original use case (deprecation warnings
for global variables, which are a property of the window object). But
for keys of any other object, we'll want to some context for the name.
* Remove redundant test expect numbers. (Follows-up 7c36375, c4c7007d)
Bug: T146432
Change-Id: I7ff0b230608f5ca582fc6752b59c4bb998c78ba2
---
M resources/src/mediawiki/mediawiki.js
M tests/qunit/data/testrunner.js
M tests/qunit/suites/resources/mediawiki/mediawiki.test.js
3 files changed, 63 insertions(+), 65 deletions(-)
git pull ssh://gerrit.wikimedia.org:29418/mediawiki/core
refs/changes/57/312557/1
diff --git a/resources/src/mediawiki/mediawiki.js
b/resources/src/mediawiki/mediawiki.js
index de2b8ee..6237391 100644
--- a/resources/src/mediawiki/mediawiki.js
+++ b/resources/src/mediawiki/mediawiki.js
@@ -66,48 +66,20 @@
}() );
/**
- * Create an object that can be read from or written to from methods
that allow
+ * Create an object that can be read from or written to via methods
that allow
* interaction both with single and multiple properties at once.
*
- * @example
- *
- * var collection, query, results;
- *
- * // Create your address book
- * collection = new mw.Map();
- *
- * // This data could be coming from an external source (eg.
API/AJAX)
- * collection.set( {
- * 'John Doe': '[email protected]',
- * 'Jane Doe': '[email protected]',
- * 'George van Halen': '[email protected]'
- * } );
- *
- * wanted = ['John Doe', 'Jane Doe', 'Daniel Jackson'];
- *
- * // You can detect missing keys first
- * if ( !collection.exists( wanted ) ) {
- * // One or more are missing (in this case: "Daniel Jackson")
- * mw.log( 'One or more names were not found in your address
book' );
- * }
- *
- * // Or just let it give you what it can. Optionally fill in from
a default.
- * results = collection.get( wanted, '[email protected]' );
- * mw.log( results['Jane Doe'] ); // "[email protected]"
- * mw.log( results['Daniel Jackson'] ); // "[email protected]"
- *
+ * @private
* @class mw.Map
*
* @constructor
- * @param {Object|boolean} [values] The value-baring object to be
mapped. Defaults to an
- * empty object.
- * For backwards-compatibility with mw.config, this can also be `true`
in which case values
- * are 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.
+ * @param {boolean} [global=false] Whether to synchronise =values to
the global
+ * window object (for backwards-compatibility with mw.config; T72470).
Values are
+ * copied in one direction only. Changes to globals do not reflect in
the map.
*/
- function Map( values ) {
- if ( values === true ) {
- this.values = {};
+ function Map( global ) {
+ this.internalValues = {};
+ if ( global === true ) {
// Override #set to also set the global variable
this.set = function ( selection, value ) {
@@ -129,7 +101,14 @@
return;
}
- this.values = values || {};
+ // Deprecated since MediaWiki 1.28
+ log.deprecate(
+ this,
+ 'values',
+ this.internalValues,
+ 'mw.Map#values is deprecated. Use mw.Map#get()
instead.',
+ 'Map-values'
+ );
}
/**
@@ -142,8 +121,8 @@
* @param {Mixed} value
*/
function setGlobalMapValue( map, key, value ) {
- map.values[ key ] = value;
- mw.log.deprecate(
+ map.internalValues[ key ] = value;
+ log.deprecate(
window,
key,
value,
@@ -153,6 +132,8 @@
}
Map.prototype = {
+ constructor: Map,
+
/**
* Get the value of one or more keys.
*
@@ -162,7 +143,7 @@
* @param {Mixed} [fallback=null] Value for keys that don't
exist.
* @return {Mixed|Object| null} If selection was a string,
returns the value,
* If selection was an array, returns an object of key/values.
- * If no selection is passed, the 'values' container is
returned. (Beware that,
+ * If no selection is passed, the internal container is
returned. (Beware that,
* as is the default in JavaScript, the object is returned by
reference.)
*/
get: function ( selection, fallback ) {
@@ -181,14 +162,14 @@
}
if ( typeof selection === 'string' ) {
- if ( !hasOwn.call( this.values, selection ) ) {
+ if ( !hasOwn.call( this.internalValues,
selection ) ) {
return fallback;
}
- return this.values[ selection ];
+ return this.internalValues[ selection ];
}
if ( selection === undefined ) {
- return this.values;
+ return this.internalValues;
}
// Invalid selection key
@@ -207,12 +188,12 @@
if ( $.isPlainObject( selection ) ) {
for ( s in selection ) {
- this.values[ s ] = selection[ s ];
+ this.internalValues[ s ] = selection[ s
];
}
return true;
}
if ( typeof selection === 'string' && arguments.length
> 1 ) {
- this.values[ selection ] = value;
+ this.internalValues[ selection ] = value;
return true;
}
return false;
@@ -229,13 +210,13 @@
if ( $.isArray( selection ) ) {
for ( s = 0; s < selection.length; s++ ) {
- if ( typeof selection[ s ] !== 'string'
|| !hasOwn.call( this.values, selection[ s ] ) ) {
+ if ( typeof selection[ s ] !== 'string'
|| !hasOwn.call( this.internalValues, selection[ s ] ) ) {
return false;
}
}
return true;
}
- return typeof selection === 'string' && hasOwn.call(
this.values, selection );
+ return typeof selection === 'string' && hasOwn.call(
this.internalValues, selection );
}
};
@@ -475,11 +456,14 @@
* @param {string} key Name of property to create in `obj`
* @param {Mixed} val The value this property should return
when accessed
* @param {string} [msg] Optional text to include in the
deprecation message
+ * @param {string} [logName=key] Optional custom name for the
feature.
+ * This is used instead of `key` in the message and
`mw.deprecate` tracking.
*/
- log.deprecate = !Object.defineProperty ? function ( obj, key,
val, msg ) {
+ log.deprecate = !Object.defineProperty ? function ( obj, key,
val, msg, logName ) {
obj[ key ] = val;
- } : function ( obj, key, val, msg ) {
- msg = 'Use of "' + key + '" is deprecated.' + ( msg ? (
' ' + msg ) : '' );
+ } : function ( obj, key, val, msg, logName ) {
+ logName = logName || key;
+ msg = 'Use of "' + logName + '" is deprecated.' + ( msg
? ( ' ' + msg ) : '' );
var logged = new StringSet();
function uniqueTrace() {
var trace = new Error().stack;
@@ -494,14 +478,14 @@
enumerable: true,
get: function () {
if ( uniqueTrace() ) {
- mw.track( 'mw.deprecate', key );
+ mw.track( 'mw.deprecate',
logName );
mw.log.warn( msg );
}
return val;
},
set: function ( newVal ) {
if ( uniqueTrace() ) {
- mw.track( 'mw.deprecate', key );
+ mw.track( 'mw.deprecate',
logName );
mw.log.warn( msg );
}
val = newVal;
diff --git a/tests/qunit/data/testrunner.js b/tests/qunit/data/testrunner.js
index 79f37dc..b79c192 100644
--- a/tests/qunit/data/testrunner.js
+++ b/tests/qunit/data/testrunner.js
@@ -167,10 +167,11 @@
*/
QUnit.newMwEnvironment = ( function () {
var warn, error, liveConfig, liveMessages,
+ MwMap = mw.config.constructor, // internal use only
ajaxRequests = [];
- liveConfig = mw.config.values;
- liveMessages = mw.messages.values;
+ liveConfig = mw.config;
+ liveMessages = mw.messages;
function suppressWarnings() {
warn = mw.log.warn;
@@ -198,14 +199,14 @@
// NOTE: It is important that we suppress warnings
because extend() will also access
// deprecated properties and trigger deprecation
warnings from mw.log#deprecate.
suppressWarnings();
- copy = $.extend( {}, liveConfig, custom );
+ copy = $.extend( {}, liveConfig.get(), custom );
restoreWarnings();
return copy;
}
function freshMessagesCopy( custom ) {
- return $.extend( /*deep=*/true, {}, liveMessages,
custom );
+ return $.extend( /*deep=*/true, {}, liveMessages.get(),
custom );
}
/**
@@ -231,8 +232,15 @@
setup: function () {
// Greetings, mock environment!
- mw.config.values = freshConfigCopy(
localEnv.config );
- mw.messages.values = freshMessagesCopy(
localEnv.messages );
+ mw.config = new MwMap();
+ mw.config.set( freshConfigCopy(
localEnv.config ) );
+ mw.messages = new MwMap();
+ mw.messages.set( freshMessagesCopy(
localEnv.messages ) );
+ // Update reference to mw.messages
+ mw.jqueryMsg.setParserDefaults( {
+ messages: mw.messages
+ } );
+
this.suppressWarnings =
suppressWarnings;
this.restoreWarnings = restoreWarnings;
@@ -251,8 +259,12 @@
$( document ).off( 'ajaxSend',
trackAjax );
// Farewell, mock environment!
- mw.config.values = liveConfig;
- mw.messages.values = liveMessages;
+ mw.config = liveConfig;
+ mw.messages = liveMessages;
+ // Restore reference to mw.messages
+ mw.jqueryMsg.setParserDefaults( {
+ messages: liveMessages
+ } );
// As a convenience feature,
automatically restore warnings if they're
// still suppressed by the end of the
test.
diff --git a/tests/qunit/suites/resources/mediawiki/mediawiki.test.js
b/tests/qunit/suites/resources/mediawiki/mediawiki.test.js
index ab463a9..1f24a26 100644
--- a/tests/qunit/suites/resources/mediawiki/mediawiki.test.js
+++ b/tests/qunit/suites/resources/mediawiki/mediawiki.test.js
@@ -65,10 +65,13 @@
);
} );
- QUnit.test( 'mw.Map', 35, function ( assert ) {
+ QUnit.test( 'mw.Map', function ( assert ) {
var arry, conf, funky, globalConf, nummy, someValues;
+ this.suppressWarnings();
conf = new mw.Map();
+ this.restoreWarnings();
+
// Dummy variables
funky = function () {};
arry = [];
@@ -126,15 +129,15 @@
lorem: 'ipsum'
}, 'Map.get returns multiple values correctly as an object' );
- assert.deepEqual( conf, new mw.Map( conf.values ), 'new mw.Map
maps over existing values-bearing object' );
-
assert.deepEqual( conf.get( [ 'foo', 'notExist' ] ), {
foo: 'bar',
notExist: null
}, 'Map.get return includes keys that were not found as null
values' );
// Interacting with globals and accessing the values object
+ this.suppressWarnings();
assert.strictEqual( conf.get(), conf.values, 'Map.get returns
the entire values object by reference (if called without arguments)' );
+ this.restoreWarnings();
conf.set( 'globalMapChecker', 'Hi' );
@@ -174,7 +177,7 @@
assert.ok( mw.config instanceof mw.Map, 'mw.config instance of
mw.Map' );
} );
- QUnit.test( 'mw.message & mw.messages', 100, function ( assert ) {
+ QUnit.test( 'mw.message & mw.messages', function ( assert ) {
var goodbye, hello;
// Convenience method for asserting the same result for
multiple formats
@@ -189,7 +192,6 @@
}
assert.ok( mw.messages, 'messages defined' );
- assert.ok( mw.messages instanceof mw.Map, 'mw.messages instance
of mw.Map' );
assert.ok( mw.messages.set( 'hello', 'Hello <b>awesome</b>
world' ), 'mw.messages.set: Register' );
hello = mw.message( 'hello' );
--
To view, visit https://gerrit.wikimedia.org/r/312557
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings
Gerrit-MessageType: newchange
Gerrit-Change-Id: I7ff0b230608f5ca582fc6752b59c4bb998c78ba2
Gerrit-PatchSet: 1
Gerrit-Project: mediawiki/core
Gerrit-Branch: master
Gerrit-Owner: Krinkle <[email protected]>
_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits