[gjs: 33/43] CI: Add prefer-rest-params and prefer-spread to eslint rules



commit 5e6a65a8cfe63df25e5514930d06e2fcb54e9e0e
Author: Philip Chimento <philip chimento gmail com>
Date:   Sun Aug 4 18:05:50 2019 -0700

    CI: Add prefer-rest-params and prefer-spread to eslint rules
    
    The 'arguments' object is a weird almost-but-not-quite array, which can
    often be a source of bugs. Additionally, calling variadic functions with
    the spread operator is often a lot more readable.

 .eslintrc.yml                           |  2 ++
 installed-tests/js/testGIMarshalling.js | 20 +++---------
 installed-tests/js/testLegacyClass.js   | 12 +++----
 modules/_legacy.js                      | 56 ++++++++++++++++-----------------
 modules/format.js                       |  7 ++---
 modules/lang.js                         |  7 ++---
 modules/overrides/GObject.js            | 21 ++++++-------
 modules/overrides/Gio.js                | 13 ++++----
 modules/tweener/tweener.js              |  2 +-
 9 files changed, 61 insertions(+), 79 deletions(-)
---
diff --git a/.eslintrc.yml b/.eslintrc.yml
index 2ae05603..3a55280c 100644
--- a/.eslintrc.yml
+++ b/.eslintrc.yml
@@ -114,6 +114,8 @@ rules:
   object-curly-spacing: error
   object-shorthand: error
   operator-linebreak: error
+  prefer-rest-params: error
+  prefer-spread: error
   prefer-template: error
   quotes:
     - error
diff --git a/installed-tests/js/testGIMarshalling.js b/installed-tests/js/testGIMarshalling.js
index e4102877..96fbf94e 100644
--- a/installed-tests/js/testGIMarshalling.js
+++ b/installed-tests/js/testGIMarshalling.js
@@ -702,16 +702,12 @@ describe('GObject virtual function', function () {
 
         let key = 'vfunc_constructed';
 
-        class _SimpleTestClass1 extends GObject.Object {
-            _init() {
-                super._init(...arguments);
-            }
-        }
+        class _SimpleTestClass1 extends GObject.Object {}
 
         if (GObject.Object.prototype.vfunc_constructed) {
             let parentFunc = GObject.Object.prototype.vfunc_constructed;
-            _SimpleTestClass1.prototype[key] = function () {
-                parentFunc.call(this, ...arguments);
+            _SimpleTestClass1.prototype[key] = function (...args) {
+                parentFunc.call(this, ...args);
                 callback('123');
             };
         } else {
@@ -732,10 +728,6 @@ describe('GObject virtual function', function () {
         let callback;
 
         class _SimpleTestClass2 extends GObject.Object {
-            _init() {
-                super._init(...arguments);
-            }
-
             vfunc_constructed() {
                 super.vfunc_constructed();
                 callback('vfunc_constructed');
@@ -751,11 +743,7 @@ describe('GObject virtual function', function () {
     });
 
     it('handles non-existing properties', function () {
-        const _SimpleTestClass3 = class extends GObject.Object {
-            _init() {
-                super._init(...arguments);
-            }
-        };
+        const _SimpleTestClass3 = class extends GObject.Object {};
 
         _SimpleTestClass3.prototype.vfunc_doesnt_exist = function () {};
 
diff --git a/installed-tests/js/testLegacyClass.js b/installed-tests/js/testLegacyClass.js
index cc5f1875..7c0ab77a 100644
--- a/installed-tests/js/testLegacyClass.js
+++ b/installed-tests/js/testLegacyClass.js
@@ -377,9 +377,9 @@ const InterfaceRequiringOtherInterface = new Lang.Interface({
     Name: 'InterfaceRequiringOtherInterface',
     Requires: [AnInterface],
 
-    optional() {
+    optional(...args) {
         return `InterfaceRequiringOtherInterface.optional()\n${
-            AnInterface.prototype.optional.apply(this, arguments)}`;
+            AnInterface.prototype.optional.apply(this, args)}`;
     },
 
     optionalGeneric() {
@@ -398,8 +398,8 @@ const ObjectImplementingAnInterface = new Lang.Class({
 
     required() {},
 
-    optional() {
-        return AnInterface.prototype.optional.apply(this, arguments);
+    optional(...args) {
+        return AnInterface.prototype.optional.apply(this, args);
     },
 
     optionalGeneric() {
@@ -429,8 +429,8 @@ const ImplementationOfTwoInterfaces = new Lang.Class({
 
     required() {},
 
-    optional() {
-        return InterfaceRequiringOtherInterface.prototype.optional.apply(this, arguments);
+    optional(...args) {
+        return InterfaceRequiringOtherInterface.prototype.optional.apply(this, args);
     },
 
     optionalGeneric() {
diff --git a/modules/_legacy.js b/modules/_legacy.js
index 455bc736..10234ca0 100644
--- a/modules/_legacy.js
+++ b/modules/_legacy.js
@@ -14,8 +14,8 @@ function _Base() {
 
 _Base.__super__ = null;
 _Base.prototype._init = function() { };
-_Base.prototype._construct = function() {
-    this._init.apply(this, arguments);
+_Base.prototype._construct = function(...args) {
+    this._init(...args);
     return this;
 };
 _Base.prototype.__name__ = '_Base';
@@ -23,7 +23,7 @@ _Base.prototype.toString = function() {
     return `[object ${this.__name__}]`;
 };
 
-function _parent() {
+function _parent(...args) {
     if (!this.__caller__)
         throw new TypeError("The method 'parent' cannot be called");
 
@@ -36,7 +36,7 @@ function _parent() {
     if (!previous)
         throw new TypeError(`The method '${name}' is not on the superclass`);
 
-    return previous.apply(this, arguments);
+    return previous.apply(this, args);
 }
 
 function _interfacePresent(required, proto) {
@@ -58,13 +58,13 @@ function getMetaClass(params) {
     return null;
 }
 
-function Class(params) {
+function Class(params, ...otherArgs) {
     let metaClass = getMetaClass(params);
 
     if (metaClass && metaClass !== this.constructor)
-        return new metaClass(...arguments);
+        return new metaClass(params, ...otherArgs);
     else
-        return this._construct.apply(this, arguments);
+        return this._construct(params, ...otherArgs);
 }
 
 Class.__super__ = _Base;
@@ -76,10 +76,10 @@ Class.prototype.wrapFunction = function(name, meth) {
     if (meth._origin)
         meth = meth._origin;
 
-    function wrapper() {
+    function wrapper(...args) {
         let prevCaller = this.__caller__;
         this.__caller__ = wrapper;
-        let result = meth.apply(this, arguments);
+        let result = meth.apply(this, args);
         this.__caller__ = prevCaller;
         return result;
     }
@@ -95,7 +95,7 @@ Class.prototype.toString = function() {
     return `[object ${this.__name__} for ${this.prototype.__name__}]`;
 };
 
-Class.prototype._construct = function(params) {
+Class.prototype._construct = function(params, ...otherArgs) {
     if (!params.Name)
         throw new TypeError("Classes require an explicit 'Name' parameter.");
 
@@ -105,13 +105,13 @@ Class.prototype._construct = function(params) {
     if (!parent)
         parent = _Base;
 
-    function newClass() {
+    function newClass(...args) {
         if (params.Abstract && new.target.name === name)
             throw new TypeError(`Cannot instantiate abstract class ${name}`);
 
         this.__caller__ = null;
 
-        return this._construct(...arguments);
+        return this._construct(...args);
     }
 
     // Since it's not possible to create a constructor with
@@ -124,7 +124,7 @@ Class.prototype._construct = function(params) {
     newClass.prototype = Object.create(parent.prototype);
     newClass.prototype.constructor = newClass;
 
-    newClass._init.apply(newClass, arguments);
+    newClass._init(params, ...otherArgs);
 
     let interfaces = params.Implements || [];
     // If the parent already implements an interface, then we do too
@@ -273,11 +273,11 @@ function _getMetaInterface(params) {
     return metaInterface;
 }
 
-function Interface(params) {
+function Interface(params, ...otherArgs) {
     let metaInterface = _getMetaInterface(params);
     if (metaInterface && metaInterface !== this.constructor)
-        return new metaInterface(...arguments);
-    return this._construct.apply(this, arguments);
+        return new metaInterface(params, ...otherArgs);
+    return this._construct(params, ...otherArgs);
 }
 
 Class.MetaInterface = Interface;
@@ -296,7 +296,7 @@ Interface.prototype = Object.create(_Base.prototype);
 Interface.prototype.constructor = Interface;
 Interface.prototype.__name__ = 'Interface';
 
-Interface.prototype._construct = function (params) {
+Interface.prototype._construct = function (params, ...otherArgs) {
     if (!params.Name)
         throw new TypeError("Interfaces require an explicit 'Name' parameter.");
 
@@ -307,7 +307,7 @@ Interface.prototype._construct = function (params) {
     newInterface.prototype.constructor = newInterface;
     newInterface.prototype.__name__ = params.Name;
 
-    newInterface._init.apply(newInterface, arguments);
+    newInterface._init(params, ...otherArgs);
 
     Object.defineProperty(newInterface.prototype, '__metaclass__', {
         writable: false,
@@ -380,9 +380,8 @@ Interface.prototype._init = function (params) {
         // SomeInterface.prototype.some_function.call(this, blah)
         if (typeof descriptor.value === 'function') {
             let interfaceProto = this.prototype;  // capture in closure
-            this[name] = function () {
-                return interfaceProto[name].call.apply(interfaceProto[name],
-                    arguments);
+            this[name] = function (thisObj, ...args) {
+                return interfaceProto[name].call(thisObj, ...args);
             };
         }
 
@@ -481,8 +480,7 @@ function defineGObjectLegacyObjects(GObject) {
                     } else if (name.startsWith('on_')) {
                         let id = GObject.signal_lookup(name.slice(3).replace('_', '-'), this.$gtype);
                         if (id !== 0) {
-                            GObject.signal_override_class_closure(id, this.$gtype, function() {
-                                let argArray = Array.prototype.slice.call(arguments);
+                            GObject.signal_override_class_closure(id, this.$gtype, function(...argArray) {
                                 let emitter = argArray.shift();
 
                                 return wrapped.apply(emitter, argArray);
@@ -508,7 +506,7 @@ function defineGObjectLegacyObjects(GObject) {
 
         // If we want an object with a custom JSClass, we can't just
         // use a function. We have to use a custom constructor here.
-        _construct(params) {
+        _construct(params, ...otherArgs) {
             if (!params.Name)
                 throw new TypeError("Classes require an explicit 'Name' parameter.");
             let name = params.Name;
@@ -539,7 +537,7 @@ function defineGObjectLegacyObjects(GObject) {
             Object.setPrototypeOf(newClass, this.constructor.prototype);
             newClass.__super__ = parent;
 
-            newClass._init.apply(newClass, arguments);
+            newClass._init(params, ...otherArgs);
 
             Object.defineProperties(newClass.prototype, {
                 '__metaclass__': {
@@ -580,8 +578,8 @@ function defineGObjectLegacyObjects(GObject) {
         },
     });
 
-    function GObjectInterface() {
-        return this._construct.apply(this, arguments);
+    function GObjectInterface(...args) {
+        return this._construct(...args);
     }
 
     GObjectMeta.MetaInterface = GObjectInterface;
@@ -591,7 +589,7 @@ function defineGObjectLegacyObjects(GObject) {
     GObjectInterface.prototype.constructor = GObjectInterface;
     GObjectInterface.prototype.__name__ = 'GObjectInterface';
 
-    GObjectInterface.prototype._construct = function (params) {
+    GObjectInterface.prototype._construct = function (params, ...otherArgs) {
         if (!params.Name)
             throw new TypeError("Interfaces require an explicit 'Name' parameter.");
 
@@ -613,7 +611,7 @@ function defineGObjectLegacyObjects(GObject) {
         newInterface.__super__ = GObjectInterface;
         newInterface.prototype.constructor = newInterface;
 
-        newInterface._init.apply(newInterface, arguments);
+        newInterface._init(params, ...otherArgs);
 
         Object.defineProperty(newInterface.prototype, '__metaclass__', {
             writable: false,
diff --git a/modules/format.js b/modules/format.js
index f57713d6..8f5a5c36 100644
--- a/modules/format.js
+++ b/modules/format.js
@@ -66,8 +66,7 @@ function vprintf(string, args) {
     });
 }
 
-function printf() {
-    let args = Array.prototype.slice.call(arguments);
+function printf(...args) {
     let fmt = args.shift();
     print(vprintf(fmt, args));
 }
@@ -83,6 +82,6 @@ function printf() {
  * field width, e.g. "%5s".format("foo"). Unless the width is prefixed
  * with '0', the formatted string will be padded with spaces.
  */
-function format() {
-    return vprintf(this, arguments);
+function format(...args) {
+    return vprintf(this, args);
 }
diff --git a/modules/lang.js b/modules/lang.js
index cc035d43..e59a2d10 100644
--- a/modules/lang.js
+++ b/modules/lang.js
@@ -66,7 +66,7 @@ function copyPublicProperties(source, dest) {
  * @returns: a new callback
  * @type: function
  */
-function bind(obj, callback) {
+function bind(obj, callback, ...bindArguments) {
     if (typeof obj !== 'object') {
         throw new Error(`first argument to Lang.bind() must be an object, not ${
             typeof obj}`);
@@ -83,10 +83,7 @@ function bind(obj, callback) {
         return callback.bind(obj);
 
     let me = obj;
-    let bindArguments = Array.prototype.slice.call(arguments, 2);
-
-    return function() {
-        let args = Array.prototype.slice.call(arguments);
+    return function(...args) {
         args = args.concat(bindArguments);
         return callback.apply(me, args);
     };
diff --git a/modules/overrides/GObject.js b/modules/overrides/GObject.js
index c53ac513..bd1789ee 100644
--- a/modules/overrides/GObject.js
+++ b/modules/overrides/GObject.js
@@ -39,8 +39,9 @@ var _gtkCssName = Symbol('GTK widget CSS name');
 var _gtkInternalChildren = Symbol('GTK widget template internal children');
 var _gtkTemplate = Symbol('GTK widget template');
 
-function registerClass(klass) {
-    if (arguments.length === 2) {
+function registerClass(...args) {
+    let klass = args[0];
+    if (args.length === 2) {
         // The two-argument form is the convenient syntax without ESnext
         // decorators and class data properties. The first argument is an
         // object with meta info such as properties and signals. The second
@@ -55,8 +56,8 @@ function registerClass(klass) {
         //
         // When decorators and class data properties become part of the JS
         // standard, this function can be used directly as a decorator.
-        let metaInfo = arguments[0];
-        klass = arguments[1];
+        let metaInfo = args[0];
+        klass = args[1];
         if ('GTypeName' in metaInfo)
             klass[GTypeName] = metaInfo.GTypeName;
         if ('GTypeFlags' in metaInfo)
@@ -366,8 +367,8 @@ function _init() {
 
     // For compatibility with Lang.Class... we need a _construct
     // or the Lang.Class constructor will fail.
-    GObject.Object.prototype._construct = function() {
-        this._init.apply(this, arguments);
+    GObject.Object.prototype._construct = function(...args) {
+        this._init(...args);
         return this;
     };
 
@@ -408,8 +409,7 @@ function _init() {
                 let id = GObject.signal_lookup(name.slice(3).replace('_', '-'),
                     newClass.$gtype);
                 if (id !== 0) {
-                    GObject.signal_override_class_closure(id, newClass.$gtype, function() {
-                        let argArray = Array.from(arguments);
+                    GObject.signal_override_class_closure(id, newClass.$gtype, function(...argArray) {
                         let emitter = argArray.shift();
 
                         return func.apply(emitter, argArray);
@@ -455,9 +455,8 @@ function _init() {
             // SomeInterface.prototype.some_function.call(this, blah)
             if (typeof descr.value === 'function') {
                 let interfaceProto = klass.prototype;  // capture in closure
-                newInterface[key] = function () {
-                    return interfaceProto[key].call.apply(interfaceProto[key],
-                        arguments);
+                newInterface[key] = function (thisObj, ...args) {
+                    return interfaceProto[key].call(thisObj, ...args);
                 };
             }
 
diff --git a/modules/overrides/Gio.js b/modules/overrides/Gio.js
index 21d42285..dafe6de4 100644
--- a/modules/overrides/Gio.js
+++ b/modules/overrides/Gio.js
@@ -160,8 +160,8 @@ function _makeProxyMethod(method, sync) {
     for (i = 0; i < inArgs.length; i++)
         inSignature.push(inArgs[i].signature);
 
-    return function() {
-        return _proxyInvoker.call(this, name, sync, inSignature, arguments);
+    return function(...args) {
+        return _proxyInvoker.call(this, name, sync, inSignature, args);
     };
 }
 
@@ -285,9 +285,9 @@ function _newInterfaceInfo(value) {
 function _injectToMethod(klass, method, addition) {
     var previous = klass[method];
 
-    klass[method] = function() {
-        addition.apply(this, arguments);
-        return previous.apply(this, arguments);
+    klass[method] = function(...args) {
+        addition.apply(this, args);
+        return previous.apply(this, args);
     };
 }
 
@@ -304,8 +304,7 @@ function _injectToStaticMethod(klass, method, addition) {
 function _wrapFunction(klass, method, addition) {
     var previous = klass[method];
 
-    klass[method] = function() {
-        var args = Array.prototype.slice.call(arguments);
+    klass[method] = function(...args) {
         args.unshift(previous);
         return addition.apply(this, args);
     };
diff --git a/modules/tweener/tweener.js b/modules/tweener/tweener.js
index 5e97aaa6..70bed530 100644
--- a/modules/tweener/tweener.js
+++ b/modules/tweener/tweener.js
@@ -1,5 +1,5 @@
 /* -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil; -*- */
-/* eslint-disable block-scoped-var, eqeqeq, no-shadow */
+/* eslint-disable block-scoped-var, eqeqeq, no-shadow, prefer-rest-params */
 
 /* Copyright 2008  litl, LLC. */
 /**


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]