cfprotected 1.1.4 → 1.2.0

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/README.md +11 -1
  2. package/index.mjs +28 -14
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -104,12 +104,22 @@ class Example {
104
104
  As a bonus, when used on the constructor, it creates an additional property named "cla\$\$" on the prototype. This "cla\$\$" property gives instances a means to reference the class constructor even when the class itself is anonymous. This is a fill-in feature for one of the TC39 proposals offering syntax for the same.
105
105
 
106
106
  ## **abstract(klass)**
107
- This method is a class wrapper that prevents instances of the class from being constructed directly. To construct an instance of the class you must extend it. This should be nearly identical to the same functionality that exists in some compiled languages.
107
+ This method has 2 different uses. The first is as a class wrapper that prevents instances of the class from being constructed directly. To construct an instance of the class, you must extend it. This should be nearly identical to the same functionality that exists in some compiled languages.
108
108
  ```js
109
109
  const Example = abstract(class {
110
110
  ...
111
111
  });
112
112
  ```
113
+ The second use is to mark the function as not having a valid implementation. Such functions must be overridden by derived classes.
114
+ ```js
115
+ class Example {
116
+ ...
117
+ #prot = share(this, Example, {
118
+ method = abstract("Example::method")
119
+ });
120
+ ...
121
+ };
122
+ ```
113
123
 
114
124
  ## **final(klass)**
115
125
  This method is a class wrapper that prevents instances of the class from being created using descendant classes. It also attempts to prevent creation of descendant classes.
package/index.mjs CHANGED
@@ -147,7 +147,7 @@ function share(inst, klass, members) {
147
147
  return retval;
148
148
  }
149
149
 
150
- /**
150
+ /**
151
151
  * Binds the class instance to itself to allow code to selectively avoid Proxy
152
152
  * issues, especially ones involving private fields. Also binds the class
153
153
  * constructor to the instance for static referencing as "cla$$".
@@ -183,23 +183,37 @@ function accessor(desc) {
183
183
  /**
184
184
  * A class wrapper that blocks construction of an instance if the class being
185
185
  * instantiated is not a descendant of the current class.
186
- * @param {Function} klass The constructor of the current class.
186
+ * @param {function|string} klass If a function, the constructor of the current
187
+ * class. If a string, the name of the function being abstracted.
188
+ * @returns {function} Either an extended class that denies direct construction
189
+ * or a function that immediately throws.
187
190
  */
188
191
  function abstract(klass) {
189
- let name = klass.name?klass.name : "";
190
- let retval = class extends klass {
191
- constructor (...args) {
192
- if (new.target === retval) {
193
- throw new TypeError(`Class constructor ${name} is abstract and cannot be directly invoked with 'new'`);
192
+ let retval;
193
+ if (typeof(klass) == "function") {
194
+ let name = klass.name?klass.name : "";
195
+ retval = class extends klass {
196
+ constructor (...args) {
197
+ if (new.target === retval) {
198
+ throw new TypeError(`Class constructor ${name} is abstract and cannot be directly invoked with 'new'`);
199
+ }
200
+ super(...args);
194
201
  }
195
- super(...args);
196
- }
197
- };
202
+ };
198
203
 
199
- if (memos.has(klass)) {
200
- let memo = memos.get(klass);
201
- memos.set(retval, memo);
202
- memo.set(retval, memo.get(klass));
204
+ if (memos.has(klass)) {
205
+ let memo = memos.get(klass);
206
+ memos.set(retval, memo);
207
+ memo.set(retval, memo.get(klass));
208
+ }
209
+ }
210
+ else if (typeof(klass) == "string") {
211
+ retval = function() {
212
+ throw new TypeError(`${klass}() must be overridden`);
213
+ }
214
+ }
215
+ else {
216
+ throw new TypeError(`abstract parameter must be a function or string`)
203
217
  }
204
218
 
205
219
  return retval;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cfprotected",
3
- "version": "1.1.4",
3
+ "version": "1.2.0",
4
4
  "description": "An implementation of protected fields on top of class fields.",
5
5
  "main": "index.js",
6
6
  "scripts": {