build: Update eslint-config-wikimedia to 0.21.0

* Replace `substr`/`substring` with `slice`. The second argument
  to `substring` is length, not end index as in `substr`/`slice`,
  so convert where necessary.
* Replace `new Date().getTime()` with `Date.now()`
* Documentation fixes
* Replace `throw Error` with `throw new Error`

Change-Id: I532500ea4c99d8ebec01efb21273c8df21626e59
This commit is contained in:
Ed Sanders 2021-11-08 18:50:04 +00:00 committed by Krinkle
parent 58f9dc68fc
commit 9fe2995989
31 changed files with 13573 additions and 242 deletions

13711
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -20,7 +20,7 @@
"@wdio/sync": "7.4.6",
"api-testing": "1.3.0",
"dotenv": "8.2.0",
"eslint-config-wikimedia": "0.20.0",
"eslint-config-wikimedia": "0.21.0",
"grunt": "1.4.1",
"grunt-banana-checker": "0.9.0",
"grunt-contrib-copy": "1.0.0",

View file

@ -10,7 +10,7 @@
* author Mozilla Contributors
* license CC0 per https://developer.mozilla.org/en-US/docs/MDN/About#copyrights_and_licenses
*
* https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/find
* https://github.com/mdn/content/blob/b81aa721130/files/en-us/web/javascript/reference/global_objects/array/find/index.html#L113
*/
if ( !Array.prototype.find ) {
Object.defineProperty( Array.prototype, 'find', {
@ -19,7 +19,7 @@ if ( !Array.prototype.find ) {
// 1. Let O be ? ToObject(this value).
if ( this == null ) {
throw TypeError( '"this" is null or not defined' );
throw new TypeError( '"this" is null or not defined' );
}
o = Object( this );
@ -29,7 +29,7 @@ if ( !Array.prototype.find ) {
// 3. If IsCallable(predicate) is false, throw a TypeError exception.
if ( typeof predicate !== 'function' ) {
throw TypeError( 'predicate must be a function' );
throw new TypeError( 'predicate must be a function' );
}
// 4. If thisArg was supplied, let T be thisArg; else let T be undefined.

View file

@ -214,7 +214,7 @@
* @param {jQuery} [options.$customTogglers] Elements to be used as togglers
* for this collapsible element. By default, if the collapsible element
* has an id attribute like 'mw-customcollapsible-XXX', elements with a
* *class* of 'mw-customtoggle-XXX' are made togglers for it.
* **class** of 'mw-customtoggle-XXX' are made togglers for it.
* @param {boolean} [options.plainMode=false] Whether to use a "plain mode" when making the
* element collapsible - that is, hide entire tables and lists (instead
* of hiding only all rows but first of tables, and hiding each list

View file

@ -90,7 +90,7 @@
if ( !el ) {
val = '';
} else {
val = el.value.substring( el.selectionStart, el.selectionEnd );
val = el.value.slice( el.selectionStart, el.selectionEnd );
}
return val;

View file

@ -85,7 +85,6 @@ module.exports = ( function () {
return '*';
}
// eslint-disable-next-line compat/compat
origin = location.protocol + '//' + location.hostname;
if ( location.port ) {
origin += ':' + location.port;

View file

@ -522,7 +522,7 @@ Title.newFromUserInput = function ( title, defaultNamespace, options ) {
namespace = NS_MAIN;
title = title
// Strip colon
.substr( 1 )
.slice( 1 )
// Trim underscores
.replace( rUnderscoreTrim, '' );
}

View file

@ -432,7 +432,7 @@ mw.jqueryMsg.Parser.prototype = {
var len = s.length;
return function () {
var result = null;
if ( input.substr( pos, len ) === s ) {
if ( input.slice( pos, pos + len ) === s ) {
result = s;
pos += len;
}

View file

@ -191,7 +191,7 @@
newSegment = segment.toUpperCase();
// ISO 15924 script code
} else if ( segment.length === 4 && !isFirstSegment ) {
newSegment = segment.charAt( 0 ).toUpperCase() + segment.substring( 1 ).toLowerCase();
newSegment = segment.charAt( 0 ).toUpperCase() + segment.slice( 1 ).toLowerCase();
// Use lowercase for other cases
} else {
newSegment = segment.toLowerCase();

View file

@ -1141,7 +1141,7 @@ Controller.prototype._trackHighlight = function ( action, filters ) {
*/
Controller.prototype.trackFilterGroupings = function ( action ) {
var controller = this,
rightNow = new Date().getTime(),
rightNow = Date.now(),
randomIdentifier = String( mw.user.sessionId() ) + String( rightNow ) + String( Math.random() ),
// Get all current filters
filters = this.filtersModel.findSelectedItems().map( function ( item ) {

View file

@ -1020,13 +1020,13 @@ FiltersViewModel.prototype.findMatches = function ( query, returnFlat ) {
groupTitle,
result = {},
flatResult = [],
view = this.getViewByTrigger( query.substr( 0, 1 ) ),
view = this.getViewByTrigger( query.slice( 0, 1 ) ),
items = this.getFiltersByView( view );
// Normalize so we can search strings regardless of case and view
query = query.trim().toLowerCase();
if ( view !== 'default' ) {
query = query.substr( 1 );
query = query.slice( 1 );
}
// Trim again to also intercept cases where the spaces were after the trigger
// eg: '# str'
@ -1166,7 +1166,7 @@ FiltersViewModel.prototype.getViewByTrigger = function ( trigger ) {
*/
FiltersViewModel.prototype.removeViewTriggers = function ( str ) {
if ( this.getViewFromString( str ) !== 'default' ) {
str = str.substr( 1 );
str = str.slice( 1 );
}
return str;
@ -1179,7 +1179,7 @@ FiltersViewModel.prototype.removeViewTriggers = function ( str ) {
* @return {string} View name
*/
FiltersViewModel.prototype.getViewFromString = function ( str ) {
return this.getViewByTrigger( str.substr( 0, 1 ) );
return this.getViewByTrigger( str.slice( 0, 1 ) );
};
/**

View file

@ -224,7 +224,7 @@ SavedQueriesModel.prototype.convertToParameters = function ( data ) {
SavedQueriesModel.prototype.addNewQuery = function ( label, fulldata, isDefault, id ) {
var normalizedData = { params: {}, highlights: {} },
highlightParamNames = Object.keys( this.filtersModel.getEmptyHighlightParameters() ),
randomID = String( id || ( new Date() ).getTime() ),
randomID = String( id || Date.now() ),
data = this.filtersModel.getMinimizedParamRepresentation( fulldata );
// Split highlight/params

View file

@ -177,7 +177,8 @@ ChangesListWrapperWidget.prototype.onModelUpdate = function (
} );
};
/** Toggles overlay class on changes list
/**
* Toggles overlay class on changes list
*
* @param {boolean} isVisible True if overlay should be visible
*/

View file

@ -502,11 +502,11 @@ FilterTagMultiselectWidget.prototype.onModelUpdate = function () {
FilterTagMultiselectWidget.prototype.updateElementsForView = function () {
var view = this.model.getCurrentView(),
inputValue = this.input.getValue().trim(),
inputView = this.model.getViewByTrigger( inputValue.substr( 0, 1 ) );
inputView = this.model.getViewByTrigger( inputValue.slice( 0, 1 ) );
if ( inputView !== 'default' ) {
// We have a prefix already, remove it
inputValue = inputValue.substr( 1 );
inputValue = inputValue.slice( 1 );
}
if ( inputView !== view ) {

View file

@ -112,7 +112,7 @@
if ( v[ 0 ] !== '\x1f' ) {
return v.split( '|' );
} else {
return v.substr( 1 ).split( '\x1f' );
return v.slice( 1 ).split( '\x1f' );
}
}
},
@ -973,7 +973,7 @@
if ( Object.prototype.hasOwnProperty.call( availableFormats, params.format + 'fm' ) ) {
params.format = params.format + 'fm';
}
if ( params.format.substr( -2 ) === 'fm' ) {
if ( params.format.slice( -2 ) === 'fm' ) {
params.wrappedhtml = 1;
}
}
@ -1675,8 +1675,8 @@
deprecatedItems = [],
buttons = [],
filterFmModules = function ( v ) {
return v.substr( -2 ) !== 'fm' ||
!Object.prototype.hasOwnProperty.call( availableFormats, v.substr( 0, v.length - 2 ) );
return v.slice( -2 ) !== 'fm' ||
!Object.prototype.hasOwnProperty.call( availableFormats, v.slice( 0, v.length - 2 ) );
};
// This is something of a hack. We always want the 'format' and

View file

@ -30,7 +30,9 @@
*/
.mw-prefs-buttons {
background-color: #fff;
/* stylelint-disable-next-line plugin/no-unsupported-browser-features */
position: -webkit-sticky;
/* stylelint-disable-next-line plugin/no-unsupported-browser-features */
position: sticky;
bottom: 0;
margin-top: -1px;
@ -43,6 +45,7 @@
// Support Edge: The `position: sticky` rule above causes the buttons to
// disappear in RTL languages on Microsoft Edge. This magically fixes the issue. See T220706.
#preferences {
/* stylelint-disable-next-line plugin/no-unsupported-browser-features */
filter: brightness( 1 );
}

View file

@ -51,6 +51,7 @@
// Background properties.
background-repeat: no-repeat;
// Using static value instead of `background-size: contain` because of T233521#5545513.
/* stylelint-disable-next-line plugin/no-unsupported-browser-features */
background-size: @size @size;
background-position: center;
}
@ -64,6 +65,7 @@
.mw-ui-icon {
// reset font-size so the "em" value is relative to the more
// predictable rem font size ...and no rems because we can't have nice things.
/* stylelint-disable-next-line plugin/no-unsupported-browser-features */
font-size: initial;
// sizing
@ -89,7 +91,9 @@
.text-overflow( @visible: false );
// resetting styles for <button> elements
/* stylelint-disable-next-line plugin/no-unsupported-browser-features */
-moz-appearance: none;
/* stylelint-disable-next-line plugin/no-unsupported-browser-features */
-webkit-appearance: none;
background-color: transparent;
margin: 0;
@ -190,6 +194,7 @@
&:before {
// sizing
display: inline-block;
/* stylelint-disable-next-line plugin/no-unsupported-browser-features */
font-size: initial;
width: auto;
min-width: @icon-size-md;

View file

@ -98,7 +98,7 @@
if ( !this.shortZones ) {
this.shortZones = [
'Z',
this.fullZones[ 1 ].substr( 0, 1 ).toUpperCase()
this.fullZones[ 1 ].slice( 0, 1 ).toUpperCase()
];
if ( this.shortZones[ 1 ] === 'Z' ) {
this.shortZones[ 1 ] = 'L';
@ -210,7 +210,7 @@
}
}
if ( last < format.length ) {
ret.push( format.substr( last ) );
ret.push( format.slice( last ) );
}
return ret;

View file

@ -37,28 +37,28 @@
config.shortMonthNames = {};
// eslint-disable-next-line no-jquery/no-each-util
$.each( config.fullMonthNames, function ( k, v ) {
config.shortMonthNames[ k ] = v.substr( 0, 3 );
config.shortMonthNames[ k ] = v.slice( 0, 3 );
} );
}
if ( config.shortDayNames && !config.dayLetters ) {
config.dayLetters = [];
// eslint-disable-next-line no-jquery/no-each-util
$.each( config.shortDayNames, function ( k, v ) {
config.dayLetters[ k ] = v.substr( 0, 1 );
config.dayLetters[ k ] = v.slice( 0, 1 );
} );
}
if ( config.fullDayNames && !config.dayLetters ) {
config.dayLetters = [];
// eslint-disable-next-line no-jquery/no-each-util
$.each( config.fullDayNames, function ( k, v ) {
config.dayLetters[ k ] = v.substr( 0, 1 );
config.dayLetters[ k ] = v.slice( 0, 1 );
} );
}
if ( config.fullDayNames && !config.shortDayNames ) {
config.shortDayNames = {};
// eslint-disable-next-line no-jquery/no-each-util
$.each( config.fullDayNames, function ( k, v ) {
config.shortDayNames[ k ] = v.substr( 0, 3 );
config.shortDayNames[ k ] = v.slice( 0, 3 );
} );
}
config = $.extend( {
@ -159,28 +159,28 @@
this.shortMonthNames = {};
// eslint-disable-next-line no-jquery/no-each-util
$.each( this.fullMonthNames, function ( k, v ) {
this.shortMonthNames[ k ] = v.substr( 0, 3 );
this.shortMonthNames[ k ] = v.slice( 0, 3 );
}.bind( this ) );
}
if ( this.shortDayNames && !this.dayLetters ) {
this.dayLetters = [];
// eslint-disable-next-line no-jquery/no-each-util
$.each( this.shortDayNames, function ( k, v ) {
this.dayLetters[ k ] = v.substr( 0, 1 );
this.dayLetters[ k ] = v.slice( 0, 1 );
}.bind( this ) );
}
if ( this.fullDayNames && !this.dayLetters ) {
this.dayLetters = [];
// eslint-disable-next-line no-jquery/no-each-util
$.each( this.fullDayNames, function ( k, v ) {
this.dayLetters[ k ] = v.substr( 0, 1 );
this.dayLetters[ k ] = v.slice( 0, 1 );
}.bind( this ) );
}
if ( this.fullDayNames && !this.shortDayNames ) {
this.shortDayNames = {};
// eslint-disable-next-line no-jquery/no-each-util
$.each( this.fullDayNames, function ( k, v ) {
this.shortDayNames[ k ] = v.substr( 0, 3 );
this.shortDayNames[ k ] = v.slice( 0, 3 );
}.bind( this ) );
}
@ -243,7 +243,7 @@
this.dayLetters = [];
// eslint-disable-next-line no-jquery/no-each-util
$.each( this.shortDayNames, function ( k, v ) {
this.dayLetters[ k ] = v.substr( 0, 1 );
this.dayLetters[ k ] = v.slice( 0, 1 );
}.bind( this ) );
}

View file

@ -162,12 +162,11 @@
}
return this.getInterwikiPrefixesPromise().then( function ( interwikiPrefixes ) {
var interwiki;
// Optimization: check we have any prefixes.
if ( interwikiPrefixes.length ) {
interwiki = query.substring( 0, query.indexOf( ':' ) );
var interwiki = query.slice( 0, Math.max( 0, query.indexOf( ':' ) ) );
if (
interwiki && interwiki !== '' &&
interwiki !== '' &&
interwikiPrefixes.indexOf( interwiki ) !== -1
) {
// Interwiki prefix is valid: return the original query as a valid title

View file

@ -14,6 +14,8 @@
var mw, log,
con = window.console;
/* https://github.com/gajus/eslint-plugin-jsdoc/issues/806 */
/* eslint-disable jsdoc/valid-types */
/**
* Log a message to window.console, if possible.
*
@ -47,6 +49,7 @@
}
}
}
/* eslint-enable jsdoc/valid-types */
/**
* Create an object that can be read from or written to via methods that allow

View file

@ -1220,9 +1220,8 @@
for ( i = 0; i < modules.length; i++ ) {
// Determine how many bytes this module would add to the query string
// If lastDotIndex is -1, substr() returns an empty string
var lastDotIndex = modules[ i ].lastIndexOf( '.' ),
prefix = modules[ i ].substr( 0, lastDotIndex ),
prefix = modules[ i ].slice( 0, Math.max( 0, lastDotIndex ) ),
suffix = modules[ i ].slice( lastDotIndex + 1 ),
bytesAdded = moduleMap[ prefix ] ?
suffix.length + 3 : // '%2C'.length == 3

View file

@ -12,7 +12,7 @@ describe( 'Listing Users', function () {
before( async () => {
prefix = await utils.title();
prefix = prefix.substring( 0, 7 );
prefix = prefix.slice( 0, 7 );
// NOTE: Because of T199393, the accounts have to be created sequentially.
// Doing so in parallel triggers a race condition that often results in a DBQueryError.

View file

@ -1,3 +1,4 @@
// @vue/component
module.exports = {
data: function () {
return {

View file

@ -1,3 +1,4 @@
// @vue/component
module.exports = {
data: function () {
return {

View file

@ -16,6 +16,7 @@
</template>
<script>
// @vue/component
module.exports = {
data: function () {
return {

View file

@ -34,7 +34,7 @@
*/
QUnit.fixurl = function ( value ) {
return value + ( /\?/.test( value ) ? '&' : '?' ) +
String( new Date().getTime() ) +
String( Date.now() ) +
String( parseInt( Math.random() * 100000, 10 ) );
};

View file

@ -45,7 +45,7 @@
// something is minified, there are occasionally line breaks inserted after
// every few thousand bytes, which means the test result changes over time
// based on the code above.
// eslint-disable-next-line no-multi-str, no-eval
// eslint-disable-next-line no-eval
eval( "({\
main: 'init.js',\
files: {\

View file

@ -63,7 +63,7 @@
assert.strictEqual( typeof mw.now(), 'number', 'Return a number' );
assert.strictEqual(
String( Math.round( mw.now() ) ).length,
String( +new Date() ).length,
String( Date.now() ).length,
'Match size of current timestamp'
);
} );

View file

@ -83,7 +83,7 @@
}
function styleTestLoop() {
var styleTestSince = new Date().getTime() - styleTestStart;
var styleTestSince = Date.now() - styleTestStart;
// If it is passing or if we timed out, run the real test and stop the loop
if ( isCssImportApplied() || styleTestSince > styleTestTimeout ) {
assert.strictEqual( $element.css( prop ), val,
@ -101,7 +101,7 @@
}
// Start the loop
styleTestStart = new Date().getTime();
styleTestStart = Date.now();
styleTestLoop();
}

View file

@ -4,7 +4,7 @@
var clock = this.clock = this.sandbox.useFakeTimers();
this.sandbox.stub( mw, 'now', function () {
return +new Date();
return Date.now();
} );
this.tick = function ( forward ) {