[gjs] lang: Copy symbol properties into class prototype
- From: Philip Chimento <pchimento src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gjs] lang: Copy symbol properties into class prototype
- Date: Sun, 26 Feb 2017 21:54:12 +0000 (UTC)
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]