@colyseus/schema 3.0.0-alpha.30 → 3.0.0-alpha.31
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/build/cjs/index.js +383 -341
- package/build/cjs/index.js.map +1 -1
- package/build/esm/index.mjs +383 -341
- package/build/esm/index.mjs.map +1 -1
- package/build/umd/index.js +383 -341
- package/lib/Metadata.d.ts +14 -5
- package/lib/Metadata.js +49 -20
- package/lib/Metadata.js.map +1 -1
- package/lib/Reflection.js +4 -13
- package/lib/Reflection.js.map +1 -1
- package/lib/Schema.js +26 -39
- package/lib/Schema.js.map +1 -1
- package/lib/annotations.d.ts +1 -2
- package/lib/annotations.js +58 -52
- package/lib/annotations.js.map +1 -1
- package/lib/bench_encode.js +33 -11
- package/lib/bench_encode.js.map +1 -1
- package/lib/decoder/DecodeOperation.js +4 -8
- package/lib/decoder/DecodeOperation.js.map +1 -1
- package/lib/decoder/ReferenceTracker.js +3 -2
- package/lib/decoder/ReferenceTracker.js.map +1 -1
- package/lib/decoder/strategy/StateCallbacks.js +4 -3
- package/lib/decoder/strategy/StateCallbacks.js.map +1 -1
- package/lib/encoder/ChangeTree.d.ts +8 -7
- package/lib/encoder/ChangeTree.js +128 -115
- package/lib/encoder/ChangeTree.js.map +1 -1
- package/lib/encoder/EncodeOperation.d.ts +1 -4
- package/lib/encoder/EncodeOperation.js +46 -46
- package/lib/encoder/EncodeOperation.js.map +1 -1
- package/lib/encoder/Encoder.js +11 -3
- package/lib/encoder/Encoder.js.map +1 -1
- package/lib/encoder/StateView.js +3 -3
- package/lib/encoder/StateView.js.map +1 -1
- package/lib/encoding/assert.d.ts +2 -1
- package/lib/encoding/assert.js +2 -2
- package/lib/encoding/assert.js.map +1 -1
- package/lib/index.d.ts +1 -2
- package/lib/index.js +11 -10
- package/lib/index.js.map +1 -1
- package/lib/types/TypeContext.js +7 -14
- package/lib/types/TypeContext.js.map +1 -1
- package/lib/types/custom/ArraySchema.js +6 -0
- package/lib/types/custom/ArraySchema.js.map +1 -1
- package/lib/types/custom/CollectionSchema.js +1 -0
- package/lib/types/custom/CollectionSchema.js.map +1 -1
- package/lib/types/custom/MapSchema.js +5 -0
- package/lib/types/custom/MapSchema.js.map +1 -1
- package/lib/types/custom/SetSchema.js +1 -0
- package/lib/types/custom/SetSchema.js.map +1 -1
- package/lib/types/symbols.d.ts +1 -0
- package/lib/types/symbols.js +2 -1
- package/lib/types/symbols.js.map +1 -1
- package/package.json +1 -1
- package/src/Metadata.ts +60 -29
- package/src/Reflection.ts +5 -15
- package/src/Schema.ts +33 -45
- package/src/annotations.ts +75 -67
- package/src/bench_encode.ts +37 -13
- package/src/decoder/DecodeOperation.ts +4 -10
- package/src/decoder/ReferenceTracker.ts +3 -2
- package/src/decoder/strategy/StateCallbacks.ts +4 -3
- package/src/encoder/ChangeTree.ts +146 -135
- package/src/encoder/EncodeOperation.ts +64 -58
- package/src/encoder/Encoder.ts +16 -4
- package/src/encoder/StateView.ts +4 -4
- package/src/encoding/assert.ts +4 -3
- package/src/index.ts +1 -4
- package/src/types/TypeContext.ts +10 -15
- package/src/types/custom/ArraySchema.ts +8 -0
- package/src/types/custom/CollectionSchema.ts +1 -0
- package/src/types/custom/MapSchema.ts +6 -0
- package/src/types/custom/SetSchema.ts +1 -0
- package/src/types/symbols.ts +2 -0
package/build/cjs/index.js
CHANGED
|
@@ -36,6 +36,7 @@ const $decoder = Symbol("$decoder");
|
|
|
36
36
|
const $filter = Symbol("$filter");
|
|
37
37
|
const $getByIndex = Symbol("$getByIndex");
|
|
38
38
|
const $deleteByIndex = Symbol("$deleteByIndex");
|
|
39
|
+
const $descriptors = Symbol("$descriptors");
|
|
39
40
|
/**
|
|
40
41
|
* Used to hold ChangeTree instances whitin the structures
|
|
41
42
|
*/
|
|
@@ -71,34 +72,67 @@ function getType(identifier) {
|
|
|
71
72
|
}
|
|
72
73
|
|
|
73
74
|
const Metadata = {
|
|
74
|
-
addField(metadata, index,
|
|
75
|
+
addField(metadata, index, name, type, descriptor) {
|
|
75
76
|
if (index > 64) {
|
|
76
|
-
throw new Error(`Can't define field '${
|
|
77
|
+
throw new Error(`Can't define field '${name}'.\nSchema instances may only have up to 64 fields.`);
|
|
77
78
|
}
|
|
78
|
-
metadata[
|
|
79
|
+
metadata[index] = Object.assign(metadata[index] || {}, // avoid overwriting previous field metadata (@owned / @deprecated)
|
|
79
80
|
{
|
|
80
81
|
type: (Array.isArray(type))
|
|
81
82
|
? { array: type[0] }
|
|
82
83
|
: type,
|
|
83
84
|
index,
|
|
84
|
-
|
|
85
|
+
name,
|
|
85
86
|
});
|
|
87
|
+
// create "descriptors" map
|
|
88
|
+
metadata[$descriptors] ??= {};
|
|
89
|
+
if (descriptor) {
|
|
90
|
+
// for encoder
|
|
91
|
+
metadata[$descriptors][name] = descriptor;
|
|
92
|
+
metadata[$descriptors][`_${name}`] = {
|
|
93
|
+
value: undefined,
|
|
94
|
+
writable: true,
|
|
95
|
+
enumerable: false,
|
|
96
|
+
configurable: true,
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
else {
|
|
100
|
+
// for decoder
|
|
101
|
+
metadata[$descriptors][name] = {
|
|
102
|
+
value: undefined,
|
|
103
|
+
writable: true,
|
|
104
|
+
enumerable: true,
|
|
105
|
+
configurable: true,
|
|
106
|
+
};
|
|
107
|
+
}
|
|
86
108
|
// map -1 as last field index
|
|
87
109
|
Object.defineProperty(metadata, -1, {
|
|
88
110
|
value: index,
|
|
89
111
|
enumerable: false,
|
|
90
112
|
configurable: true
|
|
91
113
|
});
|
|
92
|
-
// map
|
|
93
|
-
Object.defineProperty(metadata,
|
|
94
|
-
value:
|
|
114
|
+
// map field name => index (non enumerable)
|
|
115
|
+
Object.defineProperty(metadata, name, {
|
|
116
|
+
value: index,
|
|
95
117
|
enumerable: false,
|
|
96
118
|
configurable: true,
|
|
97
119
|
});
|
|
120
|
+
// if child Ref/complex type, add to -4
|
|
121
|
+
if (typeof (metadata[index].type) !== "string") {
|
|
122
|
+
if (metadata[-4] === undefined) {
|
|
123
|
+
Object.defineProperty(metadata, -4, {
|
|
124
|
+
value: [],
|
|
125
|
+
enumerable: false,
|
|
126
|
+
configurable: true,
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
metadata[-4].push(index);
|
|
130
|
+
}
|
|
98
131
|
},
|
|
99
132
|
setTag(metadata, fieldName, tag) {
|
|
133
|
+
const index = metadata[fieldName];
|
|
134
|
+
const field = metadata[index];
|
|
100
135
|
// add 'tag' to the field
|
|
101
|
-
const field = metadata[fieldName];
|
|
102
136
|
field.tag = tag;
|
|
103
137
|
if (!metadata[-2]) {
|
|
104
138
|
// -2: all field indexes with "view" tag
|
|
@@ -114,20 +148,14 @@ const Metadata = {
|
|
|
114
148
|
configurable: true
|
|
115
149
|
});
|
|
116
150
|
}
|
|
117
|
-
metadata[-2].push(
|
|
151
|
+
metadata[-2].push(index);
|
|
118
152
|
if (!metadata[-3][tag]) {
|
|
119
153
|
metadata[-3][tag] = [];
|
|
120
154
|
}
|
|
121
|
-
metadata[-3][tag].push(
|
|
155
|
+
metadata[-3][tag].push(index);
|
|
122
156
|
},
|
|
123
157
|
setFields(target, fields) {
|
|
124
158
|
const metadata = (target.prototype.constructor[Symbol.metadata] ??= {});
|
|
125
|
-
// target[$track] = function (changeTree, index: number, operation: OPERATION = OPERATION.ADD) {
|
|
126
|
-
// changeTree.change(index, operation, encodeSchemaOperation);
|
|
127
|
-
// };
|
|
128
|
-
// target[$encoder] = encodeSchemaOperation;
|
|
129
|
-
// target[$decoder] = decodeSchemaOperation;
|
|
130
|
-
// if (!target.prototype.toJSON) { target.prototype.toJSON = Schema.prototype.toJSON; }
|
|
131
159
|
let index = 0;
|
|
132
160
|
for (const field in fields) {
|
|
133
161
|
const type = fields[field];
|
|
@@ -135,7 +163,7 @@ const Metadata = {
|
|
|
135
163
|
const complexTypeKlass = (Array.isArray(type))
|
|
136
164
|
? getType("array")
|
|
137
165
|
: (typeof (Object.keys(type)[0]) === "string") && getType(Object.keys(type)[0]);
|
|
138
|
-
Metadata.addField(metadata, index, field, type, getPropertyDescriptor(`_${field}`, index, type, complexTypeKlass
|
|
166
|
+
Metadata.addField(metadata, index, field, type, getPropertyDescriptor(`_${field}`, index, type, complexTypeKlass));
|
|
139
167
|
index++;
|
|
140
168
|
}
|
|
141
169
|
},
|
|
@@ -164,8 +192,9 @@ const Metadata = {
|
|
|
164
192
|
// assign parent metadata to current
|
|
165
193
|
Object.assign(metadata, parentMetadata);
|
|
166
194
|
for (let i = 0; i <= parentMetadata[-1]; i++) {
|
|
167
|
-
|
|
168
|
-
|
|
195
|
+
const fieldName = parentMetadata[i].name;
|
|
196
|
+
Object.defineProperty(metadata, fieldName, {
|
|
197
|
+
value: parentMetadata[fieldName],
|
|
169
198
|
enumerable: false,
|
|
170
199
|
configurable: true,
|
|
171
200
|
});
|
|
@@ -189,7 +218,7 @@ const Metadata = {
|
|
|
189
218
|
const metadata = klass[Symbol.metadata];
|
|
190
219
|
const fields = {};
|
|
191
220
|
for (let i = 0; i <= metadata[-1]; i++) {
|
|
192
|
-
fields[metadata[i]] = metadata[
|
|
221
|
+
fields[metadata[i].name] = metadata[i].type;
|
|
193
222
|
}
|
|
194
223
|
return fields;
|
|
195
224
|
}
|
|
@@ -198,48 +227,59 @@ const Metadata = {
|
|
|
198
227
|
var _a$5;
|
|
199
228
|
class ChangeTree {
|
|
200
229
|
static { _a$5 = $isNew; }
|
|
201
|
-
;
|
|
202
230
|
constructor(ref) {
|
|
203
|
-
this.
|
|
231
|
+
this.isFiltered = false;
|
|
232
|
+
this.isPartiallyFiltered = false;
|
|
204
233
|
this.currentOperationIndex = 0;
|
|
205
|
-
this.allChanges = new Map();
|
|
206
|
-
this.allFilteredChanges = new Map();
|
|
207
234
|
this.changes = new Map();
|
|
208
|
-
this.
|
|
235
|
+
this.allChanges = new Map();
|
|
209
236
|
this[_a$5] = true;
|
|
210
237
|
this.ref = ref;
|
|
238
|
+
//
|
|
239
|
+
// Does this structure have "filters" declared?
|
|
240
|
+
//
|
|
241
|
+
if (ref.constructor[Symbol.metadata]?.[-2]) {
|
|
242
|
+
this.allFilteredChanges = new Map();
|
|
243
|
+
this.filteredChanges = new Map();
|
|
244
|
+
}
|
|
211
245
|
}
|
|
212
246
|
setRoot(root) {
|
|
213
247
|
this.root = root;
|
|
214
248
|
this.root.add(this);
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
249
|
+
const metadata = this.ref.constructor[Symbol.metadata];
|
|
250
|
+
if (this.root.types.hasFilters) {
|
|
251
|
+
//
|
|
252
|
+
// At Schema initialization, the "root" structure might not be available
|
|
253
|
+
// yet, as it only does once the "Encoder" has been set up.
|
|
254
|
+
//
|
|
255
|
+
// So the "parent" may be already set without a "root".
|
|
256
|
+
//
|
|
257
|
+
this.checkIsFiltered(metadata, this.parent, this.parentIndex);
|
|
258
|
+
if (this.isFiltered || this.isPartiallyFiltered) {
|
|
259
|
+
this.root.allFilteredChanges.set(this, this.allFilteredChanges);
|
|
260
|
+
this.root.filteredChanges.set(this, this.filteredChanges);
|
|
261
|
+
}
|
|
262
|
+
}
|
|
224
263
|
if (!this.isFiltered) {
|
|
225
264
|
this.root.changes.set(this, this.changes);
|
|
265
|
+
this.root.allChanges.set(this, this.allChanges);
|
|
226
266
|
}
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
267
|
+
this.ensureRefId();
|
|
268
|
+
if (metadata) {
|
|
269
|
+
metadata[-4]?.forEach((index) => {
|
|
270
|
+
const field = metadata[index];
|
|
271
|
+
const value = this.ref[field.name];
|
|
272
|
+
if (value) {
|
|
273
|
+
value[$changes].setRoot(root);
|
|
274
|
+
}
|
|
275
|
+
});
|
|
230
276
|
}
|
|
231
|
-
if (
|
|
232
|
-
|
|
277
|
+
else if (this.ref[$childType] && typeof (this.ref[$childType]) !== "string") {
|
|
278
|
+
// MapSchema / ArraySchema, etc.
|
|
279
|
+
this.ref.forEach((value, key) => {
|
|
280
|
+
value[$changes].setRoot(root);
|
|
281
|
+
});
|
|
233
282
|
}
|
|
234
|
-
this.forEachChild((changeTree, _) => {
|
|
235
|
-
changeTree.setRoot(root);
|
|
236
|
-
});
|
|
237
|
-
// this.allChanges.forEach((_, index) => {
|
|
238
|
-
// const childRef = this.ref[$getByIndex](index);
|
|
239
|
-
// if (childRef && childRef[$changes]) {
|
|
240
|
-
// childRef[$changes].setRoot(root);
|
|
241
|
-
// }
|
|
242
|
-
// });
|
|
243
283
|
}
|
|
244
284
|
setParent(parent, root, parentIndex) {
|
|
245
285
|
this.parent = parent;
|
|
@@ -249,48 +289,60 @@ class ChangeTree {
|
|
|
249
289
|
return;
|
|
250
290
|
}
|
|
251
291
|
root.add(this);
|
|
292
|
+
const metadata = this.ref.constructor[Symbol.metadata];
|
|
252
293
|
// skip if parent is already set
|
|
253
|
-
if (root
|
|
254
|
-
this.
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
294
|
+
if (root !== this.root) {
|
|
295
|
+
this.root = root;
|
|
296
|
+
if (root.types.hasFilters) {
|
|
297
|
+
this.checkIsFiltered(metadata, parent, parentIndex);
|
|
298
|
+
if (this.isFiltered || this.isPartiallyFiltered) {
|
|
299
|
+
this.root.filteredChanges.set(this, this.filteredChanges);
|
|
300
|
+
this.root.allFilteredChanges.set(this, this.filteredChanges);
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
if (!this.isFiltered) {
|
|
304
|
+
this.root.changes.set(this, this.changes);
|
|
305
|
+
this.root.allChanges.set(this, this.allChanges);
|
|
306
|
+
}
|
|
307
|
+
this.ensureRefId();
|
|
258
308
|
}
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
309
|
+
// assign same parent on child structures
|
|
310
|
+
if (metadata) {
|
|
311
|
+
metadata[-4]?.forEach((index) => {
|
|
312
|
+
const field = metadata[index];
|
|
313
|
+
const value = this.ref[field.name];
|
|
314
|
+
value?.[$changes].setParent(this.ref, root, index);
|
|
315
|
+
// console.log(this.ref.constructor.name, field.name, value);
|
|
316
|
+
// try { throw new Error(); } catch (e) {
|
|
317
|
+
// console.log(e.stack);
|
|
318
|
+
// }
|
|
319
|
+
});
|
|
264
320
|
}
|
|
265
|
-
if (this.
|
|
266
|
-
|
|
267
|
-
this.
|
|
321
|
+
else if (this.ref[$childType] && typeof (this.ref[$childType]) !== "string") {
|
|
322
|
+
// MapSchema / ArraySchema, etc.
|
|
323
|
+
this.ref.forEach((value, key) => {
|
|
324
|
+
value[$changes].setParent(this.ref, root, this.indexes[key] ?? key);
|
|
325
|
+
});
|
|
268
326
|
}
|
|
269
|
-
this.ensureRefId();
|
|
270
|
-
this.forEachChild((changeTree, atIndex) => {
|
|
271
|
-
changeTree.setParent(this.ref, root, atIndex);
|
|
272
|
-
});
|
|
273
327
|
}
|
|
274
328
|
forEachChild(callback) {
|
|
275
329
|
//
|
|
276
330
|
// assign same parent on child structures
|
|
277
331
|
//
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
const value = this.ref[field];
|
|
283
|
-
if (value
|
|
284
|
-
callback(value[$changes],
|
|
332
|
+
const metadata = this.ref.constructor[Symbol.metadata];
|
|
333
|
+
if (metadata) {
|
|
334
|
+
metadata[-4]?.forEach((index) => {
|
|
335
|
+
const field = metadata[index];
|
|
336
|
+
const value = this.ref[field.name];
|
|
337
|
+
if (value) {
|
|
338
|
+
callback(value[$changes], index);
|
|
285
339
|
}
|
|
286
|
-
}
|
|
340
|
+
});
|
|
287
341
|
}
|
|
288
|
-
else if (typeof (this.ref)
|
|
342
|
+
else if (this.ref[$childType] && typeof (this.ref[$childType]) !== "string") {
|
|
289
343
|
// MapSchema / ArraySchema, etc.
|
|
290
344
|
this.ref.forEach((value, key) => {
|
|
291
|
-
|
|
292
|
-
callback(value[$changes], this.ref[$changes].indexes[key] ?? key);
|
|
293
|
-
}
|
|
345
|
+
callback(value[$changes], this.indexes[key] ?? key);
|
|
294
346
|
});
|
|
295
347
|
}
|
|
296
348
|
}
|
|
@@ -299,8 +351,8 @@ class ChangeTree {
|
|
|
299
351
|
this.root?.changes.set(this, this.changes);
|
|
300
352
|
}
|
|
301
353
|
change(index, operation = exports.OPERATION.ADD) {
|
|
302
|
-
const metadata = this.ref
|
|
303
|
-
const isFiltered = this.isFiltered || (metadata
|
|
354
|
+
const metadata = this.ref.constructor[Symbol.metadata];
|
|
355
|
+
const isFiltered = this.isFiltered || (metadata?.[index]?.tag !== undefined);
|
|
304
356
|
const changeSet = (isFiltered)
|
|
305
357
|
? this.filteredChanges
|
|
306
358
|
: this.changes;
|
|
@@ -311,14 +363,14 @@ class ChangeTree {
|
|
|
311
363
|
: (previousOperation === exports.OPERATION.DELETE)
|
|
312
364
|
? exports.OPERATION.DELETE_AND_ADD
|
|
313
365
|
: operation;
|
|
366
|
+
//
|
|
367
|
+
// TODO: are DELETE operations being encoded as ADD here ??
|
|
368
|
+
//
|
|
314
369
|
changeSet.set(index, op);
|
|
315
370
|
}
|
|
316
|
-
//
|
|
317
|
-
// TODO: are DELETE operations being encoded as ADD here ??
|
|
318
|
-
//
|
|
319
371
|
if (isFiltered) {
|
|
320
|
-
this.root?.filteredChanges.set(this, this.filteredChanges);
|
|
321
372
|
this.allFilteredChanges.set(index, exports.OPERATION.ADD);
|
|
373
|
+
this.root?.filteredChanges.set(this, this.filteredChanges);
|
|
322
374
|
this.root?.allFilteredChanges.set(this, this.allFilteredChanges);
|
|
323
375
|
}
|
|
324
376
|
else {
|
|
@@ -365,9 +417,7 @@ class ChangeTree {
|
|
|
365
417
|
});
|
|
366
418
|
}
|
|
367
419
|
indexedOperation(index, operation, allChangesIndex = index) {
|
|
368
|
-
|
|
369
|
-
const isFiltered = this.isFiltered || (metadata && metadata[metadata[index]].tag !== undefined);
|
|
370
|
-
if (isFiltered) {
|
|
420
|
+
if (this.filteredChanges !== undefined) {
|
|
371
421
|
this.allFilteredChanges.set(allChangesIndex, exports.OPERATION.ADD);
|
|
372
422
|
this.filteredChanges.set(index, operation);
|
|
373
423
|
this.root?.filteredChanges.set(this, this.filteredChanges);
|
|
@@ -380,8 +430,8 @@ class ChangeTree {
|
|
|
380
430
|
}
|
|
381
431
|
getType(index) {
|
|
382
432
|
if (Metadata.isValidInstance(this.ref)) {
|
|
383
|
-
const metadata = this.ref
|
|
384
|
-
return metadata[
|
|
433
|
+
const metadata = this.ref.constructor[Symbol.metadata];
|
|
434
|
+
return metadata[index].type;
|
|
385
435
|
}
|
|
386
436
|
else {
|
|
387
437
|
//
|
|
@@ -395,7 +445,7 @@ class ChangeTree {
|
|
|
395
445
|
}
|
|
396
446
|
getChange(index) {
|
|
397
447
|
// TODO: optimize this. avoid checking against multiple instances
|
|
398
|
-
return this.changes.get(index) ?? this.filteredChanges
|
|
448
|
+
return this.changes.get(index) ?? this.filteredChanges?.get(index);
|
|
399
449
|
}
|
|
400
450
|
//
|
|
401
451
|
// used during `.encode()`
|
|
@@ -416,9 +466,7 @@ class ChangeTree {
|
|
|
416
466
|
}
|
|
417
467
|
return;
|
|
418
468
|
}
|
|
419
|
-
const
|
|
420
|
-
const isFiltered = this.isFiltered || (metadata && metadata[metadata[index]].tag !== undefined);
|
|
421
|
-
const changeSet = (isFiltered)
|
|
469
|
+
const changeSet = (this.filteredChanges)
|
|
422
470
|
? this.filteredChanges
|
|
423
471
|
: this.changes;
|
|
424
472
|
const previousValue = this.getValue(index);
|
|
@@ -441,7 +489,7 @@ class ChangeTree {
|
|
|
441
489
|
//
|
|
442
490
|
// FIXME: this is looking a bit ugly (and repeated from `.change()`)
|
|
443
491
|
//
|
|
444
|
-
if (
|
|
492
|
+
if (this.filteredChanges) {
|
|
445
493
|
this.root?.filteredChanges.set(this, this.filteredChanges);
|
|
446
494
|
this.allFilteredChanges.delete(allChangesIndex);
|
|
447
495
|
}
|
|
@@ -452,6 +500,7 @@ class ChangeTree {
|
|
|
452
500
|
}
|
|
453
501
|
endEncode() {
|
|
454
502
|
this.changes.clear();
|
|
503
|
+
// ArraySchema and MapSchema have a custom "encode end" method
|
|
455
504
|
this.ref[$onEncodeEnd]?.();
|
|
456
505
|
// Not a new instance anymore
|
|
457
506
|
delete this[$isNew];
|
|
@@ -464,12 +513,12 @@ class ChangeTree {
|
|
|
464
513
|
//
|
|
465
514
|
this.ref[$onEncodeEnd]?.();
|
|
466
515
|
this.changes.clear();
|
|
467
|
-
this.filteredChanges
|
|
516
|
+
this.filteredChanges?.clear();
|
|
468
517
|
// reset operation index
|
|
469
518
|
this.currentOperationIndex = 0;
|
|
470
519
|
if (discardAll) {
|
|
471
520
|
this.allChanges.clear();
|
|
472
|
-
this.allFilteredChanges
|
|
521
|
+
this.allFilteredChanges?.clear();
|
|
473
522
|
// remove children references
|
|
474
523
|
this.forEachChild((changeTree, _) => this.root?.remove(changeTree));
|
|
475
524
|
}
|
|
@@ -496,48 +545,41 @@ class ChangeTree {
|
|
|
496
545
|
get changed() {
|
|
497
546
|
return this.changes.size > 0;
|
|
498
547
|
}
|
|
499
|
-
checkIsFiltered(parent, parentIndex) {
|
|
548
|
+
checkIsFiltered(metadata, parent, parentIndex) {
|
|
500
549
|
// Detect if current structure has "filters" declared
|
|
501
|
-
this.isPartiallyFiltered =
|
|
502
|
-
if (
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
const changes = this.changes;
|
|
535
|
-
this.changes = this.filteredChanges;
|
|
536
|
-
this.filteredChanges = changes;
|
|
537
|
-
// swap "all changes" reference
|
|
538
|
-
const allFilteredChanges = this.allFilteredChanges;
|
|
539
|
-
this.allFilteredChanges = this.allChanges;
|
|
540
|
-
this.allChanges = allFilteredChanges;
|
|
550
|
+
this.isPartiallyFiltered = metadata?.[-2] !== undefined;
|
|
551
|
+
if (this.isPartiallyFiltered) {
|
|
552
|
+
this.filteredChanges = this.filteredChanges || new Map();
|
|
553
|
+
this.allFilteredChanges = this.allFilteredChanges || new Map();
|
|
554
|
+
}
|
|
555
|
+
if (parent) {
|
|
556
|
+
if (!Metadata.isValidInstance(parent)) {
|
|
557
|
+
const parentChangeTree = parent[$changes];
|
|
558
|
+
parent = parentChangeTree.parent;
|
|
559
|
+
parentIndex = parentChangeTree.parentIndex;
|
|
560
|
+
}
|
|
561
|
+
const parentMetadata = parent?.constructor?.[Symbol.metadata];
|
|
562
|
+
this.isFiltered = (parent && parentMetadata?.[-2]?.includes(parentIndex));
|
|
563
|
+
//
|
|
564
|
+
// TODO: refactor this!
|
|
565
|
+
//
|
|
566
|
+
// swapping `changes` and `filteredChanges` is required here
|
|
567
|
+
// because "isFiltered" may not be imedialely available on `change()`
|
|
568
|
+
//
|
|
569
|
+
if (this.isFiltered) {
|
|
570
|
+
this.filteredChanges = new Map();
|
|
571
|
+
this.allFilteredChanges = new Map();
|
|
572
|
+
if (this.changes.size > 0) {
|
|
573
|
+
// swap changes reference
|
|
574
|
+
const changes = this.changes;
|
|
575
|
+
this.changes = this.filteredChanges;
|
|
576
|
+
this.filteredChanges = changes;
|
|
577
|
+
// swap "all changes" reference
|
|
578
|
+
const allFilteredChanges = this.allFilteredChanges;
|
|
579
|
+
this.allFilteredChanges = this.allChanges;
|
|
580
|
+
this.allChanges = allFilteredChanges;
|
|
581
|
+
}
|
|
582
|
+
}
|
|
541
583
|
}
|
|
542
584
|
}
|
|
543
585
|
}
|
|
@@ -821,62 +863,21 @@ var encode = /*#__PURE__*/Object.freeze({
|
|
|
821
863
|
writeFloat64: writeFloat64
|
|
822
864
|
});
|
|
823
865
|
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
case "int32":
|
|
836
|
-
case "uint32":
|
|
837
|
-
case "int64":
|
|
838
|
-
case "uint64":
|
|
839
|
-
case "float32":
|
|
840
|
-
case "float64":
|
|
841
|
-
typeofTarget = "number";
|
|
842
|
-
if (isNaN(value)) {
|
|
843
|
-
console.log(`trying to encode "NaN" in ${klass.constructor.name}#${field}`);
|
|
844
|
-
}
|
|
845
|
-
break;
|
|
846
|
-
case "string":
|
|
847
|
-
typeofTarget = "string";
|
|
848
|
-
allowNull = true;
|
|
849
|
-
break;
|
|
850
|
-
case "boolean":
|
|
851
|
-
// boolean is always encoded as true/false based on truthiness
|
|
852
|
-
return;
|
|
853
|
-
}
|
|
854
|
-
if (typeof (value) !== typeofTarget && (!allowNull || (allowNull && value !== null))) {
|
|
855
|
-
let foundValue = `'${JSON.stringify(value)}'${(value && value.constructor && ` (${value.constructor.name})`) || ''}`;
|
|
856
|
-
throw new EncodeSchemaError(`a '${typeofTarget}' was expected, but ${foundValue} was provided in ${klass.constructor.name}#${field}`);
|
|
857
|
-
}
|
|
858
|
-
}
|
|
859
|
-
function assertInstanceType(value, type, klass, field) {
|
|
860
|
-
if (!(value instanceof type)) {
|
|
861
|
-
throw new EncodeSchemaError(`a '${type.name}' was expected, but '${value && value.constructor.name}' was provided in ${klass.constructor.name}#${field}`);
|
|
862
|
-
}
|
|
863
|
-
}
|
|
864
|
-
|
|
865
|
-
function encodePrimitiveType(type, bytes, value, klass, field, it) {
|
|
866
|
-
assertType(value, type, klass, field);
|
|
867
|
-
const encodeFunc = encode[type];
|
|
868
|
-
if (encodeFunc) {
|
|
869
|
-
encodeFunc(bytes, value, it);
|
|
870
|
-
// encodeFunc(bytes, value);
|
|
871
|
-
}
|
|
872
|
-
else {
|
|
873
|
-
throw new EncodeSchemaError(`a '${type}' was expected, but ${value} was provided in ${klass.constructor.name}#${field}`);
|
|
866
|
+
function encodeValue(encoder, bytes,
|
|
867
|
+
// ref: Ref,
|
|
868
|
+
type, value,
|
|
869
|
+
// field: string | number,
|
|
870
|
+
operation, it) {
|
|
871
|
+
if (typeof (type) === "string") {
|
|
872
|
+
//
|
|
873
|
+
// Primitive values
|
|
874
|
+
//
|
|
875
|
+
// assertType(value, type as string, ref as Schema, field);
|
|
876
|
+
encode[type]?.(bytes, value, it);
|
|
874
877
|
}
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
// TODO: move this to the `@type()` annotation
|
|
879
|
-
assertInstanceType(value, type, ref, field);
|
|
878
|
+
else if (type[Symbol.metadata] !== undefined) {
|
|
879
|
+
// // TODO: move this to the `@type()` annotation
|
|
880
|
+
// assertInstanceType(value, type as typeof Schema, ref as Schema, field);
|
|
880
881
|
//
|
|
881
882
|
// Encode refId for this instance.
|
|
882
883
|
// The actual instance is going to be encoded on next `changeTree` iteration.
|
|
@@ -887,21 +888,15 @@ function encodeValue(encoder, bytes, ref, type, value, field, operation, it) {
|
|
|
887
888
|
encoder.tryEncodeTypeId(bytes, type, value.constructor, it);
|
|
888
889
|
}
|
|
889
890
|
}
|
|
890
|
-
else if (typeof (type) === "string") {
|
|
891
|
-
//
|
|
892
|
-
// Primitive values
|
|
893
|
-
//
|
|
894
|
-
encodePrimitiveType(type, bytes, value, ref, field, it);
|
|
895
|
-
}
|
|
896
891
|
else {
|
|
897
|
-
//
|
|
898
|
-
// Custom type (MapSchema, ArraySchema, etc)
|
|
899
|
-
//
|
|
900
|
-
const definition = getType(Object.keys(type)[0]);
|
|
901
|
-
//
|
|
902
|
-
// ensure a ArraySchema has been provided
|
|
903
|
-
//
|
|
904
|
-
assertInstanceType(ref[field], definition.constructor, ref, field);
|
|
892
|
+
// //
|
|
893
|
+
// // Custom type (MapSchema, ArraySchema, etc)
|
|
894
|
+
// //
|
|
895
|
+
// const definition = getType(Object.keys(type)[0]);
|
|
896
|
+
// //
|
|
897
|
+
// // ensure a ArraySchema has been provided
|
|
898
|
+
// //
|
|
899
|
+
// assertInstanceType(ref[field], definition.constructor, ref as Schema, field);
|
|
905
900
|
//
|
|
906
901
|
// Encode refId for this instance.
|
|
907
902
|
// The actual instance is going to be encoded on next `changeTree` iteration.
|
|
@@ -914,26 +909,27 @@ function encodeValue(encoder, bytes, ref, type, value, field, operation, it) {
|
|
|
914
909
|
* @private
|
|
915
910
|
*/
|
|
916
911
|
const encodeSchemaOperation = function (encoder, bytes, changeTree, index, operation, it) {
|
|
917
|
-
const ref = changeTree.ref;
|
|
918
|
-
const metadata = ref['constructor'][Symbol.metadata];
|
|
919
|
-
const field = metadata[index];
|
|
920
|
-
const type = metadata[field].type;
|
|
921
|
-
const value = ref[field];
|
|
922
912
|
// "compress" field index + operation
|
|
923
913
|
bytes[it.offset++] = (index | operation) & 255;
|
|
924
914
|
// Do not encode value for DELETE operations
|
|
925
915
|
if (operation === exports.OPERATION.DELETE) {
|
|
926
916
|
return;
|
|
927
917
|
}
|
|
918
|
+
const ref = changeTree.ref;
|
|
919
|
+
const metadata = ref['constructor'][Symbol.metadata];
|
|
920
|
+
const field = metadata[index];
|
|
928
921
|
// TODO: inline this function call small performance gain
|
|
929
|
-
encodeValue(encoder, bytes,
|
|
922
|
+
encodeValue(encoder, bytes,
|
|
923
|
+
// ref,
|
|
924
|
+
metadata[index].type, ref[field.name],
|
|
925
|
+
// index,
|
|
926
|
+
operation, it);
|
|
930
927
|
};
|
|
931
928
|
/**
|
|
932
929
|
* Used for collections (MapSchema, CollectionSchema, SetSchema)
|
|
933
930
|
* @private
|
|
934
931
|
*/
|
|
935
|
-
const encodeKeyValueOperation = function (encoder, bytes, changeTree,
|
|
936
|
-
const ref = changeTree.ref;
|
|
932
|
+
const encodeKeyValueOperation = function (encoder, bytes, changeTree, index, operation, it) {
|
|
937
933
|
// encode operation
|
|
938
934
|
bytes[it.offset++] = operation & 255;
|
|
939
935
|
// custom operations
|
|
@@ -941,11 +937,12 @@ const encodeKeyValueOperation = function (encoder, bytes, changeTree, field, ope
|
|
|
941
937
|
return;
|
|
942
938
|
}
|
|
943
939
|
// encode index
|
|
944
|
-
number$1(bytes,
|
|
940
|
+
number$1(bytes, index, it);
|
|
945
941
|
// Do not encode value for DELETE operations
|
|
946
942
|
if (operation === exports.OPERATION.DELETE) {
|
|
947
943
|
return;
|
|
948
944
|
}
|
|
945
|
+
const ref = changeTree.ref;
|
|
949
946
|
//
|
|
950
947
|
// encode "alias" for dynamic fields (maps)
|
|
951
948
|
//
|
|
@@ -954,12 +951,12 @@ const encodeKeyValueOperation = function (encoder, bytes, changeTree, field, ope
|
|
|
954
951
|
//
|
|
955
952
|
// MapSchema dynamic key
|
|
956
953
|
//
|
|
957
|
-
const dynamicIndex = changeTree.ref['$indexes'].get(
|
|
954
|
+
const dynamicIndex = changeTree.ref['$indexes'].get(index);
|
|
958
955
|
string$1(bytes, dynamicIndex, it);
|
|
959
956
|
}
|
|
960
957
|
}
|
|
961
|
-
const type = changeTree.getType(
|
|
962
|
-
const value = changeTree.getValue(
|
|
958
|
+
const type = changeTree.getType(index);
|
|
959
|
+
const value = changeTree.getValue(index);
|
|
963
960
|
// try { throw new Error(); } catch (e) {
|
|
964
961
|
// // only print if not coming from Reflection.ts
|
|
965
962
|
// if (!e.stack.includes("src/Reflection.ts")) {
|
|
@@ -973,7 +970,11 @@ const encodeKeyValueOperation = function (encoder, bytes, changeTree, field, ope
|
|
|
973
970
|
// }
|
|
974
971
|
// }
|
|
975
972
|
// TODO: inline this function call small performance gain
|
|
976
|
-
encodeValue(encoder, bytes,
|
|
973
|
+
encodeValue(encoder, bytes,
|
|
974
|
+
// ref,
|
|
975
|
+
type, value,
|
|
976
|
+
// index,
|
|
977
|
+
operation, it);
|
|
977
978
|
};
|
|
978
979
|
/**
|
|
979
980
|
* Used for collections (MapSchema, ArraySchema, etc.)
|
|
@@ -1017,7 +1018,11 @@ const encodeArray = function (encoder, bytes, changeTree, field, operation, it,
|
|
|
1017
1018
|
// items: ref.toJSON(),
|
|
1018
1019
|
// });
|
|
1019
1020
|
// TODO: inline this function call small performance gain
|
|
1020
|
-
encodeValue(encoder, bytes,
|
|
1021
|
+
encodeValue(encoder, bytes,
|
|
1022
|
+
// ref,
|
|
1023
|
+
type, value,
|
|
1024
|
+
// field,
|
|
1025
|
+
operation, it);
|
|
1021
1026
|
};
|
|
1022
1027
|
|
|
1023
1028
|
/**
|
|
@@ -1374,7 +1379,7 @@ function decodeValue(decoder, operation, ref, index, type, bytes, it, allChanges
|
|
|
1374
1379
|
}
|
|
1375
1380
|
const decodeSchemaOperation = function (decoder, bytes, it, ref, allChanges) {
|
|
1376
1381
|
const first_byte = bytes[it.offset++];
|
|
1377
|
-
const metadata = ref
|
|
1382
|
+
const metadata = ref.constructor[Symbol.metadata];
|
|
1378
1383
|
// "compressed" index + operation
|
|
1379
1384
|
const operation = (first_byte >> 6) << 6;
|
|
1380
1385
|
const index = first_byte % (operation || 255);
|
|
@@ -1384,9 +1389,9 @@ const decodeSchemaOperation = function (decoder, bytes, it, ref, allChanges) {
|
|
|
1384
1389
|
console.warn("@colyseus/schema: field not defined at", { index, ref: ref.constructor.name, metadata });
|
|
1385
1390
|
return DEFINITION_MISMATCH;
|
|
1386
1391
|
}
|
|
1387
|
-
const { value, previousValue } = decodeValue(decoder, operation, ref, index,
|
|
1392
|
+
const { value, previousValue } = decodeValue(decoder, operation, ref, index, field.type, bytes, it, allChanges);
|
|
1388
1393
|
if (value !== null && value !== undefined) {
|
|
1389
|
-
ref[field] = value;
|
|
1394
|
+
ref[field.name] = value;
|
|
1390
1395
|
}
|
|
1391
1396
|
// add change
|
|
1392
1397
|
if (previousValue !== value) {
|
|
@@ -1394,7 +1399,7 @@ const decodeSchemaOperation = function (decoder, bytes, it, ref, allChanges) {
|
|
|
1394
1399
|
ref,
|
|
1395
1400
|
refId: decoder.currentRefId,
|
|
1396
1401
|
op: operation,
|
|
1397
|
-
field: field,
|
|
1402
|
+
field: field.name,
|
|
1398
1403
|
value,
|
|
1399
1404
|
previousValue,
|
|
1400
1405
|
});
|
|
@@ -1492,7 +1497,6 @@ const decodeArray = function (decoder, bytes, it, ref, allChanges) {
|
|
|
1492
1497
|
return;
|
|
1493
1498
|
}
|
|
1494
1499
|
else if (operation === exports.OPERATION.ADD_BY_REFID) {
|
|
1495
|
-
// operation = OPERATION.ADD;
|
|
1496
1500
|
const refId = number(bytes, it);
|
|
1497
1501
|
const itemByRefId = decoder.root.refs.get(refId);
|
|
1498
1502
|
// use existing index, or push new value
|
|
@@ -1526,6 +1530,47 @@ const decodeArray = function (decoder, bytes, it, ref, allChanges) {
|
|
|
1526
1530
|
}
|
|
1527
1531
|
};
|
|
1528
1532
|
|
|
1533
|
+
class EncodeSchemaError extends Error {
|
|
1534
|
+
}
|
|
1535
|
+
function assertType(value, type, klass, field) {
|
|
1536
|
+
let typeofTarget;
|
|
1537
|
+
let allowNull = false;
|
|
1538
|
+
switch (type) {
|
|
1539
|
+
case "number":
|
|
1540
|
+
case "int8":
|
|
1541
|
+
case "uint8":
|
|
1542
|
+
case "int16":
|
|
1543
|
+
case "uint16":
|
|
1544
|
+
case "int32":
|
|
1545
|
+
case "uint32":
|
|
1546
|
+
case "int64":
|
|
1547
|
+
case "uint64":
|
|
1548
|
+
case "float32":
|
|
1549
|
+
case "float64":
|
|
1550
|
+
typeofTarget = "number";
|
|
1551
|
+
if (isNaN(value)) {
|
|
1552
|
+
console.log(`trying to encode "NaN" in ${klass.constructor.name}#${field}`);
|
|
1553
|
+
}
|
|
1554
|
+
break;
|
|
1555
|
+
case "string":
|
|
1556
|
+
typeofTarget = "string";
|
|
1557
|
+
allowNull = true;
|
|
1558
|
+
break;
|
|
1559
|
+
case "boolean":
|
|
1560
|
+
// boolean is always encoded as true/false based on truthiness
|
|
1561
|
+
return;
|
|
1562
|
+
}
|
|
1563
|
+
if (typeof (value) !== typeofTarget && (!allowNull || (allowNull && value !== null))) {
|
|
1564
|
+
let foundValue = `'${JSON.stringify(value)}'${(value && value.constructor && ` (${value.constructor.name})`) || ''}`;
|
|
1565
|
+
throw new EncodeSchemaError(`a '${typeofTarget}' was expected, but ${foundValue} was provided in ${klass.constructor.name}#${field}`);
|
|
1566
|
+
}
|
|
1567
|
+
}
|
|
1568
|
+
function assertInstanceType(value, type, instance, field) {
|
|
1569
|
+
if (!(value instanceof type)) {
|
|
1570
|
+
throw new EncodeSchemaError(`a '${type.name}' was expected, but '${value && value.constructor.name}' was provided in ${instance.constructor.name}#${field}`);
|
|
1571
|
+
}
|
|
1572
|
+
}
|
|
1573
|
+
|
|
1529
1574
|
var _a$4, _b$4;
|
|
1530
1575
|
const DEFAULT_SORT = (a, b) => {
|
|
1531
1576
|
const A = a.toString();
|
|
@@ -1591,6 +1636,7 @@ class ArraySchema {
|
|
|
1591
1636
|
}
|
|
1592
1637
|
else {
|
|
1593
1638
|
if (setValue[$changes]) {
|
|
1639
|
+
assertInstanceType(setValue, obj[$childType], obj, key);
|
|
1594
1640
|
if (obj.items[key] !== undefined) {
|
|
1595
1641
|
if (setValue[$changes][$isNew]) {
|
|
1596
1642
|
this[$changes].indexedOperation(Number(key), exports.OPERATION.MOVE_AND_ADD);
|
|
@@ -1637,6 +1683,7 @@ class ArraySchema {
|
|
|
1637
1683
|
}
|
|
1638
1684
|
});
|
|
1639
1685
|
this[$changes] = new ChangeTree(proxy);
|
|
1686
|
+
this[$changes].indexes = {};
|
|
1640
1687
|
this.push.apply(this, items);
|
|
1641
1688
|
return proxy;
|
|
1642
1689
|
}
|
|
@@ -1661,6 +1708,9 @@ class ArraySchema {
|
|
|
1661
1708
|
if (value === undefined || value === null) {
|
|
1662
1709
|
return;
|
|
1663
1710
|
}
|
|
1711
|
+
else if (typeof (value) === "object" && this[$childType]) {
|
|
1712
|
+
assertInstanceType(value, this[$childType], this, i);
|
|
1713
|
+
}
|
|
1664
1714
|
const changeTree = this[$changes];
|
|
1665
1715
|
changeTree.indexedOperation(length, exports.OPERATION.ADD, this.items.length);
|
|
1666
1716
|
this.items.push(value);
|
|
@@ -2188,6 +2238,7 @@ class MapSchema {
|
|
|
2188
2238
|
this.$items = new Map();
|
|
2189
2239
|
this.$indexes = new Map();
|
|
2190
2240
|
this[$changes] = new ChangeTree(this);
|
|
2241
|
+
this[$changes].indexes = {};
|
|
2191
2242
|
if (initialValues) {
|
|
2192
2243
|
if (initialValues instanceof Map ||
|
|
2193
2244
|
initialValues instanceof MapSchema) {
|
|
@@ -2214,6 +2265,9 @@ class MapSchema {
|
|
|
2214
2265
|
if (value === undefined || value === null) {
|
|
2215
2266
|
throw new Error(`MapSchema#set('${key}', ${value}): trying to set ${value} value on '${key}'.`);
|
|
2216
2267
|
}
|
|
2268
|
+
else if (typeof (value) === "object" && this[$childType]) {
|
|
2269
|
+
assertInstanceType(value, this[$childType], this, key);
|
|
2270
|
+
}
|
|
2217
2271
|
// Force "key" as string
|
|
2218
2272
|
// See: https://github.com/colyseus/colyseus/issues/561#issuecomment-1646733468
|
|
2219
2273
|
key = key.toString();
|
|
@@ -2419,27 +2473,20 @@ class TypeContext {
|
|
|
2419
2473
|
if (parentFieldViewTag !== undefined) {
|
|
2420
2474
|
this.parentFiltered[`${this.schemas.get(klass)}-${parentIndex}`] = true;
|
|
2421
2475
|
}
|
|
2422
|
-
for (const
|
|
2423
|
-
|
|
2424
|
-
|
|
2425
|
-
|
|
2426
|
-
// if (
|
|
2427
|
-
// parentFieldViewTag !== undefined &&
|
|
2428
|
-
// metadata[field].tag === undefined
|
|
2429
|
-
// ) {
|
|
2430
|
-
// metadata[field].tag = parentFieldViewTag;
|
|
2431
|
-
// }
|
|
2432
|
-
const fieldType = metadata[field].type;
|
|
2433
|
-
const viewTag = metadata[field].tag;
|
|
2476
|
+
for (const fieldIndex in metadata) {
|
|
2477
|
+
const index = fieldIndex;
|
|
2478
|
+
const fieldType = metadata[index].type;
|
|
2479
|
+
const viewTag = metadata[index].tag;
|
|
2434
2480
|
if (typeof (fieldType) === "string") {
|
|
2435
2481
|
continue;
|
|
2436
2482
|
}
|
|
2437
2483
|
if (Array.isArray(fieldType)) {
|
|
2438
2484
|
const type = fieldType[0];
|
|
2485
|
+
// skip primitive types
|
|
2439
2486
|
if (type === "string") {
|
|
2440
2487
|
continue;
|
|
2441
2488
|
}
|
|
2442
|
-
this.discoverTypes(type,
|
|
2489
|
+
this.discoverTypes(type, index, viewTag);
|
|
2443
2490
|
}
|
|
2444
2491
|
else if (typeof (fieldType) === "function") {
|
|
2445
2492
|
this.discoverTypes(fieldType, viewTag);
|
|
@@ -2450,7 +2497,7 @@ class TypeContext {
|
|
|
2450
2497
|
if (typeof (type) === "string") {
|
|
2451
2498
|
continue;
|
|
2452
2499
|
}
|
|
2453
|
-
this.discoverTypes(type,
|
|
2500
|
+
this.discoverTypes(type, index, viewTag);
|
|
2454
2501
|
}
|
|
2455
2502
|
}
|
|
2456
2503
|
}
|
|
@@ -2606,17 +2653,18 @@ function view(tag = DEFAULT_VIEW_TAG) {
|
|
|
2606
2653
|
const parentMetadata = parentClass[Symbol.metadata];
|
|
2607
2654
|
// TODO: use Metadata.initialize()
|
|
2608
2655
|
const metadata = (constructor[Symbol.metadata] ??= Object.assign({}, constructor[Symbol.metadata], parentMetadata ?? Object.create(null)));
|
|
2609
|
-
|
|
2610
|
-
|
|
2611
|
-
|
|
2612
|
-
|
|
2613
|
-
|
|
2614
|
-
|
|
2615
|
-
|
|
2616
|
-
|
|
2617
|
-
|
|
2618
|
-
|
|
2619
|
-
}
|
|
2656
|
+
// const fieldIndex = metadata[fieldName];
|
|
2657
|
+
// if (!metadata[fieldIndex]) {
|
|
2658
|
+
// //
|
|
2659
|
+
// // detect index for this field, considering inheritance
|
|
2660
|
+
// //
|
|
2661
|
+
// metadata[fieldIndex] = {
|
|
2662
|
+
// type: undefined,
|
|
2663
|
+
// index: (metadata[-1] // current structure already has fields defined
|
|
2664
|
+
// ?? (parentMetadata && parentMetadata[-1]) // parent structure has fields defined
|
|
2665
|
+
// ?? -1) + 1 // no fields defined
|
|
2666
|
+
// }
|
|
2667
|
+
// }
|
|
2620
2668
|
Metadata.setTag(metadata, fieldName, tag);
|
|
2621
2669
|
};
|
|
2622
2670
|
}
|
|
@@ -2631,16 +2679,16 @@ function type(type, options) {
|
|
|
2631
2679
|
const parentClass = Object.getPrototypeOf(constructor);
|
|
2632
2680
|
const parentMetadata = parentClass && parentClass[Symbol.metadata];
|
|
2633
2681
|
const metadata = Metadata.initialize(constructor, parentMetadata);
|
|
2634
|
-
let fieldIndex;
|
|
2682
|
+
let fieldIndex = metadata[field];
|
|
2635
2683
|
/**
|
|
2636
2684
|
* skip if descriptor already exists for this field (`@deprecated()`)
|
|
2637
2685
|
*/
|
|
2638
|
-
if (metadata[
|
|
2639
|
-
if (metadata[
|
|
2686
|
+
if (metadata[fieldIndex]) {
|
|
2687
|
+
if (metadata[fieldIndex].deprecated) {
|
|
2640
2688
|
// do not create accessors for deprecated properties.
|
|
2641
2689
|
return;
|
|
2642
2690
|
}
|
|
2643
|
-
else if (metadata[
|
|
2691
|
+
else if (metadata[fieldIndex].type !== undefined) {
|
|
2644
2692
|
// trying to define same property multiple times across inheritance.
|
|
2645
2693
|
// https://github.com/colyseus/colyseus-unity3d/issues/131#issuecomment-814308572
|
|
2646
2694
|
try {
|
|
@@ -2651,9 +2699,6 @@ function type(type, options) {
|
|
|
2651
2699
|
throw new Error(`${e.message} ${definitionAtLine}`);
|
|
2652
2700
|
}
|
|
2653
2701
|
}
|
|
2654
|
-
else {
|
|
2655
|
-
fieldIndex = metadata[field].index;
|
|
2656
|
-
}
|
|
2657
2702
|
}
|
|
2658
2703
|
else {
|
|
2659
2704
|
//
|
|
@@ -2679,11 +2724,11 @@ function type(type, options) {
|
|
|
2679
2724
|
const childType = (complexTypeKlass)
|
|
2680
2725
|
? Object.values(type)[0]
|
|
2681
2726
|
: type;
|
|
2682
|
-
Metadata.addField(metadata, fieldIndex, field, type, getPropertyDescriptor(`_${field}`, fieldIndex, childType, complexTypeKlass
|
|
2727
|
+
Metadata.addField(metadata, fieldIndex, field, type, getPropertyDescriptor(`_${field}`, fieldIndex, childType, complexTypeKlass));
|
|
2683
2728
|
}
|
|
2684
2729
|
};
|
|
2685
2730
|
}
|
|
2686
|
-
function getPropertyDescriptor(fieldCached, fieldIndex, type, complexTypeKlass
|
|
2731
|
+
function getPropertyDescriptor(fieldCached, fieldIndex, type, complexTypeKlass) {
|
|
2687
2732
|
return {
|
|
2688
2733
|
get: function () { return this[fieldCached]; },
|
|
2689
2734
|
set: function (value) {
|
|
@@ -2705,22 +2750,27 @@ function getPropertyDescriptor(fieldCached, fieldIndex, type, complexTypeKlass,
|
|
|
2705
2750
|
}
|
|
2706
2751
|
value[$childType] = type;
|
|
2707
2752
|
}
|
|
2753
|
+
else if (typeof (type) !== "string") {
|
|
2754
|
+
assertInstanceType(value, type, this, fieldCached.substring(1));
|
|
2755
|
+
}
|
|
2756
|
+
else {
|
|
2757
|
+
assertType(value, type, this, fieldCached.substring(1));
|
|
2758
|
+
}
|
|
2759
|
+
const changeTree = this[$changes];
|
|
2708
2760
|
//
|
|
2709
2761
|
// Replacing existing "ref", remove it from root.
|
|
2710
2762
|
// TODO: if there are other references to this instance, we should not remove it from root.
|
|
2711
2763
|
//
|
|
2712
2764
|
if (previousValue !== undefined && previousValue[$changes]) {
|
|
2713
|
-
|
|
2765
|
+
changeTree.root?.remove(previousValue[$changes]);
|
|
2714
2766
|
}
|
|
2715
2767
|
// flag the change for encoding.
|
|
2716
|
-
this.constructor[$track](
|
|
2768
|
+
this.constructor[$track](changeTree, fieldIndex, exports.OPERATION.ADD);
|
|
2717
2769
|
//
|
|
2718
2770
|
// call setParent() recursively for this and its child
|
|
2719
2771
|
// structures.
|
|
2720
2772
|
//
|
|
2721
|
-
|
|
2722
|
-
value[$changes].setParent(this, this[$changes].root, metadata[field].index);
|
|
2723
|
-
}
|
|
2773
|
+
value[$changes]?.setParent(this, changeTree.root, fieldIndex);
|
|
2724
2774
|
}
|
|
2725
2775
|
else if (previousValue !== undefined) {
|
|
2726
2776
|
//
|
|
@@ -2747,20 +2797,22 @@ function deprecated(throws = true) {
|
|
|
2747
2797
|
const parentClass = Object.getPrototypeOf(constructor);
|
|
2748
2798
|
const parentMetadata = parentClass[Symbol.metadata];
|
|
2749
2799
|
const metadata = (constructor[Symbol.metadata] ??= Object.assign({}, constructor[Symbol.metadata], parentMetadata ?? Object.create(null)));
|
|
2750
|
-
|
|
2751
|
-
|
|
2752
|
-
|
|
2753
|
-
|
|
2754
|
-
|
|
2755
|
-
|
|
2756
|
-
|
|
2757
|
-
|
|
2758
|
-
|
|
2759
|
-
|
|
2760
|
-
}
|
|
2761
|
-
|
|
2800
|
+
const fieldIndex = metadata[field];
|
|
2801
|
+
// if (!metadata[field]) {
|
|
2802
|
+
// //
|
|
2803
|
+
// // detect index for this field, considering inheritance
|
|
2804
|
+
// //
|
|
2805
|
+
// metadata[field] = {
|
|
2806
|
+
// type: undefined,
|
|
2807
|
+
// index: (metadata[-1] // current structure already has fields defined
|
|
2808
|
+
// ?? (parentMetadata && parentMetadata[-1]) // parent structure has fields defined
|
|
2809
|
+
// ?? -1) + 1 // no fields defined
|
|
2810
|
+
// }
|
|
2811
|
+
// }
|
|
2812
|
+
metadata[fieldIndex].deprecated = true;
|
|
2762
2813
|
if (throws) {
|
|
2763
|
-
metadata[
|
|
2814
|
+
metadata[$descriptors] ??= {};
|
|
2815
|
+
metadata[$descriptors][field] = {
|
|
2764
2816
|
get: function () { throw new Error(`${field} is deprecated.`); },
|
|
2765
2817
|
set: function (value) { },
|
|
2766
2818
|
enumerable: false,
|
|
@@ -2768,8 +2820,8 @@ function deprecated(throws = true) {
|
|
|
2768
2820
|
};
|
|
2769
2821
|
}
|
|
2770
2822
|
// flag metadata[field] as non-enumerable
|
|
2771
|
-
Object.defineProperty(metadata,
|
|
2772
|
-
value: metadata[
|
|
2823
|
+
Object.defineProperty(metadata, fieldIndex, {
|
|
2824
|
+
value: metadata[fieldIndex],
|
|
2773
2825
|
enumerable: false,
|
|
2774
2826
|
configurable: true
|
|
2775
2827
|
});
|
|
@@ -2835,35 +2887,7 @@ class Schema {
|
|
|
2835
2887
|
enumerable: false,
|
|
2836
2888
|
writable: true
|
|
2837
2889
|
});
|
|
2838
|
-
|
|
2839
|
-
// Define property descriptors
|
|
2840
|
-
for (const field in metadata) {
|
|
2841
|
-
if (metadata[field].descriptor) {
|
|
2842
|
-
// for encoder
|
|
2843
|
-
Object.defineProperty(instance, `_${field}`, {
|
|
2844
|
-
value: undefined,
|
|
2845
|
-
writable: true,
|
|
2846
|
-
enumerable: false,
|
|
2847
|
-
configurable: true,
|
|
2848
|
-
});
|
|
2849
|
-
Object.defineProperty(instance, field, metadata[field].descriptor);
|
|
2850
|
-
}
|
|
2851
|
-
else {
|
|
2852
|
-
// for decoder
|
|
2853
|
-
Object.defineProperty(instance, field, {
|
|
2854
|
-
value: undefined,
|
|
2855
|
-
writable: true,
|
|
2856
|
-
enumerable: true,
|
|
2857
|
-
configurable: true,
|
|
2858
|
-
});
|
|
2859
|
-
}
|
|
2860
|
-
// Object.defineProperty(instance, field, {
|
|
2861
|
-
// ...instance.constructor[Symbol.metadata][field].descriptor
|
|
2862
|
-
// });
|
|
2863
|
-
// if (args[0]?.hasOwnProperty(field)) {
|
|
2864
|
-
// instance[field] = args[0][field];
|
|
2865
|
-
// }
|
|
2866
|
-
}
|
|
2890
|
+
Object.defineProperties(instance, instance.constructor[Symbol.metadata]?.[$descriptors] || {});
|
|
2867
2891
|
}
|
|
2868
2892
|
static is(type) {
|
|
2869
2893
|
return typeof (type[Symbol.metadata]) === "object";
|
|
@@ -2887,7 +2911,7 @@ class Schema {
|
|
|
2887
2911
|
*/
|
|
2888
2912
|
static [$filter](ref, index, view) {
|
|
2889
2913
|
const metadata = ref.constructor[Symbol.metadata];
|
|
2890
|
-
const tag = metadata[
|
|
2914
|
+
const tag = metadata[index]?.tag;
|
|
2891
2915
|
if (view === undefined) {
|
|
2892
2916
|
// shared pass/encode: encode if doesn't have a tag
|
|
2893
2917
|
return tag === undefined;
|
|
@@ -2908,12 +2932,21 @@ class Schema {
|
|
|
2908
2932
|
}
|
|
2909
2933
|
// allow inherited classes to have a constructor
|
|
2910
2934
|
constructor(...args) {
|
|
2911
|
-
|
|
2935
|
+
//
|
|
2936
|
+
// inline
|
|
2937
|
+
// Schema.initialize(this);
|
|
2938
|
+
//
|
|
2939
|
+
Object.defineProperty(this, $changes, {
|
|
2940
|
+
value: new ChangeTree(this),
|
|
2941
|
+
enumerable: false,
|
|
2942
|
+
writable: true
|
|
2943
|
+
});
|
|
2944
|
+
Object.defineProperties(this, this.constructor[Symbol.metadata]?.[$descriptors] || {});
|
|
2912
2945
|
//
|
|
2913
2946
|
// Assign initial values
|
|
2914
2947
|
//
|
|
2915
2948
|
if (args[0]) {
|
|
2916
|
-
|
|
2949
|
+
Object.assign(this, args[0]);
|
|
2917
2950
|
}
|
|
2918
2951
|
}
|
|
2919
2952
|
assign(props) {
|
|
@@ -2927,7 +2960,8 @@ class Schema {
|
|
|
2927
2960
|
* @param operation OPERATION to perform (detected automatically)
|
|
2928
2961
|
*/
|
|
2929
2962
|
setDirty(property, operation) {
|
|
2930
|
-
this
|
|
2963
|
+
const metadata = this.constructor[Symbol.metadata];
|
|
2964
|
+
this[$changes].change(metadata[metadata[property]].index, operation);
|
|
2931
2965
|
}
|
|
2932
2966
|
clone() {
|
|
2933
2967
|
const cloned = new (this.constructor);
|
|
@@ -2936,7 +2970,9 @@ class Schema {
|
|
|
2936
2970
|
// TODO: clone all properties, not only annotated ones
|
|
2937
2971
|
//
|
|
2938
2972
|
// for (const field in this) {
|
|
2939
|
-
for (const
|
|
2973
|
+
for (const fieldIndex in metadata) {
|
|
2974
|
+
// const field = metadata[metadata[fieldIndex]].name;
|
|
2975
|
+
const field = metadata[fieldIndex].name;
|
|
2940
2976
|
if (typeof (this[field]) === "object" &&
|
|
2941
2977
|
typeof (this[field]?.clone) === "function") {
|
|
2942
2978
|
// deep clone
|
|
@@ -2950,10 +2986,11 @@ class Schema {
|
|
|
2950
2986
|
return cloned;
|
|
2951
2987
|
}
|
|
2952
2988
|
toJSON() {
|
|
2953
|
-
const metadata = this.constructor[Symbol.metadata];
|
|
2954
2989
|
const obj = {};
|
|
2955
|
-
|
|
2956
|
-
|
|
2990
|
+
const metadata = this.constructor[Symbol.metadata];
|
|
2991
|
+
for (const index in metadata) {
|
|
2992
|
+
const field = metadata[index];
|
|
2993
|
+
const fieldName = field.name;
|
|
2957
2994
|
if (!field.deprecated && this[fieldName] !== null && typeof (this[fieldName]) !== "undefined") {
|
|
2958
2995
|
obj[fieldName] = (typeof (this[fieldName]['toJSON']) === "function")
|
|
2959
2996
|
? this[fieldName]['toJSON']()
|
|
@@ -2966,10 +3003,12 @@ class Schema {
|
|
|
2966
3003
|
this[$changes].discardAll();
|
|
2967
3004
|
}
|
|
2968
3005
|
[$getByIndex](index) {
|
|
2969
|
-
|
|
3006
|
+
const metadata = this.constructor[Symbol.metadata];
|
|
3007
|
+
return this[metadata[index].name];
|
|
2970
3008
|
}
|
|
2971
3009
|
[$deleteByIndex](index) {
|
|
2972
|
-
this
|
|
3010
|
+
const metadata = this.constructor[Symbol.metadata];
|
|
3011
|
+
this[metadata[index].name] = undefined;
|
|
2973
3012
|
}
|
|
2974
3013
|
static debugRefIds(instance, jsonContents = true, level = 0) {
|
|
2975
3014
|
const ref = instance;
|
|
@@ -3093,6 +3132,7 @@ class CollectionSchema {
|
|
|
3093
3132
|
this.$indexes = new Map();
|
|
3094
3133
|
this.$refId = 0;
|
|
3095
3134
|
this[$changes] = new ChangeTree(this);
|
|
3135
|
+
this[$changes].indexes = {};
|
|
3096
3136
|
if (initialValues) {
|
|
3097
3137
|
initialValues.forEach((v) => this.add(v));
|
|
3098
3138
|
}
|
|
@@ -3248,6 +3288,7 @@ class SetSchema {
|
|
|
3248
3288
|
this.$indexes = new Map();
|
|
3249
3289
|
this.$refId = 0;
|
|
3250
3290
|
this[$changes] = new ChangeTree(this);
|
|
3291
|
+
this[$changes].indexes = {};
|
|
3251
3292
|
if (initialValues) {
|
|
3252
3293
|
initialValues.forEach((v) => this.add(v));
|
|
3253
3294
|
}
|
|
@@ -3482,8 +3523,8 @@ class Encoder {
|
|
|
3482
3523
|
) {
|
|
3483
3524
|
const hasView = (view !== undefined);
|
|
3484
3525
|
const rootChangeTree = this.state[$changes];
|
|
3485
|
-
const
|
|
3486
|
-
for (const [changeTree, changes] of
|
|
3526
|
+
const shouldClearChanges = !isEncodeAll && !hasView;
|
|
3527
|
+
for (const [changeTree, changes] of changeTrees.entries()) {
|
|
3487
3528
|
const ref = changeTree.ref;
|
|
3488
3529
|
const ctor = ref['constructor'];
|
|
3489
3530
|
const encoder = ctor[$encoder];
|
|
@@ -3535,6 +3576,9 @@ class Encoder {
|
|
|
3535
3576
|
// }
|
|
3536
3577
|
encoder(this, buffer, changeTree, fieldIndex, operation, it, isEncodeAll, hasView);
|
|
3537
3578
|
}
|
|
3579
|
+
// if (shouldClearChanges) {
|
|
3580
|
+
// changeTree.endEncode();
|
|
3581
|
+
// }
|
|
3538
3582
|
}
|
|
3539
3583
|
if (it.offset > buffer.byteLength) {
|
|
3540
3584
|
const newSize = getNextPowerOf2(buffer.byteLength * 2);
|
|
@@ -3557,7 +3601,7 @@ class Encoder {
|
|
|
3557
3601
|
//
|
|
3558
3602
|
// only clear changes after making sure buffer resize is not required.
|
|
3559
3603
|
//
|
|
3560
|
-
if (
|
|
3604
|
+
if (shouldClearChanges) {
|
|
3561
3605
|
//
|
|
3562
3606
|
// FIXME: avoid iterating over change trees twice.
|
|
3563
3607
|
//
|
|
@@ -3641,6 +3685,11 @@ class Encoder {
|
|
|
3641
3685
|
const changeTreesIterator = changeTrees.entries();
|
|
3642
3686
|
for (const [changeTree, _] of changeTreesIterator) {
|
|
3643
3687
|
changeTree.endEncode();
|
|
3688
|
+
// changeTree.changes.clear();
|
|
3689
|
+
// // ArraySchema and MapSchema have a custom "encode end" method
|
|
3690
|
+
// changeTree.ref[$onEncodeEnd]?.();
|
|
3691
|
+
// // Not a new instance anymore
|
|
3692
|
+
// delete changeTree[$isNew];
|
|
3644
3693
|
}
|
|
3645
3694
|
}
|
|
3646
3695
|
discardChanges() {
|
|
@@ -3756,8 +3805,9 @@ class ReferenceTracker {
|
|
|
3756
3805
|
// Ensure child schema instances have their references removed as well.
|
|
3757
3806
|
//
|
|
3758
3807
|
if (Metadata.isValidInstance(ref)) {
|
|
3759
|
-
const metadata = ref
|
|
3760
|
-
for (const
|
|
3808
|
+
const metadata = ref.constructor[Symbol.metadata];
|
|
3809
|
+
for (const index in metadata) {
|
|
3810
|
+
const field = metadata[index].name;
|
|
3761
3811
|
const childRefId = typeof (ref[field]) === "object" && this.refIds.get(ref[field]);
|
|
3762
3812
|
if (childRefId) {
|
|
3763
3813
|
this.removeRef(childRefId);
|
|
@@ -3944,7 +3994,9 @@ class Reflection extends Schema {
|
|
|
3944
3994
|
const reflection = new Reflection();
|
|
3945
3995
|
const encoder = new Encoder(reflection);
|
|
3946
3996
|
const buildType = (currentType, metadata) => {
|
|
3947
|
-
for (const
|
|
3997
|
+
for (const fieldIndex in metadata) {
|
|
3998
|
+
const index = Number(fieldIndex);
|
|
3999
|
+
const fieldName = metadata[index].name;
|
|
3948
4000
|
// skip fields from parent classes
|
|
3949
4001
|
if (!Object.prototype.hasOwnProperty.call(metadata, fieldName)) {
|
|
3950
4002
|
continue;
|
|
@@ -3952,7 +4004,7 @@ class Reflection extends Schema {
|
|
|
3952
4004
|
const field = new ReflectionField();
|
|
3953
4005
|
field.name = fieldName;
|
|
3954
4006
|
let fieldType;
|
|
3955
|
-
const type = metadata[
|
|
4007
|
+
const type = metadata[index].type;
|
|
3956
4008
|
if (typeof (type) === "string") {
|
|
3957
4009
|
fieldType = type;
|
|
3958
4010
|
}
|
|
@@ -4018,18 +4070,7 @@ class Reflection extends Schema {
|
|
|
4018
4070
|
reflection.types.forEach((reflectionType) => {
|
|
4019
4071
|
const schemaType = typeContext.get(reflectionType.id);
|
|
4020
4072
|
const metadata = schemaType[Symbol.metadata];
|
|
4021
|
-
// FIXME: use metadata[-1] to get field count
|
|
4022
4073
|
const parentFieldIndex = 0;
|
|
4023
|
-
// console.log("--------------------");
|
|
4024
|
-
// // console.log("reflectionType", reflectionType.toJSON());
|
|
4025
|
-
// console.log("reflectionType.fields", reflectionType.fields.toJSON());
|
|
4026
|
-
// console.log("parentFieldIndex", parentFieldIndex);
|
|
4027
|
-
//
|
|
4028
|
-
// FIXME: set fields using parentKlass as well
|
|
4029
|
-
// currently the fields are duplicated on inherited classes
|
|
4030
|
-
//
|
|
4031
|
-
// // const parentKlass = reflection.types[reflectionType.extendsId];
|
|
4032
|
-
// // parentKlass.fields
|
|
4033
4074
|
reflectionType.fields.forEach((field, i) => {
|
|
4034
4075
|
const fieldIndex = parentFieldIndex + i;
|
|
4035
4076
|
if (field.referencedType !== undefined) {
|
|
@@ -4194,7 +4235,7 @@ function getDecoderStateCallbacks(decoder) {
|
|
|
4194
4235
|
//
|
|
4195
4236
|
bindTo: function bindTo(targetObject, properties) {
|
|
4196
4237
|
if (!properties) {
|
|
4197
|
-
properties = Object.keys(metadata);
|
|
4238
|
+
properties = Object.keys(metadata).map((index) => metadata[index].name);
|
|
4198
4239
|
}
|
|
4199
4240
|
return $root.addCallback($root.refIds.get(context.instance), exports.OPERATION.REPLACE, () => {
|
|
4200
4241
|
properties.forEach((prop) => targetObject[prop] = context.instance[prop]);
|
|
@@ -4202,7 +4243,8 @@ function getDecoderStateCallbacks(decoder) {
|
|
|
4202
4243
|
}
|
|
4203
4244
|
}, {
|
|
4204
4245
|
get(target, prop) {
|
|
4205
|
-
|
|
4246
|
+
const metadataField = metadata[metadata[prop]];
|
|
4247
|
+
if (metadataField) {
|
|
4206
4248
|
const instance = context.instance?.[prop];
|
|
4207
4249
|
const onInstanceAvailable = ((callback) => {
|
|
4208
4250
|
const unbind = $(context.instance).listen(prop, (value, _) => {
|
|
@@ -4218,7 +4260,7 @@ function getDecoderStateCallbacks(decoder) {
|
|
|
4218
4260
|
callback(instance, true);
|
|
4219
4261
|
}
|
|
4220
4262
|
});
|
|
4221
|
-
return getProxy(
|
|
4263
|
+
return getProxy(metadataField.type, {
|
|
4222
4264
|
// make sure refId is available, otherwise need to wait for the instance to be available.
|
|
4223
4265
|
instance: ($root.refIds.get(instance) && instance),
|
|
4224
4266
|
parentInstance: context.instance,
|
|
@@ -4331,7 +4373,7 @@ class StateView {
|
|
|
4331
4373
|
console.warn("StateView#add(), invalid object:", obj);
|
|
4332
4374
|
return this;
|
|
4333
4375
|
}
|
|
4334
|
-
// FIXME: ArraySchema/MapSchema
|
|
4376
|
+
// FIXME: ArraySchema/MapSchema do not have metadata
|
|
4335
4377
|
const metadata = obj.constructor[Symbol.metadata];
|
|
4336
4378
|
const changeTree = obj[$changes];
|
|
4337
4379
|
this.items.add(changeTree);
|
|
@@ -4377,7 +4419,7 @@ class StateView {
|
|
|
4377
4419
|
? changeTree.allFilteredChanges
|
|
4378
4420
|
: changeTree.allChanges;
|
|
4379
4421
|
changeSet.forEach((op, index) => {
|
|
4380
|
-
const tagAtIndex = metadata?.[
|
|
4422
|
+
const tagAtIndex = metadata?.[index].tag;
|
|
4381
4423
|
if ((isInvisible || // if "invisible", include all
|
|
4382
4424
|
tagAtIndex === undefined || // "all change" with no tag
|
|
4383
4425
|
tagAtIndex === tag // tagged property
|
|
@@ -4390,7 +4432,7 @@ class StateView {
|
|
|
4390
4432
|
// Add children of this ChangeTree to this view
|
|
4391
4433
|
changeTree.forEachChild((change, index) => {
|
|
4392
4434
|
// Do not ADD children that don't have the same tag
|
|
4393
|
-
if (metadata && metadata[
|
|
4435
|
+
if (metadata && metadata[index].tag !== tag) {
|
|
4394
4436
|
return;
|
|
4395
4437
|
}
|
|
4396
4438
|
this.add(change.ref, tag, false);
|