From 1ded08465bab88d58e722dcf5b496d2e5a557023 Mon Sep 17 00:00:00 2001 From: jdlrobson Date: Fri, 10 Aug 2018 11:02:22 -0700 Subject: [PATCH] Hygiene: Discourage use of $.each Even though Array.prototype.forEach only works on arrays, and $.each is more generic, I think it makes sense to begin discouraging the usage of $.each now. This can be overriden by ignore lines or by Array.prototype.forEach compatible lines. This doesn't seem too much of an ask of engineers and helps future migrations Bug: T200877 Change-Id: I339cff311a830699c8e32f07cec338a39870c53f --- .eslintrc.json | 5 +++++ resources/src/jquery.tablesorter/jquery.tablesorter.js | 2 ++ resources/src/mediawiki.Uri/Uri.js | 1 + .../src/mediawiki.action/mediawiki.action.edit.preview.js | 1 + resources/src/mediawiki.api/index.js | 1 + resources/src/mediawiki.api/upload.js | 1 + resources/src/mediawiki.inspect.js | 1 + resources/src/mediawiki.jqueryMsg/mediawiki.jqueryMsg.js | 2 ++ .../mediawiki.rcfilters/dm/mw.rcfilters.dm.FilterGroup.js | 1 + .../src/mediawiki.rcfilters/dm/mw.rcfilters.dm.FilterItem.js | 1 + .../dm/mw.rcfilters.dm.FiltersViewModel.js | 1 + .../dm/mw.rcfilters.dm.SavedQueriesModel.js | 1 + resources/src/mediawiki.rcfilters/mw.rcfilters.Controller.js | 1 + .../mediawiki.rcfilters/ui/mw.rcfilters.ui.GroupWidget.js | 1 + .../ui/mw.rcfilters.ui.MenuSelectWidget.js | 2 ++ resources/src/mediawiki.special.apisandbox/apisandbox.js | 1 + resources/src/mediawiki.template.mustache.js | 1 + .../src/mediawiki.widgets.datetime/DateTimeInputWidget.js | 1 + .../mw.widgets.CategoryMultiselectWidget.js | 4 ++-- .../mediawiki.widgets/mw.widgets.CategoryTagItemWidget.js | 4 ++-- .../src/mediawiki.widgets/mw.widgets.CheckMatrixWidget.js | 4 ++++ .../src/mediawiki.widgets/mw.widgets.SearchInputWidget.js | 1 + tests/qunit/data/testrunner.js | 3 +++ .../qunit/suites/resources/mediawiki/mediawiki.cldr.test.js | 1 + .../suites/resources/mediawiki/mediawiki.language.test.js | 1 + .../qunit/suites/resources/mediawiki/mediawiki.util.test.js | 1 + 26 files changed, 40 insertions(+), 4 deletions(-) diff --git a/.eslintrc.json b/.eslintrc.json index f08861759b..4630e071e5 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -25,6 +25,11 @@ "property": "inArray", "message": "Please use Array.prototype.indexOf instead" }, + { + "object": "$", + "property": "each", + "message": "Please consider different approaches to $.each, especially when using Array's. You can override this warning if necessary with eslint-disable-next-line." + }, { "object": "$", "property": "isArray", diff --git a/resources/src/jquery.tablesorter/jquery.tablesorter.js b/resources/src/jquery.tablesorter/jquery.tablesorter.js index 6287126f6b..cbdc2fa9b3 100644 --- a/resources/src/jquery.tablesorter/jquery.tablesorter.js +++ b/resources/src/jquery.tablesorter/jquery.tablesorter.js @@ -324,6 +324,7 @@ // Loop through all the dom cells of the thead $tableRows.each( function ( rowIndex, row ) { + // eslint-disable-next-line no-restricted-properties $.each( row.cells, function ( columnIndex, cell ) { var matrixRowIndex, matrixColumnIndex; @@ -770,6 +771,7 @@ function convertSortList( sortObjects ) { var sortList = []; sortObjects.forEach( function ( sortObject ) { + // eslint-disable-next-line no-restricted-properties $.each( sortObject, function ( columnIndex, order ) { var orderIndex = ( order === 'desc' ) ? 1 : 0; sortList.push( [ parseInt( columnIndex, 10 ), orderIndex ] ); diff --git a/resources/src/mediawiki.Uri/Uri.js b/resources/src/mediawiki.Uri/Uri.js index eb7cff0c66..bfdfc88077 100644 --- a/resources/src/mediawiki.Uri/Uri.js +++ b/resources/src/mediawiki.Uri/Uri.js @@ -368,6 +368,7 @@ */ getQueryString: function () { var args = []; + // eslint-disable-next-line no-restricted-properties $.each( this.query, function ( key, val ) { var k = Uri.encode( key ), vals = Array.isArray( val ) ? val : [ val ]; diff --git a/resources/src/mediawiki.action/mediawiki.action.edit.preview.js b/resources/src/mediawiki.action/mediawiki.action.edit.preview.js index b87fba77a5..dc1f33b7d8 100644 --- a/resources/src/mediawiki.action/mediawiki.action.edit.preview.js +++ b/resources/src/mediawiki.action/mediawiki.action.edit.preview.js @@ -149,6 +149,7 @@ } newList = []; + // eslint-disable-next-line no-restricted-properties $.each( response.parse.indicators, function ( name, indicator ) { newList.push( $( '
' ) diff --git a/resources/src/mediawiki.api/index.js b/resources/src/mediawiki.api/index.js index 51f359c54a..8c9b309e2b 100644 --- a/resources/src/mediawiki.api/index.js +++ b/resources/src/mediawiki.api/index.js @@ -53,6 +53,7 @@ // Pre-populate with fake ajax promises to save http requests for tokens // we already have on the page via the user.tokens module (T36733). promises[ defaultOptions.ajax.url ] = {}; + // eslint-disable-next-line no-restricted-properties $.each( mw.user.tokens.get(), function ( key, value ) { // This requires #getToken to use the same key as user.tokens. // Format: token-type + "Token" (eg. csrfToken, patrolToken, watchToken). diff --git a/resources/src/mediawiki.api/upload.js b/resources/src/mediawiki.api/upload.js index f343321e13..dc82fb5555 100644 --- a/resources/src/mediawiki.api/upload.js +++ b/resources/src/mediawiki.api/upload.js @@ -233,6 +233,7 @@ file.name = 'file'; + // eslint-disable-next-line no-restricted-properties $.each( data, function ( key, val ) { $form.append( getHiddenInput( key, val ) ); } ); diff --git a/resources/src/mediawiki.inspect.js b/resources/src/mediawiki.inspect.js index f4545dee0f..3a649a90b1 100644 --- a/resources/src/mediawiki.inspect.js +++ b/resources/src/mediawiki.inspect.js @@ -153,6 +153,7 @@ style.textContent = css; document.body.appendChild( style ); + // eslint-disable-next-line no-restricted-properties $.each( style.sheet.cssRules, function ( index, rule ) { selectors.total++; // document.querySelector() on prefixed pseudo-elements can throw exceptions diff --git a/resources/src/mediawiki.jqueryMsg/mediawiki.jqueryMsg.js b/resources/src/mediawiki.jqueryMsg/mediawiki.jqueryMsg.js index b7fd6fdeb4..b3154e155f 100644 --- a/resources/src/mediawiki.jqueryMsg/mediawiki.jqueryMsg.js +++ b/resources/src/mediawiki.jqueryMsg/mediawiki.jqueryMsg.js @@ -957,6 +957,7 @@ mw.jqueryMsg.HtmlEmitter = function ( language, magic ) { var jmsg = this; this.language = language; + // eslint-disable-next-line no-restricted-properties $.each( magic, function ( key, val ) { jmsg[ key.toLowerCase() ] = function () { return val; @@ -1022,6 +1023,7 @@ */ concat: function ( nodes ) { var $span = $( '' ).addClass( 'mediaWiki_htmlEmitter' ); + // eslint-disable-next-line no-restricted-properties $.each( nodes, function ( i, node ) { // Let jQuery append nodes, arrays of nodes and jQuery objects // other things (strings, numbers, ..) are appended as text nodes (not as HTML strings) diff --git a/resources/src/mediawiki.rcfilters/dm/mw.rcfilters.dm.FilterGroup.js b/resources/src/mediawiki.rcfilters/dm/mw.rcfilters.dm.FilterGroup.js index a62acc5b9e..7aceed65d4 100644 --- a/resources/src/mediawiki.rcfilters/dm/mw.rcfilters.dm.FilterGroup.js +++ b/resources/src/mediawiki.rcfilters/dm/mw.rcfilters.dm.FilterGroup.js @@ -1,3 +1,4 @@ +/* eslint-disable no-restricted-properties */ ( function ( mw ) { /** * View model for a filter group diff --git a/resources/src/mediawiki.rcfilters/dm/mw.rcfilters.dm.FilterItem.js b/resources/src/mediawiki.rcfilters/dm/mw.rcfilters.dm.FilterItem.js index d7f7b02111..7e35b333e0 100644 --- a/resources/src/mediawiki.rcfilters/dm/mw.rcfilters.dm.FilterItem.js +++ b/resources/src/mediawiki.rcfilters/dm/mw.rcfilters.dm.FilterItem.js @@ -94,6 +94,7 @@ key = key || 'contextDescription'; + // eslint-disable-next-line no-restricted-properties $.each( conflicts, function ( filterName, conflict ) { if ( !conflict.item.isSelected() ) { return; diff --git a/resources/src/mediawiki.rcfilters/dm/mw.rcfilters.dm.FiltersViewModel.js b/resources/src/mediawiki.rcfilters/dm/mw.rcfilters.dm.FiltersViewModel.js index cdf1f63517..45d54a03cd 100644 --- a/resources/src/mediawiki.rcfilters/dm/mw.rcfilters.dm.FiltersViewModel.js +++ b/resources/src/mediawiki.rcfilters/dm/mw.rcfilters.dm.FiltersViewModel.js @@ -1,3 +1,4 @@ +/* eslint-disable no-restricted-properties */ ( function ( mw, $ ) { /** * View model for the filters selection and display diff --git a/resources/src/mediawiki.rcfilters/dm/mw.rcfilters.dm.SavedQueriesModel.js b/resources/src/mediawiki.rcfilters/dm/mw.rcfilters.dm.SavedQueriesModel.js index 77d5961a6e..e7cb6b680d 100644 --- a/resources/src/mediawiki.rcfilters/dm/mw.rcfilters.dm.SavedQueriesModel.js +++ b/resources/src/mediawiki.rcfilters/dm/mw.rcfilters.dm.SavedQueriesModel.js @@ -1,3 +1,4 @@ +/* eslint-disable no-restricted-properties */ ( function ( mw, $ ) { /** * View model for saved queries diff --git a/resources/src/mediawiki.rcfilters/mw.rcfilters.Controller.js b/resources/src/mediawiki.rcfilters/mw.rcfilters.Controller.js index 5af001e1c3..1664e86135 100644 --- a/resources/src/mediawiki.rcfilters/mw.rcfilters.Controller.js +++ b/resources/src/mediawiki.rcfilters/mw.rcfilters.Controller.js @@ -1,3 +1,4 @@ +/* eslint-disable no-restricted-properties */ ( function ( mw, $ ) { var byteLength = require( 'mediawiki.String' ).byteLength; diff --git a/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.GroupWidget.js b/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.GroupWidget.js index 167df09112..7a95e3dd4c 100644 --- a/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.GroupWidget.js +++ b/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.GroupWidget.js @@ -22,6 +22,7 @@ if ( config.events ) { // Aggregate events + // eslint-disable-next-line no-restricted-properties $.each( config.events, function ( eventName, eventEmit ) { aggregate[ eventName ] = eventEmit; } ); diff --git a/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.MenuSelectWidget.js b/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.MenuSelectWidget.js index 40b2fcf1d0..d4f0aea070 100644 --- a/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.MenuSelectWidget.js +++ b/resources/src/mediawiki.rcfilters/ui/mw.rcfilters.ui.MenuSelectWidget.js @@ -149,6 +149,7 @@ this.$overlay.append( this.highlightPopup.$element ); // Count groups per view + // eslint-disable-next-line no-restricted-properties $.each( groups, function ( groupName, groupModel ) { if ( !groupModel.isHidden() ) { viewGroupCount[ groupModel.getView() ] = viewGroupCount[ groupModel.getView() ] || 0; @@ -156,6 +157,7 @@ } } ); + // eslint-disable-next-line no-restricted-properties $.each( groups, function ( groupName, groupModel ) { var currentItems = [], view = groupModel.getView(); diff --git a/resources/src/mediawiki.special.apisandbox/apisandbox.js b/resources/src/mediawiki.special.apisandbox/apisandbox.js index beac624ee9..ad5fb065d0 100644 --- a/resources/src/mediawiki.special.apisandbox/apisandbox.js +++ b/resources/src/mediawiki.special.apisandbox/apisandbox.js @@ -1597,6 +1597,7 @@ } toRemove = {}; + // eslint-disable-next-line no-restricted-properties $.each( this.templatedItemsCache, function ( k, el ) { if ( el.widget.isElementAttached() ) { toRemove[ k ] = el; diff --git a/resources/src/mediawiki.template.mustache.js b/resources/src/mediawiki.template.mustache.js index 9f5e5c4e9f..c3139a29cf 100644 --- a/resources/src/mediawiki.template.mustache.js +++ b/resources/src/mediawiki.template.mustache.js @@ -21,6 +21,7 @@ render: function ( data, partialTemplates ) { var partials = {}; if ( partialTemplates ) { + /* eslint-disable-next-line no-restricted-properties */ $.each( partialTemplates, function ( name, template ) { partials[ name ] = template.getSource(); } ); diff --git a/resources/src/mediawiki.widgets.datetime/DateTimeInputWidget.js b/resources/src/mediawiki.widgets.datetime/DateTimeInputWidget.js index 17f1fb4607..77271f7b76 100644 --- a/resources/src/mediawiki.widgets.datetime/DateTimeInputWidget.js +++ b/resources/src/mediawiki.widgets.datetime/DateTimeInputWidget.js @@ -373,6 +373,7 @@ } else { maxlength = spec.size; if ( spec.intercalarySize ) { + // eslint-disable-next-line no-restricted-properties $.each( spec.intercalarySize, reduceFunc ); } $field = $( '' ).attr( 'type', 'text' ) diff --git a/resources/src/mediawiki.widgets/mw.widgets.CategoryMultiselectWidget.js b/resources/src/mediawiki.widgets/mw.widgets.CategoryMultiselectWidget.js index c5063797ed..a71b3d11ce 100644 --- a/resources/src/mediawiki.widgets/mw.widgets.CategoryMultiselectWidget.js +++ b/resources/src/mediawiki.widgets/mw.widgets.CategoryMultiselectWidget.js @@ -321,7 +321,7 @@ } ).done( function ( res ) { var categories = []; - $.each( res.query.pages, function ( index, page ) { + res.query.pages.forEach( function ( page ) { if ( !page.missing ) { categories.push( page.title ); } @@ -367,7 +367,7 @@ } ).done( function ( res ) { var categories = []; - $.each( res.query.pages, function ( index, page ) { + res.query.pages.forEach( function ( page ) { if ( !page.missing && Array.isArray( page.categories ) ) { categories.push.apply( categories, page.categories.map( function ( category ) { return category.title; diff --git a/resources/src/mediawiki.widgets/mw.widgets.CategoryTagItemWidget.js b/resources/src/mediawiki.widgets/mw.widgets.CategoryTagItemWidget.js index f0b2d44e35..77c2c359d7 100644 --- a/resources/src/mediawiki.widgets/mw.widgets.CategoryTagItemWidget.js +++ b/resources/src/mediawiki.widgets/mw.widgets.CategoryTagItemWidget.js @@ -57,10 +57,10 @@ var normalized = {}, pages = {}; - $.each( response.query.normalized || [], function ( index, data ) { + ( response.query.normalized || [] ).forEach( function ( data ) { normalized[ data.fromencoded ? decodeURIComponent( data.from ) : data.from ] = data.to; } ); - $.each( response.query.pages, function ( index, page ) { + response.query.pages.forEach( function ( page ) { pages[ page.title ] = !page.missing; } ); titles.forEach( function ( title ) { diff --git a/resources/src/mediawiki.widgets/mw.widgets.CheckMatrixWidget.js b/resources/src/mediawiki.widgets/mw.widgets.CheckMatrixWidget.js index 21b4f101e2..64b75927d4 100644 --- a/resources/src/mediawiki.widgets/mw.widgets.CheckMatrixWidget.js +++ b/resources/src/mediawiki.widgets/mw.widgets.CheckMatrixWidget.js @@ -40,12 +40,14 @@ $headRow.append( $( '' ).text( '\u00A0' ) ); // Iterate over the columns object (ignore the value) + // eslint-disable-next-line no-restricted-properties $.each( this.columns, function ( columnLabel ) { $headRow.append( $( '' ).html( columnLabel ) ); } ); $table.append( $headRow ); // Build table + // eslint-disable-next-line no-restricted-properties $.each( this.rows, function ( rowLabel, rowTag ) { var $row = $( '' ), labelField = new OO.ui.FieldLayout( @@ -61,6 +63,7 @@ $row.append( $( '' ).append( labelField.$element ) ); // Columns + // eslint-disable-next-line no-restricted-properties $.each( widget.columns, function ( columnLabel, columnTag ) { var thisTag = columnTag + '-' + rowTag, checkbox = new OO.ui.CheckboxInputWidget( { @@ -135,6 +138,7 @@ // setDisabled sometimes gets called before the widget is ready if ( this.checkboxes && Object.keys( this.checkboxes ).length > 0 ) { // Propagate to all checkboxes and update their disabled state + // eslint-disable-next-line no-restricted-properties $.each( this.checkboxes, function ( name, checkbox ) { checkbox.setDisabled( widget.isTagDisabled( name ) ); } ); diff --git a/resources/src/mediawiki.widgets/mw.widgets.SearchInputWidget.js b/resources/src/mediawiki.widgets/mw.widgets.SearchInputWidget.js index c25ab45067..75bf891cee 100644 --- a/resources/src/mediawiki.widgets/mw.widgets.SearchInputWidget.js +++ b/resources/src/mediawiki.widgets/mw.widgets.SearchInputWidget.js @@ -191,6 +191,7 @@ urls = data.data[ 3 ], self = this; + // eslint-disable-next-line no-restricted-properties $.each( titles, function ( i, result ) { items.push( new mw.widgets.TitleOptionWidget( self.getOptionWidgetData( diff --git a/tests/qunit/data/testrunner.js b/tests/qunit/data/testrunner.js index d8972ab389..981043bc2d 100644 --- a/tests/qunit/data/testrunner.js +++ b/tests/qunit/data/testrunner.js @@ -258,6 +258,7 @@ // Check for incomplete animations/requests/etc and throw if there are any. if ( $.timers && $.timers.length !== 0 ) { timers = $.timers.length; + // eslint-disable-next-line no-restricted-properties $.each( $.timers, function ( i, timer ) { var node = timer.elem; mw.log.warn( 'Unfinished animation #' + i + ' in ' + timer.queue + ' queue on ' + @@ -305,6 +306,8 @@ QUnit.whenPromisesComplete = function () { var altPromises = []; + // When we have ES6 support we'll be able to use Array.from here + // eslint-disable-next-line no-restricted-properties $.each( arguments, function ( i, arg ) { var alt = $.Deferred(); altPromises.push( alt ); diff --git a/tests/qunit/suites/resources/mediawiki/mediawiki.cldr.test.js b/tests/qunit/suites/resources/mediawiki/mediawiki.cldr.test.js index 17eaa7e1e6..b5824d33b0 100644 --- a/tests/qunit/suites/resources/mediawiki/mediawiki.cldr.test.js +++ b/tests/qunit/suites/resources/mediawiki/mediawiki.cldr.test.js @@ -74,6 +74,7 @@ } ); } + // eslint-disable-next-line no-restricted-properties $.each( pluralTestcases, function ( langCode, tests ) { if ( langCode === mw.config.get( 'wgUserLanguage' ) ) { pluralTest( langCode, tests ); diff --git a/tests/qunit/suites/resources/mediawiki/mediawiki.language.test.js b/tests/qunit/suites/resources/mediawiki/mediawiki.language.test.js index 9ea3c110f3..d460c0be14 100644 --- a/tests/qunit/suites/resources/mediawiki/mediawiki.language.test.js +++ b/tests/qunit/suites/resources/mediawiki/mediawiki.language.test.js @@ -598,6 +598,7 @@ ] }; + // eslint-disable-next-line no-restricted-properties $.each( grammarTests, function ( langCode, test ) { if ( langCode === mw.config.get( 'wgUserLanguage' ) ) { grammarTest( langCode, test ); diff --git a/tests/qunit/suites/resources/mediawiki/mediawiki.util.test.js b/tests/qunit/suites/resources/mediawiki/mediawiki.util.test.js index 272b1471dd..0a65788682 100644 --- a/tests/qunit/suites/resources/mediawiki/mediawiki.util.test.js +++ b/tests/qunit/suites/resources/mediawiki/mediawiki.util.test.js @@ -150,6 +150,7 @@ QUnit.test( 'wikiUrlencode', function ( assert ) { assert.strictEqual( util.wikiUrlencode( 'Test:A & B/Here' ), 'Test:A_%26_B/Here' ); // See also wfUrlencodeTest.php#provideURLS + // eslint-disable-next-line no-restricted-properties $.each( { '+': '%2B', '&': '%26', -- 2.20.1