@bhbr/better-things 0.0.0-stage → 1.0.1
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.
- package/README.md +7 -2
- package/dist/BetterObject.d.ts +36 -0
- package/dist/BetterObject.d.ts.map +1 -0
- package/dist/BetterObject.js +295 -0
- package/dist/BetterObject.js.map +1 -0
- package/dist/ClassDeclaration.d.ts +18 -0
- package/dist/ClassDeclaration.d.ts.map +1 -0
- package/dist/ClassDeclaration.js +75 -0
- package/dist/ClassDeclaration.js.map +1 -0
- package/dist/Errors.d.ts +7 -0
- package/dist/Errors.d.ts.map +1 -0
- package/dist/Errors.js +13 -0
- package/dist/Errors.js.map +1 -0
- package/package.json +41 -4
package/README.md
CHANGED
|
@@ -1,3 +1,8 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Description
|
|
2
|
+
|
|
3
|
+
This package defines a generic class BetterObject that allows for safer subclassing. In particular:
|
|
4
|
+
|
|
5
|
+
- it provides a simple method `defaults` for setting default values of all properties at object creation,
|
|
6
|
+
|
|
7
|
+
- and a method `mutabilities` that defined permissions for changing the properties' values and defaults on or after object creation or when subclassing.
|
|
2
8
|
|
|
3
|
-
This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
export declare class BetterObject {
|
|
2
|
+
private static classDeclarations;
|
|
3
|
+
properties: Array<string>;
|
|
4
|
+
private indirectlyWritableProperties;
|
|
5
|
+
mutabilities(): object;
|
|
6
|
+
defaults(): object;
|
|
7
|
+
constructor(args?: object);
|
|
8
|
+
private registerOwnClassDeclaration;
|
|
9
|
+
private static initializeClassDeclarations;
|
|
10
|
+
private prototypes;
|
|
11
|
+
ancestry(): Array<string>;
|
|
12
|
+
isInstanceOf(cls: string): boolean;
|
|
13
|
+
private checkConstructorArgs;
|
|
14
|
+
private setProperties;
|
|
15
|
+
private accessorArgs;
|
|
16
|
+
private nonAccessorArgs;
|
|
17
|
+
private setProperty;
|
|
18
|
+
private setExistingProperty;
|
|
19
|
+
createProperty(prop: string, value: any): void;
|
|
20
|
+
removeProperty(prop: string): void;
|
|
21
|
+
isAccessor(prop: string): boolean;
|
|
22
|
+
private propertyDescriptors;
|
|
23
|
+
propertyDescriptor(prop: string): PropertyDescriptor | undefined;
|
|
24
|
+
private getAccessor;
|
|
25
|
+
mutability(prop: string): string;
|
|
26
|
+
isWritable(prop: string): boolean;
|
|
27
|
+
synchronizeUpdateArguments(args: object): object;
|
|
28
|
+
private checkUpdateArgs;
|
|
29
|
+
update(args?: object): void;
|
|
30
|
+
private removeUnchangedProperties;
|
|
31
|
+
fullDefaults(): object;
|
|
32
|
+
fullMutabilities(): object;
|
|
33
|
+
copyFrom(obj: BetterObject): void;
|
|
34
|
+
static clearClassDeclarations(): void;
|
|
35
|
+
}
|
|
36
|
+
//# sourceMappingURL=BetterObject.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"BetterObject.d.ts","sourceRoot":"","sources":["../src/BetterObject.ts"],"names":[],"mappings":"AAOA,qBAAa,YAAY;IA6BxB,OAAO,CAAC,MAAM,CAAC,iBAAiB,CAAQ;IACxC,UAAU,EAAE,KAAK,CAAC,MAAM,CAAC,CAAA;IACzB,OAAO,CAAC,4BAA4B,CAAQ;IAG5C,YAAY,IAAI,MAAM;IACtB,QAAQ,IAAI,MAAM;gBAKN,IAAI,GAAE,MAAW;IAqC7B,OAAO,CAAC,2BAA2B;IA6BnC,OAAO,CAAC,MAAM,CAAC,2BAA2B;IAc1C,OAAO,CAAC,UAAU;IAYlB,QAAQ,IAAI,KAAK,CAAC,MAAM,CAAC;IAIzB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO;IAIlC,OAAO,CAAC,oBAAoB;IAS5B,OAAO,CAAC,aAAa;IAiBrB,OAAO,CAAC,YAAY;IAUpB,OAAO,CAAC,eAAe;IAUvB,OAAO,CAAC,WAAW;IAQnB,OAAO,CAAC,mBAAmB;IAa3B,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG;IAwBvC,cAAc,CAAC,IAAI,EAAE,MAAM;IAK3B,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;IAUjC,OAAO,CAAC,mBAAmB;IAU3B,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,kBAAkB,GAAG,SAAS;IAKhE,OAAO,CAAC,WAAW;IAKnB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM;IAIhC,UAAU,CAAC,IAAI,EAAE,MAAM;IAIvB,0BAA0B,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM;IAQhD,OAAO,CAAC,eAAe;IASvB,MAAM,CAAC,IAAI,GAAE,MAAW;IAUxB,OAAO,CAAC,yBAAyB;IAsBjC,YAAY,IAAI,MAAM;IAItB,gBAAgB,IAAI,MAAM;IAI1B,QAAQ,CAAC,GAAG,EAAE,YAAY;IAQ1B,MAAM,CAAC,sBAAsB;CAK7B"}
|
|
@@ -0,0 +1,295 @@
|
|
|
1
|
+
import { equal } from '@bhbr/egalite';
|
|
2
|
+
import { isInstanceOf, ancestry } from '@bhbr/upper-class';
|
|
3
|
+
import { remove } from '@bhbr/betray';
|
|
4
|
+
import { ClassDeclaration } from './ClassDeclaration.js';
|
|
5
|
+
import { AssignmentError } from './Errors.js';
|
|
6
|
+
export class BetterObject {
|
|
7
|
+
// These properties need to be treated separately so we can modify them without declaring a public writable property. They are hidden inside this private dictionary, and modified by calling the update method, which internally accesses this dictionary.
|
|
8
|
+
mutabilities() { return {}; }
|
|
9
|
+
defaults() { return {}; }
|
|
10
|
+
// Empty base implementations that ground the recursive buildup of the fullMutabilities and fullDefaults
|
|
11
|
+
constructor(args = {}) {
|
|
12
|
+
// Create the static classDeclarations object if it hasn't been done yet
|
|
13
|
+
if (BetterObject.classDeclarations === undefined) {
|
|
14
|
+
BetterObject.initializeClassDeclarations();
|
|
15
|
+
}
|
|
16
|
+
// If this is the first instance of a subclass, register the class declaration
|
|
17
|
+
if (BetterObject.classDeclarations[this.constructor.name] === undefined) {
|
|
18
|
+
// This requires all ancestor classes to be registered already, so loop over their prototypes
|
|
19
|
+
let protos = this.prototypes();
|
|
20
|
+
for (let obj of protos) {
|
|
21
|
+
if (BetterObject.classDeclarations[obj.constructor.name] !== undefined) {
|
|
22
|
+
continue;
|
|
23
|
+
}
|
|
24
|
+
obj.registerOwnClassDeclaration();
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
// Initialize the list of properties
|
|
28
|
+
Object.defineProperty(this, 'properties', {
|
|
29
|
+
value: [],
|
|
30
|
+
writable: false,
|
|
31
|
+
enumerable: true
|
|
32
|
+
});
|
|
33
|
+
Object.defineProperty(this, 'indirectlyWritableProperties', {
|
|
34
|
+
value: {},
|
|
35
|
+
writable: false,
|
|
36
|
+
enumerable: true
|
|
37
|
+
});
|
|
38
|
+
// Are the initialization values valid?
|
|
39
|
+
this.checkConstructorArgs(args);
|
|
40
|
+
// If yes, complement them with the default values and set them
|
|
41
|
+
let initialArgs = this.fullDefaults();
|
|
42
|
+
Object.assign(initialArgs, args);
|
|
43
|
+
initialArgs = this.synchronizeUpdateArguments(initialArgs);
|
|
44
|
+
this.setProperties(initialArgs);
|
|
45
|
+
}
|
|
46
|
+
registerOwnClassDeclaration() {
|
|
47
|
+
let parentClass = Object.getPrototypeOf(this);
|
|
48
|
+
// Get the mutabilities
|
|
49
|
+
var mutabilities = this.mutabilities();
|
|
50
|
+
// If the class does not subclass the mutabilities() method, this would just call super method. In that case set the mutabilities to an empty object to express that nothing has changed in the subclass.
|
|
51
|
+
let parentMutabilities = parentClass.mutabilities();
|
|
52
|
+
if (equal(parentMutabilities, mutabilities)) {
|
|
53
|
+
mutabilities = {};
|
|
54
|
+
}
|
|
55
|
+
// Get the defaults function/method
|
|
56
|
+
// In order to decide whether this one has been overridden, evaluate both the method and the super method and compare the generated defaults objects. If they are the same, retain a function that creates an empty object.
|
|
57
|
+
let defaultsObject = this.defaults();
|
|
58
|
+
let parentDefaultsObject = parentClass.defaults();
|
|
59
|
+
let flag = equal(parentDefaultsObject, defaultsObject);
|
|
60
|
+
let defaultsFunction = flag ? function () { return {}; } : this.defaults;
|
|
61
|
+
// Create the class declaration from the class name, parent class declaration, mutabilities object and defaults function
|
|
62
|
+
let classDeclarationName = this.constructor.name;
|
|
63
|
+
let parentClassName = parentClass.constructor.name;
|
|
64
|
+
let parentClassDeclaration = BetterObject.classDeclarations[parentClassName];
|
|
65
|
+
BetterObject.classDeclarations[classDeclarationName] = new ClassDeclaration({
|
|
66
|
+
name: classDeclarationName,
|
|
67
|
+
parent: parentClassDeclaration,
|
|
68
|
+
mutabilities: mutabilities,
|
|
69
|
+
defaults: defaultsFunction
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
static initializeClassDeclarations() {
|
|
73
|
+
BetterObject.classDeclarations = {
|
|
74
|
+
// The first entry is for the base class
|
|
75
|
+
BetterObject: new ClassDeclaration({
|
|
76
|
+
name: 'BetterObject',
|
|
77
|
+
parent: null,
|
|
78
|
+
mutabilities: {},
|
|
79
|
+
defaults: function () { return {}; }
|
|
80
|
+
})
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
// TODO: map the following three methods to the functions imported from upper-class
|
|
84
|
+
prototypes() {
|
|
85
|
+
// A list of the class's prototype object, from BetterObject to the class itself
|
|
86
|
+
let ret = [];
|
|
87
|
+
var obj = Object.getPrototypeOf(this);
|
|
88
|
+
while (obj != null) {
|
|
89
|
+
ret.push(obj);
|
|
90
|
+
obj = Object.getPrototypeOf(obj);
|
|
91
|
+
}
|
|
92
|
+
ret.pop(); // superfluous entry of type Object
|
|
93
|
+
return ret.reverse();
|
|
94
|
+
}
|
|
95
|
+
ancestry() {
|
|
96
|
+
return ancestry(this);
|
|
97
|
+
}
|
|
98
|
+
isInstanceOf(cls) {
|
|
99
|
+
return isInstanceOf(this, cls);
|
|
100
|
+
}
|
|
101
|
+
checkConstructorArgs(args) {
|
|
102
|
+
// Only properties with mutability 'always', 'on_update' or 'on_init' can be set in the constructor call
|
|
103
|
+
for (let [prop, value] of Object.entries(args)) {
|
|
104
|
+
if (this.mutability(prop) === 'never' || this.mutability(prop) === 'in_subclass') {
|
|
105
|
+
throw new AssignmentError(`Property ${prop} in class ${this.constructor.name} cannot be assigned new value ${value} in constructor`);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
setProperties(args = {}) {
|
|
110
|
+
// Accessors (abstract properties that are just setters, e. g. a Circle's midpoint) are set only after all non-accessors have been set. So we split the args along that separation.
|
|
111
|
+
// Set the non-accessors (properties that have their own state)
|
|
112
|
+
let nonAccessorArgs = this.nonAccessorArgs(args);
|
|
113
|
+
for (let [prop, value] of Object.entries(nonAccessorArgs)) {
|
|
114
|
+
this.setProperty(prop, value);
|
|
115
|
+
}
|
|
116
|
+
// Set the accessors (abstract properties)
|
|
117
|
+
let accessorArgs = this.accessorArgs(args);
|
|
118
|
+
for (let [prop, value] of Object.entries(accessorArgs)) {
|
|
119
|
+
this.setProperty(prop, value);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
accessorArgs(args) {
|
|
123
|
+
let accessorArgs = {};
|
|
124
|
+
for (let [prop, value] of Object.entries(args)) {
|
|
125
|
+
if (this.isAccessor(prop)) {
|
|
126
|
+
accessorArgs[prop] = value;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
return accessorArgs;
|
|
130
|
+
}
|
|
131
|
+
nonAccessorArgs(args) {
|
|
132
|
+
let nonAccessorArgs = {};
|
|
133
|
+
for (let [prop, value] of Object.entries(args)) {
|
|
134
|
+
if (!this.isAccessor(prop)) {
|
|
135
|
+
nonAccessorArgs[prop] = value;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
return nonAccessorArgs;
|
|
139
|
+
}
|
|
140
|
+
setProperty(prop, value) {
|
|
141
|
+
if (!this.properties.includes(prop) && !this.isAccessor(prop)) {
|
|
142
|
+
this.createProperty(prop, value);
|
|
143
|
+
}
|
|
144
|
+
else {
|
|
145
|
+
this.setExistingProperty(prop, value);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
setExistingProperty(prop, value) {
|
|
149
|
+
if (this.isAccessor(prop)) {
|
|
150
|
+
let accessor = this.getAccessor(prop);
|
|
151
|
+
accessor.call(this, value);
|
|
152
|
+
return;
|
|
153
|
+
}
|
|
154
|
+
if (this.isWritable(prop)) {
|
|
155
|
+
this[prop] = value;
|
|
156
|
+
}
|
|
157
|
+
else {
|
|
158
|
+
this.indirectlyWritableProperties[prop] = value;
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
createProperty(prop, value) {
|
|
162
|
+
// i. e. a property that can only the changed via the update() method
|
|
163
|
+
let isSettable = (this.mutability(prop) == 'always');
|
|
164
|
+
if (isSettable) {
|
|
165
|
+
Object.defineProperty(this, prop, {
|
|
166
|
+
value: value,
|
|
167
|
+
writable: true,
|
|
168
|
+
enumerable: true
|
|
169
|
+
});
|
|
170
|
+
}
|
|
171
|
+
else {
|
|
172
|
+
this.indirectlyWritableProperties[prop] = value;
|
|
173
|
+
Object.defineProperty(this, prop, {
|
|
174
|
+
get() {
|
|
175
|
+
return this.indirectlyWritableProperties[prop];
|
|
176
|
+
},
|
|
177
|
+
set(newValue) {
|
|
178
|
+
throw new AssignmentError(`Use the update method to change the value of property ${prop} in class ${this.constructor.name}`);
|
|
179
|
+
},
|
|
180
|
+
enumerable: true
|
|
181
|
+
});
|
|
182
|
+
}
|
|
183
|
+
this.properties.push(prop);
|
|
184
|
+
}
|
|
185
|
+
removeProperty(prop) {
|
|
186
|
+
this[prop] = undefined;
|
|
187
|
+
remove(this.properties, prop);
|
|
188
|
+
}
|
|
189
|
+
isAccessor(prop) {
|
|
190
|
+
if (Object.keys(this.indirectlyWritableProperties).includes(prop)) {
|
|
191
|
+
return false;
|
|
192
|
+
}
|
|
193
|
+
let pd = this.propertyDescriptor(prop);
|
|
194
|
+
if (pd === undefined) {
|
|
195
|
+
return false;
|
|
196
|
+
}
|
|
197
|
+
if (!pd.enumerable) {
|
|
198
|
+
return true;
|
|
199
|
+
}
|
|
200
|
+
let s = pd['set'];
|
|
201
|
+
let flag = (s !== undefined);
|
|
202
|
+
return flag;
|
|
203
|
+
}
|
|
204
|
+
propertyDescriptors() {
|
|
205
|
+
let pds = {};
|
|
206
|
+
var obj = this;
|
|
207
|
+
while (obj) {
|
|
208
|
+
pds = Object.assign(pds, Object.getOwnPropertyDescriptors(obj));
|
|
209
|
+
obj = Object.getPrototypeOf(obj);
|
|
210
|
+
}
|
|
211
|
+
return pds;
|
|
212
|
+
}
|
|
213
|
+
propertyDescriptor(prop) {
|
|
214
|
+
let pds = this.propertyDescriptors();
|
|
215
|
+
return pds[prop];
|
|
216
|
+
}
|
|
217
|
+
getAccessor(prop) {
|
|
218
|
+
let pd = this.propertyDescriptor(prop);
|
|
219
|
+
return (pd === undefined || pd.enumerable) ? undefined : pd.set;
|
|
220
|
+
}
|
|
221
|
+
mutability(prop) {
|
|
222
|
+
return BetterObject.classDeclarations[this.constructor.name].mutability(prop);
|
|
223
|
+
}
|
|
224
|
+
isWritable(prop) {
|
|
225
|
+
return (this.mutability(prop) === 'always');
|
|
226
|
+
}
|
|
227
|
+
synchronizeUpdateArguments(args) {
|
|
228
|
+
/*
|
|
229
|
+
Override this method to resolve possible conflicts in update arguments.
|
|
230
|
+
Example: Should Circle({ midpoint: ..., anchor: ... }) silently fit the radius or raise an error?
|
|
231
|
+
*/
|
|
232
|
+
return args;
|
|
233
|
+
}
|
|
234
|
+
checkUpdateArgs(args) {
|
|
235
|
+
// Check whether any properites are not updatable
|
|
236
|
+
for (let [prop, value] of Object.entries(args)) {
|
|
237
|
+
if (this.mutability(prop) !== 'always' && this.mutability(prop) !== 'on_update') {
|
|
238
|
+
throw new AssignmentError(`Property ${prop} in class ${this.constructor.name} is not updatable, cannot be assigned new value ${value} after initialization`);
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
update(args = {}) {
|
|
243
|
+
/*
|
|
244
|
+
Override this method in subclasses. It MUST at some point call super.update(args).
|
|
245
|
+
*/
|
|
246
|
+
this.checkUpdateArgs(args);
|
|
247
|
+
args = this.synchronizeUpdateArguments(args);
|
|
248
|
+
args = this.removeUnchangedProperties(args); // for performance
|
|
249
|
+
this.setProperties(args);
|
|
250
|
+
}
|
|
251
|
+
removeUnchangedProperties(args) {
|
|
252
|
+
for (let [prop, value] of Object.entries(args)) {
|
|
253
|
+
if (this[prop] === undefined) {
|
|
254
|
+
continue;
|
|
255
|
+
}
|
|
256
|
+
if (typeof value != 'object' || value === null) {
|
|
257
|
+
if (this[prop] === value) {
|
|
258
|
+
delete args[prop];
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
else if (value.constructor.name == 'Transform') {
|
|
262
|
+
if (this[prop].equals(value)) {
|
|
263
|
+
delete args[prop];
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
else if (equal(this[prop], value)) {
|
|
267
|
+
delete args[prop];
|
|
268
|
+
}
|
|
269
|
+
else { // any other kind of object
|
|
270
|
+
if (this[prop] == value) {
|
|
271
|
+
delete args[prop];
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
return args;
|
|
276
|
+
}
|
|
277
|
+
fullDefaults() {
|
|
278
|
+
return BetterObject.classDeclarations[this.constructor.name].fullDefaults();
|
|
279
|
+
}
|
|
280
|
+
fullMutabilities() {
|
|
281
|
+
return BetterObject.classDeclarations[this.constructor.name].fullMutabilities;
|
|
282
|
+
}
|
|
283
|
+
copyFrom(obj) {
|
|
284
|
+
let argsDict = {};
|
|
285
|
+
for (let prop of obj.properties) {
|
|
286
|
+
argsDict[prop] = obj[prop];
|
|
287
|
+
}
|
|
288
|
+
this.update(argsDict);
|
|
289
|
+
}
|
|
290
|
+
static clearClassDeclarations() {
|
|
291
|
+
// for testing
|
|
292
|
+
BetterObject.classDeclarations = undefined;
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
//# sourceMappingURL=BetterObject.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"BetterObject.js","sourceRoot":"","sources":["../src/BetterObject.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export declare class ClassDeclaration {
|
|
2
|
+
name: string;
|
|
3
|
+
parent: ClassDeclaration | null;
|
|
4
|
+
mutabilities: object;
|
|
5
|
+
defaults: () => object;
|
|
6
|
+
fullMutabilities: object;
|
|
7
|
+
fullDefaults: object;
|
|
8
|
+
private static mutabilityOrder;
|
|
9
|
+
private static compatibleMutabilities;
|
|
10
|
+
constructor(args: object);
|
|
11
|
+
mutability(prop: string): string;
|
|
12
|
+
private initializeFullMutabilities;
|
|
13
|
+
private initializeFullDefaults;
|
|
14
|
+
checkMutabilities(): void;
|
|
15
|
+
checkDefaults(): void;
|
|
16
|
+
ancestry(): Array<string>;
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=ClassDeclaration.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ClassDeclaration.d.ts","sourceRoot":"","sources":["../src/ClassDeclaration.ts"],"names":[],"mappings":"AAGA,qBAAa,gBAAgB;IAI5B,IAAI,EAAE,MAAM,CAAA;IACZ,MAAM,EAAE,gBAAgB,GAAG,IAAI,CAAA;IAC/B,YAAY,EAAE,MAAM,CAAA;IACpB,QAAQ,EAAE,MAAM,MAAM,CAAA;IAEtB,gBAAgB,EAAE,MAAM,CAAA;IACxB,YAAY,EAAE,MAAM,CAAA;IAMpB,OAAO,CAAC,MAAM,CAAC,eAAe,CAE7B;IACD,OAAO,CAAC,MAAM,CAAC,sBAAsB;gBAKzB,IAAI,EAAE,MAAM;IAUxB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM;IAKhC,OAAO,CAAC,0BAA0B;IAUlC,OAAO,CAAC,sBAAsB;IAS9B,iBAAiB;IAUjB,aAAa;IAUb,QAAQ,IAAI,KAAK,CAAC,MAAM,CAAC;CAYzB"}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { MutabilityError, AssignmentError } from './Errors.js';
|
|
2
|
+
export class ClassDeclaration {
|
|
3
|
+
static compatibleMutabilities(oldMut, newMut) {
|
|
4
|
+
// Is the dictionary of newMutabilities a valid extension of the oldMutabilities? It is only valid if mutabilities of existing properties get restricted, they can never be expanded again.
|
|
5
|
+
return (ClassDeclaration.mutabilityOrder[oldMut] <= ClassDeclaration.mutabilityOrder[newMut]);
|
|
6
|
+
}
|
|
7
|
+
constructor(args) {
|
|
8
|
+
this.name = args['name'];
|
|
9
|
+
this.parent = args['parent'];
|
|
10
|
+
this.mutabilities = Object.assign({}, args['mutabilities']); // a fresh copy (so it can be altered without propagating back into the parent classes)
|
|
11
|
+
this.defaults = args['defaults']; // a *function* object that will create a fresh default object for each new object instance (including e. g. new DOM elements)
|
|
12
|
+
this.initializeFullMutabilities(); // collect and merge the mutabilities objects of all ancestor classes
|
|
13
|
+
this.initializeFullDefaults(); // collect and merge the defaults objects (return values of the defaults functions) of all parent classes
|
|
14
|
+
}
|
|
15
|
+
mutability(prop) {
|
|
16
|
+
// If the class doesn't specify a mutability, look into the ancestor classes. If they don't either, the default mutability is 'always'.
|
|
17
|
+
return this.mutabilities[prop] ?? this.fullMutabilities[prop] ?? 'always';
|
|
18
|
+
}
|
|
19
|
+
initializeFullMutabilities() {
|
|
20
|
+
// Collect and merge the mutabilities objects of all ancestor classes into a single object
|
|
21
|
+
this.fullMutabilities = {};
|
|
22
|
+
// Collect the entire mutabilities from all ancestor classes
|
|
23
|
+
if (this.parent) {
|
|
24
|
+
Object.assign(this.fullMutabilities, this.parent.fullMutabilities);
|
|
25
|
+
}
|
|
26
|
+
// Check whether the own mutabilities are compatible with them, then update
|
|
27
|
+
this.checkMutabilities();
|
|
28
|
+
Object.assign(this.fullMutabilities, this.mutabilities);
|
|
29
|
+
}
|
|
30
|
+
initializeFullDefaults() {
|
|
31
|
+
// Collect and merge the defaults of all ancestor classes, as a function
|
|
32
|
+
this.checkDefaults();
|
|
33
|
+
this.fullDefaults = function () {
|
|
34
|
+
let parentDefaults = this.parent ? this.parent.fullDefaults() : {};
|
|
35
|
+
return Object.assign(parentDefaults, this.defaults());
|
|
36
|
+
}.bind(this);
|
|
37
|
+
}
|
|
38
|
+
checkMutabilities() {
|
|
39
|
+
// Are the mutabilities specified in the class's mutabilities() method compatible with the ones inherited from the parent class?
|
|
40
|
+
for (let [prop, newMut] of Object.entries(this.mutabilities)) {
|
|
41
|
+
let oldMut = this.parent ? this.parent.mutability(prop) : 'always';
|
|
42
|
+
if (!ClassDeclaration.compatibleMutabilities(oldMut, newMut)) {
|
|
43
|
+
throw new MutabilityError(`Mutability of property ${prop} in class ${this.name} cannot be changed from ${oldMut} to ${newMut}`);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
checkDefaults() {
|
|
48
|
+
// Are the default values specified in the class's defaults() method compatible with the mutabilities inherited from the parent class?
|
|
49
|
+
for (let [prop, value] of Object.entries(this.defaults())) {
|
|
50
|
+
let oldMut = this.parent ? this.parent.mutability(prop) : 'always';
|
|
51
|
+
if (oldMut === 'never') {
|
|
52
|
+
throw new AssignmentError(`Property ${prop} in class ${this.name} is immutable, cannot be assigned new default value ${value}`);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
ancestry() {
|
|
57
|
+
// For debugging, a list of the names of the parent classes:
|
|
58
|
+
// ['BetterObject', ..., <this.parent.name>, <this.name>]
|
|
59
|
+
let ret = [];
|
|
60
|
+
var dec = this;
|
|
61
|
+
while (dec != null) {
|
|
62
|
+
ret.push(dec.name);
|
|
63
|
+
dec = dec.parent;
|
|
64
|
+
}
|
|
65
|
+
return ret.reverse();
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
/*
|
|
69
|
+
Comparing mutabilities: from laxest ('always') to strictest ('never'). A subclass can change a property's mutability only to a stricter level.
|
|
70
|
+
See BetterObject for a description of the mutability levels.
|
|
71
|
+
*/
|
|
72
|
+
ClassDeclaration.mutabilityOrder = {
|
|
73
|
+
'always': 0, 'on_update': 1, 'on_init': 2, 'in_subclass': 3, 'never': 4
|
|
74
|
+
};
|
|
75
|
+
//# sourceMappingURL=ClassDeclaration.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ClassDeclaration.js","sourceRoot":"","sources":["../src/ClassDeclaration.ts"],"names":[],"mappings":"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"}
|
package/dist/Errors.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Errors.d.ts","sourceRoot":"","sources":["../src/Errors.ts"],"names":[],"mappings":"AACA,qBAAa,eAAgB,SAAQ,KAAK;IACzC,IAAI,SAAoB;CACxB;AAED,qBAAa,eAAgB,SAAQ,KAAK;IACzC,IAAI,SAAoB;CACxB"}
|
package/dist/Errors.js
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export class MutabilityError extends Error {
|
|
2
|
+
constructor() {
|
|
3
|
+
super(...arguments);
|
|
4
|
+
this.name = 'MutabilityError';
|
|
5
|
+
}
|
|
6
|
+
}
|
|
7
|
+
export class AssignmentError extends Error {
|
|
8
|
+
constructor() {
|
|
9
|
+
super(...arguments);
|
|
10
|
+
this.name = 'AssignmentError';
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=Errors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Errors.js","sourceRoot":"","sources":["../src/Errors.ts"],"names":[],"mappings":"AACA,MAAM,OAAO,eAAgB,SAAQ,KAAK;IAA1C;;QACC,SAAI,GAAG,iBAAiB,CAAA;IACzB,CAAC;CAAA;AAED,MAAM,OAAO,eAAgB,SAAQ,KAAK;IAA1C;;QACC,SAAI,GAAG,iBAAiB,CAAA;IACzB,CAAC;CAAA"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,43 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bhbr/better-things",
|
|
3
|
-
"version": "
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
|
|
3
|
+
"version": "1.0.1",
|
|
4
|
+
"description": "A generic class BetterObject for safer subclassing",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/better-things.js",
|
|
7
|
+
"types": "./dist/better-things.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./dist/better-things.d.ts",
|
|
11
|
+
"import": "./dist/better-things.js"
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
"files": [
|
|
15
|
+
"dist/*.js",
|
|
16
|
+
"dist/*.d.ts",
|
|
17
|
+
"dist/*.js.map",
|
|
18
|
+
"dist/*.d.ts.map"
|
|
19
|
+
],
|
|
20
|
+
"scripts": {
|
|
21
|
+
"build": "cd build && ./build.sh",
|
|
22
|
+
"test": "node dist/_tests/better-things_tests.js",
|
|
23
|
+
"prepack": "npm run build"
|
|
24
|
+
},
|
|
25
|
+
"repository": {
|
|
26
|
+
"type": "git",
|
|
27
|
+
"url": "https://github.com/bhbr/better-things"
|
|
28
|
+
},
|
|
29
|
+
"bugs": {
|
|
30
|
+
"url": "https://github.com/bhbr/better-things/issues"
|
|
31
|
+
},
|
|
32
|
+
"homepage": "https://github.com/bhbr/better-things#readme",
|
|
33
|
+
"keywords": [],
|
|
34
|
+
"author": "Ben Hambrecht",
|
|
35
|
+
"license": "ISC",
|
|
36
|
+
"devDependencies": {
|
|
37
|
+
"@bhbr/tsts": "^1.1.3"
|
|
38
|
+
},
|
|
39
|
+
"dependencies": {
|
|
40
|
+
"@bhbr/betray": "^1.0.0",
|
|
41
|
+
"@bhbr/egalite": "^1.1.4"
|
|
42
|
+
}
|
|
43
|
+
}
|