[gjs] lang: Copy symbol properties into class prototype



commit 74bf3bd3a2216338ff7ba7b7e754c96311317aa4
Author: Philip Chimento <philip chimento gmail com>
Date:   Sat Feb 25 12:49:41 2017 -0800

    lang: Copy symbol properties into class prototype
    
    Now that our JS engine supports symbols, we need to make sure that our
    class framework supports properties with symbol keys. Previously we
    would copy properties from the object passed to Lang.Class (the "params
    object") onto the class's prototype using Object.getOwnPropertyNames().
    Now we need to use Object.getOwnPropertySymbols() as well, so that
    properties and methods with symbol keys are copied.
    
    One common use case might be making an object iterable by giving it a
    Symbol.iterator method.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=778718

 installed-tests/js/testClass.js |   11 +++++++++++
 modules/lang.js                 |   38 +++++++++++++++++++++-----------------
 2 files changed, 32 insertions(+), 17 deletions(-)
---
diff --git a/installed-tests/js/testClass.js b/installed-tests/js/testClass.js
index 066134e..dfac15c 100644
--- a/installed-tests/js/testClass.js
+++ b/installed-tests/js/testClass.js
@@ -192,4 +192,15 @@ describe('Class framework', function () {
         expect(instance instanceof CustomConstruct).toBeFalsy();
         expect(instance).toEqual([1, 2]);
     });
+
+    it('allows symbol-named methods', function () {
+        const SymbolClass = new Lang.Class({
+            Name: 'SymbolClass',
+            *[Symbol.iterator]() {
+                yield* [1, 2, 3];
+            },
+        });
+        let instance = new SymbolClass();
+        expect([...instance]).toEqual([1, 2, 3]);
+    });
 });
diff --git a/modules/lang.js b/modules/lang.js
index 67a7c35..0df22dc 100644
--- a/modules/lang.js
+++ b/modules/lang.js
@@ -264,6 +264,21 @@ Class.prototype.implements = function (iface) {
     return false;
 };
 
+// key can be either a string or a symbol
+Class.prototype._copyPropertyDescriptor = function(params, propertyObj, key) {
+    let descriptor = Object.getOwnPropertyDescriptor(params, key);
+
+    if (typeof descriptor.value === 'function')
+        descriptor.value = this.wrapFunction(key, descriptor.value);
+
+    // we inherit writable and enumerable from the property
+    // descriptor of params (they're both true if created from an
+    // object literal)
+    descriptor.configurable = false;
+
+    propertyObj[key] = descriptor;
+};
+
 Class.prototype._init = function(params) {
     let name = params.Name;
 
@@ -277,28 +292,17 @@ Class.prototype._init = function(params) {
         .forEach((name) => {
             let descriptor = Object.getOwnPropertyDescriptor(iface.prototype,
                 name);
-            // writable and enumerable are inherited, see note below
+            // writable and enumerable are inherited, see note above
             descriptor.configurable = false;
             propertyObj[name] = descriptor;
         });
     });
 
-    Object.getOwnPropertyNames(params).forEach(function(name) {
-        if (['Name', 'Extends', 'Abstract', 'Implements'].indexOf(name) !== -1)
-            return;
-
-        let descriptor = Object.getOwnPropertyDescriptor(params, name);
-
-        if (typeof descriptor.value === 'function')
-            descriptor.value = this.wrapFunction(name, descriptor.value);
-
-        // we inherit writable and enumerable from the property
-        // descriptor of params (they're both true if created from an
-        // object literal)
-        descriptor.configurable = false;
-
-        propertyObj[name] = descriptor;
-    }.bind(this));
+    Object.getOwnPropertyNames(params)
+        .filter(name =>
+            ['Name', 'Extends', 'Abstract', 'Implements'].indexOf(name) === -1)
+        .concat(Object.getOwnPropertySymbols(params))
+        .forEach(this._copyPropertyDescriptor.bind(this, params, propertyObj));
 
     Object.defineProperties(this.prototype, propertyObj);
     Object.defineProperties(this.prototype, {


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