From 6ad73362f376a0399bd1568fe7bbf40425737311 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Bartosz=20Dziewo=C5=84ski?= Date: Fri, 28 Sep 2018 14:36:04 +0200 Subject: [PATCH] eslintrc: Disallow calling String/Array/Object methods introduced in ES6 or later This aims to disallow using the methods listed below, which are supported by Chromium 69 but not supported by Internet Explorer 11. Most of them were introduced in ECMAScript 6, but some are more recent or experimental. We keep breaking IE 11 support by using them. Recent examples include: * mediawiki/core: Ic85063dfbbcf26a99d343845c9fb801f1888d750 * mediawiki/extensions/MultimediaViewer: I0954c42a37668b0eb46c3e864a2e13152a6dc68a * mediawiki/extensions/UploadWizard: I70d37a8f0abcc96b5e39fa71a93cda6f3421c87c * VisualEditor/VisualEditor: Ic1971549da37091c41a847229d18e95aff5c9952 This will unfortunately almost certainly cause false positives, but hopefully not too many of them. Common false positives can be disallowed more precisely using 'no-restricted-syntax' rather than 'no-restricted-properties'. Disallowed methods: String.prototype: codePointAt endsWith includes normalize padEnd (ES 2017) padStart (ES 2017) repeat startsWith trimEnd (experimental/proposed) trimLeft (experimental/proposed) trimRight (experimental/proposed) trimStart (experimental/proposed) Array.prototype: copyWithin entries fill find findIndex flat (experimental/proposed) flatMap (experimental/proposed) includes (ES 2016) keys values String: fromCodePoint raw Array: from of Object: assign entries (ES 2017) getOwnPropertyDescriptors (ES 2017) getOwnPropertySymbols is values (ES 2017) I compiled the list based on running the following code in each browser's console, since there doesn't seem to be an authoritative list anywhere on the Internet: console.log( Object.getOwnPropertyNames( String.prototype ) ) console.log( Object.getOwnPropertyNames( Array.prototype ) ) console.log( Object.getOwnPropertyNames( Object.prototype ) ) console.log( Object.getOwnPropertyNames( String ) ) console.log( Object.getOwnPropertyNames( Array ) ) console.log( Object.getOwnPropertyNames( Object ) ) Change-Id: Ic44c79834f99c52863fbc544ad657787f70fb9bb --- .eslintrc.json | 142 ++++++++++++++++++++++++++++++++++ tests/selenium/.eslintrc.json | 3 +- 2 files changed, 144 insertions(+), 1 deletion(-) diff --git a/.eslintrc.json b/.eslintrc.json index c0767517ea..40e26ca081 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -52,6 +52,148 @@ "object": "$", "property": "proxy", "message": "Please use Function.prototype.bind instead" + }, + + { + "property": "codePointAt", + "message": "Unsupported method String.prototype.codePointAt requires ES6." + }, + { + "property": "endsWith", + "message": "Unsupported method String.prototype.endsWith requires ES6." + }, + { + "property": "normalize", + "message": "Unsupported method String.prototype.normalize requires ES6." + }, + { + "property": "padEnd", + "message": "Unsupported method String.prototype.padEnd requires ES2017." + }, + { + "property": "padStart", + "message": "Unsupported method String.prototype.padStart requires ES2017." + }, + { + "property": "repeat", + "message": "Unsupported method String.prototype.repeat requires ES6." + }, + { + "property": "startsWith", + "message": "Unsupported method String.prototype.startsWith requires ES6." + }, + { + "property": "trimEnd", + "message": "Unsupported method String.prototype.trimEnd is still experimental." + }, + { + "property": "trimLeft", + "message": "Unsupported method String.prototype.trimLeft is still experimental." + }, + { + "property": "trimRight", + "message": "Unsupported method String.prototype.trimRight is still experimental." + }, + { + "property": "trimStart", + "message": "Unsupported method String.prototype.trimStart is still experimental." + }, + { + "property": "copyWithin", + "message": "Unsupported method Array.prototype.copyWithin requires ES6." + }, + { + "property": "entries", + "message": "Unsupported method Array.prototype.entries requires ES6." + }, + { + "property": "fill", + "message": "Unsupported method Array.prototype.fill requires ES6." + }, + { + "property": "findIndex", + "message": "Unsupported method Array.prototype.findIndex requires ES6." + }, + { + "property": "flat", + "message": "Unsupported method Array.prototype.flat is still experimental." + }, + { + "property": "flatMap", + "message": "Unsupported method Array.prototype.flatMap is still experimental." + }, + { + "object": "String", + "property": "fromCodePoint", + "message": "Unsupported method String.fromCodePoint requires ES6." + }, + { + "object": "String", + "property": "raw", + "message": "Unsupported method String.raw requires ES6." + }, + { + "object": "Array", + "property": "from", + "message": "Unsupported method Array.from requires ES6." + }, + { + "object": "Array", + "property": "of", + "message": "Unsupported method Array.of requires ES6." + }, + { + "object": "Object", + "property": "assign", + "message": "Unsupported method Object.assign requires ES6." + }, + { + "object": "Object", + "property": "entries", + "message": "Unsupported method Object.entries requires ES2017." + }, + { + "object": "Object", + "property": "getOwnPropertyDescriptors", + "message": "Unsupported method Object.getOwnPropertyDescriptors requires ES2017." + }, + { + "object": "Object", + "property": "getOwnPropertySymbols", + "message": "Unsupported method Object.getOwnPropertySymbols requires ES6." + }, + { + "object": "Object", + "property": "is", + "message": "Unsupported method Object.is requires ES6." + }, + { + "object": "Object", + "property": "values", + "message": "Unsupported method Object.values requires ES2017." + } + ], + "no-restricted-syntax": [ + 2, + { + // Match expressions like .includes( … ) (false positives when used as a property name) + "selector": "CallExpression[callee.type='MemberExpression'][callee.property.type='Identifier'][callee.property.name='includes']", + "message": "Unsupported methods String.prototype.includes and Array.prototype.includes require ES6 and ES2016 respectively." + }, + { + // Match expressions like .find( function ( … ) { … } ) (avoid $( … ).find( … )) + "selector": "CallExpression[callee.type='MemberExpression'][callee.property.type='Identifier'][callee.property.name='find'][arguments.length=1][arguments.0.type='FunctionExpression']", + "message": "Unsupported method Array.prototype.find requires ES6." + }, + { + // Match expressions like .keys( … ), except Object.keys( … ) (which is valid) + "selector": "CallExpression[callee.type='MemberExpression'][callee.property.type='Identifier'][callee.property.name='keys'][callee.object.name!='Object']", + "message": "Unsupported method Array.prototype.keys requires ES6." + }, + { + // Match expressions like .values( … ), except Object.values( … ) (disallowed separately) + "selector": "CallExpression[callee.type='MemberExpression'][callee.property.type='Identifier'][callee.property.name='values'][callee.object.name!='Object']", + "message": "Unsupported method Array.prototype.values requires ES6." } ], "dot-notation": 0, diff --git a/tests/selenium/.eslintrc.json b/tests/selenium/.eslintrc.json index e39226c4ac..ad4c97bd9f 100644 --- a/tests/selenium/.eslintrc.json +++ b/tests/selenium/.eslintrc.json @@ -9,6 +9,7 @@ "browser": false }, "rules":{ - "no-console": 0 + "no-console": 0, + "no-restricted-properties": 0 } } -- 2.20.1