cfprotected 1.1.2 → 1.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/index.mjs +49 -32
  2. package/package.json +1 -1
  3. package/test/test.mjs +17 -3
package/index.mjs CHANGED
@@ -8,6 +8,28 @@ function getAllOwnKeys(o) {
8
8
  .concat(Object.getOwnPropertySymbols(o));
9
9
  }
10
10
 
11
+ function useDescriptor(desc, fn) {
12
+ if ("value" in desc) {
13
+ if (typeof(desc.value) == "function") {
14
+ fn("value");
15
+ }
16
+ }
17
+ else {
18
+ if (typeof(desc.get) == "function") {
19
+ fn("get");
20
+ }
21
+ if (typeof(desc.set) == "function") {
22
+ fn("set");
23
+ }
24
+ }
25
+ }
26
+
27
+ function bindDescriptor(desc, context) {
28
+ useDescriptor(desc, (key) => {
29
+ desc[key] = desc[key].bind(context);
30
+ });
31
+ }
32
+
11
33
  /**
12
34
  * Used to both store inherited property information as well as retrieve it.
13
35
  * @param {Object} inst The instance object that will own the shared members.
@@ -17,8 +39,6 @@ function getAllOwnKeys(o) {
17
39
  * @returns {Object} The fully constructed inheritance object.
18
40
  */
19
41
  function share(inst, klass, members) {
20
- let retval = {};
21
-
22
42
  if ((typeof(inst) == "function")
23
43
  && klass && (typeof(klass) == "object")
24
44
  && (members === void 0)) {
@@ -63,58 +83,55 @@ function share(inst, klass, members) {
63
83
 
64
84
  //Get the protected data object.
65
85
  let ancestorKey = (inst === klass) ? ancestor : inst;
66
- let memo = ancestorMemo.get(ancestorKey) || {data: {}, $uper: {}, inheritance: null};
67
- let protData = memo.data;
86
+ let memo = ancestorMemo.get(ancestorKey) || {
87
+ data: {},
88
+ $uper: {},
89
+ };
90
+ let retval = {};
68
91
 
69
92
  //Get the details of the protected properties.
70
93
  let mDesc = Object.getOwnPropertyDescriptors(members);
71
94
  let mKeys = getAllOwnKeys(members);
72
95
 
73
96
  //Change the prototype of protoData using the new members.
74
- let prototype = Object.getPrototypeOf(protData);
97
+ let prototype = Object.getPrototypeOf(memo.data);
75
98
  let proto = Object.create(prototype,
76
99
  Object.fromEntries(mKeys
77
- .filter(k => !mDesc[k].value?.hasOwnProperty(ACCESSOR))
78
- .map(k => [k, mDesc[k]])));
79
- Object.setPrototypeOf(protData, proto);
80
-
81
- //Build the accessors for this class.
82
- mKeys.forEach(m => {
83
- let desc = (mDesc[m].value?.hasOwnProperty(ACCESSOR))
84
- ? {
85
- enumerable: true,
86
- get: mDesc[m].value.get,
87
- set: mDesc[m].value.set
88
- }
89
- : mDesc[m];
90
-
91
- Object.defineProperty(retval, m, desc);
92
- });
93
-
94
- //Define the "super" accessors
95
- Object.defineProperty(retval, "$uper", { value: {} });
100
+ .map(k => {
101
+ if (mDesc[k].value?.hasOwnProperty(ACCESSOR)) {
102
+ Object.assign(mDesc[k], mDesc[k].value);
103
+ mDesc[k].enumerable = true;
104
+ delete mDesc[k][ACCESSOR];
105
+ delete mDesc[k].value;
106
+ delete mDesc[k].writable;
107
+ }
108
+ bindDescriptor(mDesc[k], inst);
109
+ return [k, mDesc[k]];
110
+ })));
111
+ Object.setPrototypeOf(retval, proto);
96
112
 
113
+ //Define the "$uper" accessors
114
+ let $uper = {};
115
+ Object.defineProperty(retval, "$uper", { value: $uper });
116
+
117
+ //Build up the "$uper" object
97
118
  for (let key of mKeys) {
98
119
  if (key in prototype) {
99
120
  let obj = prototype;
100
121
  while (!obj.hasOwnProperty(key)) {
101
122
  obj = Object.getPrototypeOf(obj);
102
123
  }
103
- Object.defineProperty(retval.$uper, key, Object.getOwnPropertyDescriptor(obj, key));
124
+ Object.defineProperty($uper, key, Object.getOwnPropertyDescriptor(obj, key));
104
125
  }
105
126
  }
106
127
 
107
128
  //Attach the super inheritance
108
- Object.setPrototypeOf(retval.$uper, memo.$uper);
109
-
110
- //Inherit the inheritance
111
- Object.setPrototypeOf(retval, memo.inheritance);
129
+ Object.setPrototypeOf($uper, memo.$uper);
112
130
 
113
131
  //Save the inheritance & protected data
114
132
  memos.get(klass).set(inst, {
115
- data: protData,
116
- inheritance: retval,
117
- $uper: retval.$uper
133
+ data: retval,
134
+ $uper: $uper
118
135
  });
119
136
 
120
137
  return retval;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cfprotected",
3
- "version": "1.1.2",
3
+ "version": "1.1.3",
4
4
  "description": "An implementation of protected fields on top of class fields.",
5
5
  "main": "index.js",
6
6
  "scripts": {
package/test/test.mjs CHANGED
@@ -2,6 +2,10 @@ import { TestWatcher } from "@jest/core";
2
2
  import { share, saveSelf, accessor, abstract, final } from "../index"; //require("cfprotected");
3
3
 
4
4
  class Base {
5
+ static #greeting = "Hello!";
6
+ static #sprot = share(this, {
7
+ getGreeting() { return this.#greeting; }
8
+ });
5
9
  #prot = share(this, Base, {
6
10
  num: 42,
7
11
  name: "John Jacob Jingleheimerschmidt",
@@ -12,7 +16,6 @@ class Base {
12
16
  get: () => this.propTestVal
13
17
  }),
14
18
  superTest: () => {
15
- console.log(`Called Base::superTest() ...`);
16
19
  return 1;
17
20
  }
18
21
  });
@@ -76,12 +79,16 @@ class Derived extends Base {
76
79
  class NonParticipant extends Base {}
77
80
 
78
81
  class GrandChild extends NonParticipant {
82
+ static #sprot = share(this, {
83
+ getGreeting() {
84
+ return `${this.#sprot.$uper.getGreeting()} My name is`;
85
+ }
86
+ });
79
87
  #prot = share(this, GrandChild, {
80
88
  otherMethod: () => {
81
89
  this.#prot.name = this.testName;
82
90
  },
83
91
  superTest: () => {
84
- console.log(`Called GrandChild::superTest() ...`);
85
92
  return 1 + this.pvt.#prot.$uper.superTest();
86
93
  }
87
94
  });
@@ -103,9 +110,13 @@ class GrandChild extends NonParticipant {
103
110
  }
104
111
 
105
112
  class SuperTest extends GrandChild {
113
+ static #sprot = share(this, {
114
+ getGreeting() {
115
+ return `${this.#sprot.$uper.getGreeting()} "${this.name}"!`
116
+ }
117
+ });
106
118
  #prot = share(this, SuperTest, {
107
119
  superTest: () => {
108
- console.log(`Called SuperTest::superTest() ...`);
109
120
  return 1 + this.pvt.#prot.$uper.superTest();
110
121
  }
111
122
  });
@@ -119,6 +130,9 @@ class SuperTest extends GrandChild {
119
130
  test(`Should be able to call super through the entire inheritance chain`, () => {
120
131
  expect(this.pvt.#prot.superTest()).toBe(3);
121
132
  });
133
+ test(`Should be able to call super through the entire static inheritance chain`, () => {
134
+ expect(SuperTest.#sprot.getGreeting()).toBe(`Hello! My name is "SuperTest"!`);
135
+ });
122
136
  }
123
137
  }
124
138