@colyseus/schema 3.0.0-alpha.0 → 3.0.0-alpha.10
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 +1219 -1427
- package/build/cjs/index.js.map +1 -1
- package/build/esm/index.mjs +85 -64
- package/build/esm/index.mjs.map +1 -1
- package/build/umd/index.js +1219 -1427
- package/lib/Reflection.d.ts +1 -1
- package/lib/Reflection.js +1 -2
- package/lib/Reflection.js.map +1 -1
- package/lib/decoder/DecodeOperation.js +2 -2
- package/lib/decoder/DecodeOperation.js.map +1 -1
- package/lib/decoder/Decoder.d.ts +1 -1
- package/lib/decoder/Decoder.js +4 -4
- package/lib/decoder/Decoder.js.map +1 -1
- package/lib/decoder/strategy/StateCallbacks.js +1 -1
- package/lib/decoder/strategy/StateCallbacks.js.map +1 -1
- package/lib/encoder/ChangeTree.d.ts +0 -2
- package/lib/encoder/ChangeTree.js +2 -6
- package/lib/encoder/ChangeTree.js.map +1 -1
- package/lib/encoder/Encoder.d.ts +5 -4
- package/lib/encoder/Encoder.js +46 -43
- package/lib/encoder/Encoder.js.map +1 -1
- package/lib/encoder/StateView.d.ts +2 -0
- package/lib/encoder/StateView.js +4 -1
- package/lib/encoder/StateView.js.map +1 -1
- package/lib/encoding/decode.d.ts +21 -19
- package/lib/encoding/decode.js +6 -6
- package/lib/encoding/decode.js.map +1 -1
- package/lib/encoding/encode.d.ts +19 -16
- package/lib/encoding/encode.js +24 -22
- package/lib/encoding/encode.js.map +1 -1
- package/package.json +1 -1
- package/src/Reflection.ts +1 -2
- package/src/decoder/DecodeOperation.ts +3 -3
- package/src/decoder/Decoder.ts +5 -5
- package/src/decoder/strategy/StateCallbacks.ts +1 -1
- package/src/encoder/ChangeTree.ts +2 -6
- package/src/encoder/Encoder.ts +51 -47
- package/src/encoder/StateView.ts +4 -0
- package/src/encoding/decode.ts +24 -25
- package/src/encoding/encode.ts +43 -37
package/build/umd/index.js
CHANGED
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.schema = {}));
|
|
5
5
|
})(this, (function (exports) { 'use strict';
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
7
|
+
const SWITCH_TO_STRUCTURE = 255; // (decoding collides with DELETE_AND_ADD + fieldIndex = 63)
|
|
8
|
+
const TYPE_ID = 213;
|
|
9
9
|
/**
|
|
10
10
|
* Encoding Schema field operations.
|
|
11
11
|
*/
|
|
@@ -31,95 +31,40 @@
|
|
|
31
31
|
OPERATION[OPERATION["DELETE_BY_REFID"] = 33] = "DELETE_BY_REFID";
|
|
32
32
|
})(exports.OPERATION || (exports.OPERATION = {}));
|
|
33
33
|
|
|
34
|
-
|
|
35
|
-
Copyright (c) Microsoft Corporation.
|
|
36
|
-
|
|
37
|
-
Permission to use, copy, modify, and/or distribute this software for any
|
|
38
|
-
purpose with or without fee is hereby granted.
|
|
39
|
-
|
|
40
|
-
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
|
41
|
-
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
|
42
|
-
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
|
43
|
-
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
|
44
|
-
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
|
45
|
-
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
|
46
|
-
PERFORMANCE OF THIS SOFTWARE.
|
|
47
|
-
***************************************************************************** */
|
|
48
|
-
/* global Reflect, Promise, SuppressedError, Symbol */
|
|
49
|
-
|
|
50
|
-
var extendStatics = function(d, b) {
|
|
51
|
-
extendStatics = Object.setPrototypeOf ||
|
|
52
|
-
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
|
|
53
|
-
function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
|
|
54
|
-
return extendStatics(d, b);
|
|
55
|
-
};
|
|
56
|
-
|
|
57
|
-
function __extends(d, b) {
|
|
58
|
-
if (typeof b !== "function" && b !== null)
|
|
59
|
-
throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
|
|
60
|
-
extendStatics(d, b);
|
|
61
|
-
function __() { this.constructor = d; }
|
|
62
|
-
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
function __decorate(decorators, target, key, desc) {
|
|
66
|
-
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
67
|
-
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
68
|
-
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
69
|
-
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
function __spreadArray(to, from, pack) {
|
|
73
|
-
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
|
|
74
|
-
if (ar || !(i in from)) {
|
|
75
|
-
if (!ar) ar = Array.prototype.slice.call(from, 0, i);
|
|
76
|
-
ar[i] = from[i];
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
return to.concat(ar || Array.prototype.slice.call(from));
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
|
|
83
|
-
var e = new Error(message);
|
|
84
|
-
return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
|
|
85
|
-
};
|
|
86
|
-
|
|
87
|
-
var _a$1;
|
|
88
|
-
var _b;
|
|
89
|
-
(_a$1 = (_b = Symbol).metadata) !== null && _a$1 !== void 0 ? _a$1 : (_b.metadata = Symbol.for("Symbol.metadata"));
|
|
34
|
+
Symbol.metadata ??= Symbol.for("Symbol.metadata");
|
|
90
35
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
36
|
+
const $track = Symbol("$track");
|
|
37
|
+
const $encoder = Symbol("$encoder");
|
|
38
|
+
const $decoder = Symbol("$decoder");
|
|
39
|
+
const $filter = Symbol("$filter");
|
|
40
|
+
const $getByIndex = Symbol("$getByIndex");
|
|
41
|
+
const $deleteByIndex = Symbol("$deleteByIndex");
|
|
97
42
|
/**
|
|
98
43
|
* Used to hold ChangeTree instances whitin the structures
|
|
99
44
|
*/
|
|
100
|
-
|
|
45
|
+
const $changes = Symbol('$changes');
|
|
101
46
|
/**
|
|
102
47
|
* Used to keep track of the type of the child elements of a collection
|
|
103
48
|
* (MapSchema, ArraySchema, etc.)
|
|
104
49
|
*/
|
|
105
|
-
|
|
50
|
+
const $childType = Symbol('$childType');
|
|
106
51
|
/**
|
|
107
52
|
* Special ChangeTree property to identify new instances
|
|
108
53
|
* (Once they're encoded, they're not new anymore)
|
|
109
54
|
*/
|
|
110
|
-
|
|
55
|
+
const $isNew = Symbol("$isNew");
|
|
111
56
|
/**
|
|
112
57
|
* Optional "discard" method for custom types (ArraySchema)
|
|
113
58
|
* (Discards changes for next serialization)
|
|
114
59
|
*/
|
|
115
|
-
|
|
60
|
+
const $onEncodeEnd = Symbol('$onEncodeEnd');
|
|
116
61
|
/**
|
|
117
62
|
* When decoding, this method is called after the instance is fully decoded
|
|
118
63
|
*/
|
|
119
|
-
|
|
64
|
+
const $onDecodeEnd = Symbol("$onDecodeEnd");
|
|
120
65
|
|
|
121
|
-
|
|
122
|
-
|
|
66
|
+
const registeredTypes = {};
|
|
67
|
+
const identifiers = new Map();
|
|
123
68
|
function registerType(identifier, definition) {
|
|
124
69
|
identifiers.set(definition.constructor, identifier);
|
|
125
70
|
registeredTypes[identifier] = definition;
|
|
@@ -128,18 +73,18 @@
|
|
|
128
73
|
return registeredTypes[identifier];
|
|
129
74
|
}
|
|
130
75
|
|
|
131
|
-
|
|
132
|
-
addField
|
|
76
|
+
const Metadata = {
|
|
77
|
+
addField(metadata, index, field, type, descriptor) {
|
|
133
78
|
if (index > 64) {
|
|
134
|
-
throw new Error(
|
|
79
|
+
throw new Error(`Can't define field '${field}'.\nSchema instances may only have up to 64 fields.`);
|
|
135
80
|
}
|
|
136
81
|
metadata[field] = Object.assign(metadata[field] || {}, // avoid overwriting previous field metadata (@owned / @deprecated)
|
|
137
82
|
{
|
|
138
83
|
type: (Array.isArray(type))
|
|
139
84
|
? { array: type[0] }
|
|
140
85
|
: type,
|
|
141
|
-
index
|
|
142
|
-
descriptor
|
|
86
|
+
index,
|
|
87
|
+
descriptor,
|
|
143
88
|
});
|
|
144
89
|
// map -1 as last field index
|
|
145
90
|
Object.defineProperty(metadata, -1, {
|
|
@@ -154,9 +99,9 @@
|
|
|
154
99
|
configurable: true,
|
|
155
100
|
});
|
|
156
101
|
},
|
|
157
|
-
setTag
|
|
102
|
+
setTag(metadata, fieldName, tag) {
|
|
158
103
|
// add 'tag' to the field
|
|
159
|
-
|
|
104
|
+
const field = metadata[fieldName];
|
|
160
105
|
field.tag = tag;
|
|
161
106
|
if (!metadata[-2]) {
|
|
162
107
|
// -2: all field indexes with "view" tag
|
|
@@ -178,47 +123,45 @@
|
|
|
178
123
|
}
|
|
179
124
|
metadata[-3][tag].push(field.index);
|
|
180
125
|
},
|
|
181
|
-
setFields
|
|
182
|
-
|
|
183
|
-
var _b, _c;
|
|
184
|
-
var metadata = ((_a = (_b = target.prototype.constructor)[_c = Symbol.metadata]) !== null && _a !== void 0 ? _a : (_b[_c] = {}));
|
|
126
|
+
setFields(target, fields) {
|
|
127
|
+
const metadata = (target.prototype.constructor[Symbol.metadata] ??= {});
|
|
185
128
|
// target[$track] = function (changeTree, index: number, operation: OPERATION = OPERATION.ADD) {
|
|
186
129
|
// changeTree.change(index, operation, encodeSchemaOperation);
|
|
187
130
|
// };
|
|
188
131
|
// target[$encoder] = encodeSchemaOperation;
|
|
189
132
|
// target[$decoder] = decodeSchemaOperation;
|
|
190
133
|
// if (!target.prototype.toJSON) { target.prototype.toJSON = Schema.prototype.toJSON; }
|
|
191
|
-
|
|
192
|
-
for (
|
|
193
|
-
|
|
134
|
+
let index = 0;
|
|
135
|
+
for (const field in fields) {
|
|
136
|
+
const type = fields[field];
|
|
194
137
|
// FIXME: this code is duplicated from @type() annotation
|
|
195
|
-
|
|
138
|
+
const complexTypeKlass = (Array.isArray(type))
|
|
196
139
|
? getType("array")
|
|
197
140
|
: (typeof (Object.keys(type)[0]) === "string") && getType(Object.keys(type)[0]);
|
|
198
|
-
Metadata.addField(metadata, index, field, type, getPropertyDescriptor(
|
|
141
|
+
Metadata.addField(metadata, index, field, type, getPropertyDescriptor(`_${field}`, index, type, complexTypeKlass, metadata, field));
|
|
199
142
|
index++;
|
|
200
143
|
}
|
|
201
144
|
},
|
|
202
|
-
isDeprecated
|
|
145
|
+
isDeprecated(metadata, field) {
|
|
203
146
|
return metadata[field].deprecated === true;
|
|
204
147
|
},
|
|
205
|
-
isValidInstance
|
|
148
|
+
isValidInstance(klass) {
|
|
206
149
|
return (klass.constructor[Symbol.metadata] &&
|
|
207
150
|
Object.prototype.hasOwnProperty.call(klass.constructor[Symbol.metadata], -1));
|
|
208
151
|
},
|
|
209
|
-
getFields
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
for (
|
|
152
|
+
getFields(klass) {
|
|
153
|
+
const metadata = klass[Symbol.metadata];
|
|
154
|
+
const fields = {};
|
|
155
|
+
for (let i = 0; i <= metadata[-1]; i++) {
|
|
213
156
|
fields[metadata[i]] = metadata[metadata[i]].type;
|
|
214
157
|
}
|
|
215
158
|
return fields;
|
|
216
159
|
}
|
|
217
160
|
};
|
|
218
161
|
|
|
219
|
-
var _a;
|
|
220
|
-
|
|
221
|
-
|
|
162
|
+
var _a$5;
|
|
163
|
+
class Root {
|
|
164
|
+
constructor() {
|
|
222
165
|
this.nextUniqueId = 0;
|
|
223
166
|
this.refCount = new WeakMap();
|
|
224
167
|
// all changes
|
|
@@ -227,18 +170,16 @@
|
|
|
227
170
|
// pending changes to be encoded
|
|
228
171
|
this.changes = new Map();
|
|
229
172
|
this.filteredChanges = new Map();
|
|
230
|
-
this.views = [];
|
|
231
173
|
}
|
|
232
|
-
|
|
174
|
+
getNextUniqueId() {
|
|
233
175
|
return this.nextUniqueId++;
|
|
234
|
-
}
|
|
235
|
-
|
|
236
|
-
|
|
176
|
+
}
|
|
177
|
+
add(changeTree) {
|
|
178
|
+
const refCount = this.refCount.get(changeTree) || 0;
|
|
237
179
|
this.refCount.set(changeTree, refCount + 1);
|
|
238
|
-
}
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
var refCount = this.refCount.get(changeTree);
|
|
180
|
+
}
|
|
181
|
+
remove(changeTree) {
|
|
182
|
+
const refCount = this.refCount.get(changeTree);
|
|
242
183
|
if (refCount <= 1) {
|
|
243
184
|
this.allChanges.delete(changeTree);
|
|
244
185
|
this.changes.delete(changeTree);
|
|
@@ -251,27 +192,26 @@
|
|
|
251
192
|
else {
|
|
252
193
|
this.refCount.set(changeTree, refCount - 1);
|
|
253
194
|
}
|
|
254
|
-
changeTree.forEachChild(
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
};
|
|
258
|
-
Root.prototype.clear = function () {
|
|
195
|
+
changeTree.forEachChild((child, _) => this.remove(child));
|
|
196
|
+
}
|
|
197
|
+
clear() {
|
|
259
198
|
this.changes.clear();
|
|
260
|
-
}
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
class ChangeTree {
|
|
202
|
+
static { _a$5 = $isNew; }
|
|
203
|
+
;
|
|
204
|
+
constructor(ref) {
|
|
265
205
|
this.indexes = {}; // TODO: remove this, only used by MapSchema/SetSchema/CollectionSchema (`encodeKeyValueOperation`)
|
|
266
206
|
this.currentOperationIndex = 0;
|
|
267
207
|
this.allChanges = new Map();
|
|
268
208
|
this.allFilteredChanges = new Map();
|
|
269
209
|
this.changes = new Map();
|
|
270
210
|
this.filteredChanges = new Map();
|
|
271
|
-
this[_a] = true;
|
|
211
|
+
this[_a$5] = true;
|
|
272
212
|
this.ref = ref;
|
|
273
213
|
}
|
|
274
|
-
|
|
214
|
+
setRoot(root) {
|
|
275
215
|
this.root = root;
|
|
276
216
|
this.root.add(this);
|
|
277
217
|
//
|
|
@@ -295,7 +235,7 @@
|
|
|
295
235
|
if (!this.isFiltered) {
|
|
296
236
|
this.root.allChanges.set(this, this.allChanges);
|
|
297
237
|
}
|
|
298
|
-
this.forEachChild(
|
|
238
|
+
this.forEachChild((changeTree, _) => {
|
|
299
239
|
changeTree.setRoot(root);
|
|
300
240
|
});
|
|
301
241
|
// this.allChanges.forEach((_, index) => {
|
|
@@ -304,9 +244,8 @@
|
|
|
304
244
|
// childRef[$changes].setRoot(root);
|
|
305
245
|
// }
|
|
306
246
|
// });
|
|
307
|
-
}
|
|
308
|
-
|
|
309
|
-
var _this = this;
|
|
247
|
+
}
|
|
248
|
+
setParent(parent, root, parentIndex) {
|
|
310
249
|
this.parent = parent;
|
|
311
250
|
this.parentIndex = parentIndex;
|
|
312
251
|
// avoid setting parents with empty `root`
|
|
@@ -316,8 +255,8 @@
|
|
|
316
255
|
root.add(this);
|
|
317
256
|
// skip if parent is already set
|
|
318
257
|
if (root === this.root) {
|
|
319
|
-
this.forEachChild(
|
|
320
|
-
changeTree.setParent(
|
|
258
|
+
this.forEachChild((changeTree, atIndex) => {
|
|
259
|
+
changeTree.setParent(this.ref, root, atIndex);
|
|
321
260
|
});
|
|
322
261
|
return;
|
|
323
262
|
}
|
|
@@ -325,29 +264,26 @@
|
|
|
325
264
|
this.checkIsFiltered(parent, parentIndex);
|
|
326
265
|
if (!this.isFiltered) {
|
|
327
266
|
this.root.changes.set(this, this.changes);
|
|
267
|
+
this.root.allChanges.set(this, this.allChanges);
|
|
328
268
|
}
|
|
329
269
|
if (this.isFiltered || this.isPartiallyFiltered) {
|
|
330
270
|
this.root.filteredChanges.set(this, this.filteredChanges);
|
|
331
271
|
this.root.allFilteredChanges.set(this, this.filteredChanges);
|
|
332
272
|
}
|
|
333
|
-
else {
|
|
334
|
-
this.root.allChanges.set(this, this.allChanges);
|
|
335
|
-
}
|
|
336
273
|
this.ensureRefId();
|
|
337
|
-
this.forEachChild(
|
|
338
|
-
changeTree.setParent(
|
|
274
|
+
this.forEachChild((changeTree, atIndex) => {
|
|
275
|
+
changeTree.setParent(this.ref, root, atIndex);
|
|
339
276
|
});
|
|
340
|
-
}
|
|
341
|
-
|
|
342
|
-
var _this = this;
|
|
277
|
+
}
|
|
278
|
+
forEachChild(callback) {
|
|
343
279
|
//
|
|
344
280
|
// assign same parent on child structures
|
|
345
281
|
//
|
|
346
282
|
if (Metadata.isValidInstance(this.ref)) {
|
|
347
|
-
|
|
283
|
+
const metadata = this.ref['constructor'][Symbol.metadata];
|
|
348
284
|
// FIXME: need to iterate over parent metadata instead.
|
|
349
|
-
for (
|
|
350
|
-
|
|
285
|
+
for (const field in metadata) {
|
|
286
|
+
const value = this.ref[field];
|
|
351
287
|
if (value && value[$changes]) {
|
|
352
288
|
callback(value[$changes], metadata[field].index);
|
|
353
289
|
}
|
|
@@ -355,29 +291,26 @@
|
|
|
355
291
|
}
|
|
356
292
|
else if (typeof (this.ref) === "object") {
|
|
357
293
|
// MapSchema / ArraySchema, etc.
|
|
358
|
-
this.ref.forEach(
|
|
294
|
+
this.ref.forEach((value, key) => {
|
|
359
295
|
if (Metadata.isValidInstance(value)) {
|
|
360
|
-
callback(value[$changes],
|
|
296
|
+
callback(value[$changes], this.ref[$changes].indexes[key]);
|
|
361
297
|
}
|
|
362
298
|
});
|
|
363
299
|
}
|
|
364
|
-
}
|
|
365
|
-
|
|
366
|
-
var _b;
|
|
300
|
+
}
|
|
301
|
+
operation(op) {
|
|
367
302
|
this.changes.set(--this.currentOperationIndex, op);
|
|
368
|
-
|
|
369
|
-
}
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
var isFiltered = this.isFiltered || (metadata && metadata[metadata[index]].tag !== undefined);
|
|
375
|
-
var changeSet = (isFiltered)
|
|
303
|
+
this.root?.changes.set(this, this.changes);
|
|
304
|
+
}
|
|
305
|
+
change(index, operation = exports.OPERATION.ADD) {
|
|
306
|
+
const metadata = this.ref['constructor'][Symbol.metadata];
|
|
307
|
+
const isFiltered = this.isFiltered || (metadata && metadata[metadata[index]].tag !== undefined);
|
|
308
|
+
const changeSet = (isFiltered)
|
|
376
309
|
? this.filteredChanges
|
|
377
310
|
: this.changes;
|
|
378
|
-
|
|
311
|
+
const previousOperation = changeSet.get(index);
|
|
379
312
|
if (!previousOperation || previousOperation === exports.OPERATION.DELETE) {
|
|
380
|
-
|
|
313
|
+
const op = (!previousOperation)
|
|
381
314
|
? operation
|
|
382
315
|
: (previousOperation === exports.OPERATION.DELETE)
|
|
383
316
|
? exports.OPERATION.DELETE_AND_ADD
|
|
@@ -389,32 +322,30 @@
|
|
|
389
322
|
//
|
|
390
323
|
if (isFiltered) {
|
|
391
324
|
this.allFilteredChanges.set(index, exports.OPERATION.ADD);
|
|
392
|
-
|
|
325
|
+
this.root?.filteredChanges.set(this, this.filteredChanges);
|
|
393
326
|
}
|
|
394
327
|
else {
|
|
395
328
|
this.allChanges.set(index, exports.OPERATION.ADD);
|
|
396
|
-
|
|
329
|
+
this.root?.changes.set(this, this.changes);
|
|
397
330
|
}
|
|
398
|
-
}
|
|
399
|
-
|
|
331
|
+
}
|
|
332
|
+
shiftChangeIndexes(shiftIndex) {
|
|
400
333
|
//
|
|
401
334
|
// Used only during:
|
|
402
335
|
//
|
|
403
336
|
// - ArraySchema#unshift()
|
|
404
337
|
//
|
|
405
|
-
|
|
338
|
+
const changeSet = (this.isFiltered)
|
|
406
339
|
? this.filteredChanges
|
|
407
340
|
: this.changes;
|
|
408
|
-
|
|
341
|
+
const changeSetEntries = Array.from(changeSet.entries());
|
|
409
342
|
changeSet.clear();
|
|
410
343
|
// Re-insert each entry with the shifted index
|
|
411
|
-
for (
|
|
412
|
-
var _b = changeSetEntries_1[_i], index = _b[0], op = _b[1];
|
|
344
|
+
for (const [index, op] of changeSetEntries) {
|
|
413
345
|
changeSet.set(index + shiftIndex, op);
|
|
414
346
|
}
|
|
415
|
-
}
|
|
416
|
-
|
|
417
|
-
if (startIndex === void 0) { startIndex = 0; }
|
|
347
|
+
}
|
|
348
|
+
shiftAllChangeIndexes(shiftIndex, startIndex = 0) {
|
|
418
349
|
//
|
|
419
350
|
// Used only during:
|
|
420
351
|
//
|
|
@@ -427,37 +358,32 @@
|
|
|
427
358
|
else {
|
|
428
359
|
this._shiftAllChangeIndexes(shiftIndex, startIndex, this.allChanges);
|
|
429
360
|
}
|
|
430
|
-
}
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
Array.from(allChangeSet.entries()).forEach(function (_b) {
|
|
434
|
-
var index = _b[0], op = _b[1];
|
|
435
|
-
// console.log('shiftAllChangeIndexes', index >= startIndex, { index, op, shiftIndex, startIndex })
|
|
361
|
+
}
|
|
362
|
+
_shiftAllChangeIndexes(shiftIndex, startIndex = 0, allChangeSet) {
|
|
363
|
+
Array.from(allChangeSet.entries()).forEach(([index, op]) => {
|
|
436
364
|
if (index >= startIndex) {
|
|
437
365
|
allChangeSet.delete(index);
|
|
438
366
|
allChangeSet.set(index + shiftIndex, op);
|
|
439
367
|
}
|
|
440
368
|
});
|
|
441
|
-
}
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
var metadata = this.ref['constructor'][Symbol.metadata];
|
|
446
|
-
var isFiltered = this.isFiltered || (metadata && metadata[metadata[index]].tag !== undefined);
|
|
369
|
+
}
|
|
370
|
+
indexedOperation(index, operation, allChangesIndex = index) {
|
|
371
|
+
const metadata = this.ref['constructor'][Symbol.metadata];
|
|
372
|
+
const isFiltered = this.isFiltered || (metadata && metadata[metadata[index]].tag !== undefined);
|
|
447
373
|
if (isFiltered) {
|
|
448
374
|
this.allFilteredChanges.set(allChangesIndex, exports.OPERATION.ADD);
|
|
449
375
|
this.filteredChanges.set(index, operation);
|
|
450
|
-
|
|
376
|
+
this.root?.filteredChanges.set(this, this.filteredChanges);
|
|
451
377
|
}
|
|
452
378
|
else {
|
|
453
379
|
this.allChanges.set(allChangesIndex, exports.OPERATION.ADD);
|
|
454
380
|
this.changes.set(index, operation);
|
|
455
|
-
|
|
381
|
+
this.root?.changes.set(this, this.changes);
|
|
456
382
|
}
|
|
457
|
-
}
|
|
458
|
-
|
|
383
|
+
}
|
|
384
|
+
getType(index) {
|
|
459
385
|
if (Metadata.isValidInstance(this.ref)) {
|
|
460
|
-
|
|
386
|
+
const metadata = this.ref['constructor'][Symbol.metadata];
|
|
461
387
|
return metadata[metadata[index]].type;
|
|
462
388
|
}
|
|
463
389
|
else {
|
|
@@ -469,41 +395,37 @@
|
|
|
469
395
|
//
|
|
470
396
|
return this.ref[$childType];
|
|
471
397
|
}
|
|
472
|
-
}
|
|
473
|
-
|
|
474
|
-
var _b;
|
|
398
|
+
}
|
|
399
|
+
getChange(index) {
|
|
475
400
|
// TODO: optimize this. avoid checking against multiple instances
|
|
476
|
-
return
|
|
477
|
-
}
|
|
401
|
+
return this.changes.get(index) ?? this.filteredChanges.get(index);
|
|
402
|
+
}
|
|
478
403
|
//
|
|
479
404
|
// used during `.encode()`
|
|
480
405
|
//
|
|
481
|
-
|
|
482
|
-
if (isEncodeAll === void 0) { isEncodeAll = false; }
|
|
406
|
+
getValue(index, isEncodeAll = false) {
|
|
483
407
|
//
|
|
484
408
|
// `isEncodeAll` param is only used by ArraySchema
|
|
485
409
|
//
|
|
486
410
|
return this.ref[$getByIndex](index, isEncodeAll);
|
|
487
|
-
}
|
|
488
|
-
|
|
489
|
-
var _b, _c, _d;
|
|
490
|
-
if (allChangesIndex === void 0) { allChangesIndex = index; }
|
|
411
|
+
}
|
|
412
|
+
delete(index, operation, allChangesIndex = index) {
|
|
491
413
|
if (index === undefined) {
|
|
492
414
|
try {
|
|
493
|
-
throw new Error(
|
|
415
|
+
throw new Error(`@colyseus/schema ${this.ref.constructor.name}: trying to delete non-existing index '${index}'`);
|
|
494
416
|
}
|
|
495
417
|
catch (e) {
|
|
496
418
|
console.warn(e);
|
|
497
419
|
}
|
|
498
420
|
return;
|
|
499
421
|
}
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
422
|
+
const metadata = this.ref['constructor'][Symbol.metadata];
|
|
423
|
+
const isFiltered = this.isFiltered || (metadata && metadata[metadata[index]].tag !== undefined);
|
|
424
|
+
const changeSet = (isFiltered)
|
|
503
425
|
? this.filteredChanges
|
|
504
426
|
: this.changes;
|
|
505
|
-
|
|
506
|
-
changeSet.set(index, operation
|
|
427
|
+
const previousValue = this.getValue(index);
|
|
428
|
+
changeSet.set(index, operation ?? exports.OPERATION.DELETE);
|
|
507
429
|
// remove `root` reference
|
|
508
430
|
if (previousValue && previousValue[$changes]) {
|
|
509
431
|
previousValue[$changes].root = undefined;
|
|
@@ -517,37 +439,33 @@
|
|
|
517
439
|
//
|
|
518
440
|
// (the property descriptors should NOT be used at decoding time. only at encoding time.)
|
|
519
441
|
//
|
|
520
|
-
|
|
442
|
+
this.root?.remove(previousValue[$changes]);
|
|
521
443
|
}
|
|
522
444
|
//
|
|
523
445
|
// FIXME: this is looking a bit ugly (and repeated from `.change()`)
|
|
524
446
|
//
|
|
525
447
|
if (isFiltered) {
|
|
526
|
-
|
|
448
|
+
this.root?.filteredChanges.set(this, this.filteredChanges);
|
|
527
449
|
this.allFilteredChanges.delete(allChangesIndex);
|
|
528
450
|
}
|
|
529
451
|
else {
|
|
530
|
-
|
|
452
|
+
this.root?.changes.set(this, this.changes);
|
|
531
453
|
this.allChanges.delete(allChangesIndex);
|
|
532
454
|
}
|
|
533
|
-
}
|
|
534
|
-
|
|
535
|
-
var _b, _c;
|
|
455
|
+
}
|
|
456
|
+
endEncode() {
|
|
536
457
|
this.changes.clear();
|
|
537
|
-
|
|
458
|
+
this.ref[$onEncodeEnd]?.();
|
|
538
459
|
// Not a new instance anymore
|
|
539
460
|
delete this[$isNew];
|
|
540
|
-
}
|
|
541
|
-
|
|
542
|
-
var _this = this;
|
|
543
|
-
var _b, _c;
|
|
544
|
-
if (discardAll === void 0) { discardAll = false; }
|
|
461
|
+
}
|
|
462
|
+
discard(discardAll = false) {
|
|
545
463
|
//
|
|
546
464
|
// > MapSchema:
|
|
547
465
|
// Remove cached key to ensure ADD operations is unsed instead of
|
|
548
466
|
// REPLACE in case same key is used on next patches.
|
|
549
467
|
//
|
|
550
|
-
|
|
468
|
+
this.ref[$onEncodeEnd]?.();
|
|
551
469
|
this.changes.clear();
|
|
552
470
|
this.filteredChanges.clear();
|
|
553
471
|
// reset operation index
|
|
@@ -556,46 +474,40 @@
|
|
|
556
474
|
this.allChanges.clear();
|
|
557
475
|
this.allFilteredChanges.clear();
|
|
558
476
|
// remove children references
|
|
559
|
-
this.forEachChild(
|
|
477
|
+
this.forEachChild((changeTree, _) => this.root?.remove(changeTree));
|
|
560
478
|
}
|
|
561
|
-
}
|
|
479
|
+
}
|
|
562
480
|
/**
|
|
563
481
|
* Recursively discard all changes from this, and child structures.
|
|
564
482
|
*/
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
var value = _this.getValue(fieldIndex);
|
|
483
|
+
discardAll() {
|
|
484
|
+
this.changes.forEach((_, fieldIndex) => {
|
|
485
|
+
const value = this.getValue(fieldIndex);
|
|
569
486
|
if (value && value[$changes]) {
|
|
570
487
|
value[$changes].discardAll();
|
|
571
488
|
}
|
|
572
489
|
});
|
|
573
490
|
this.discard();
|
|
574
|
-
}
|
|
575
|
-
|
|
491
|
+
}
|
|
492
|
+
ensureRefId() {
|
|
576
493
|
// skip if refId is already set.
|
|
577
494
|
if (this.refId !== undefined) {
|
|
578
495
|
return;
|
|
579
496
|
}
|
|
580
497
|
this.refId = this.root.getNextUniqueId();
|
|
581
|
-
}
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
enumerable: false,
|
|
587
|
-
configurable: true
|
|
588
|
-
});
|
|
589
|
-
ChangeTree.prototype.checkIsFiltered = function (parent, parentIndex) {
|
|
590
|
-
var _b, _c, _d;
|
|
498
|
+
}
|
|
499
|
+
get changed() {
|
|
500
|
+
return this.changes.size > 0;
|
|
501
|
+
}
|
|
502
|
+
checkIsFiltered(parent, parentIndex) {
|
|
591
503
|
// Detect if current structure has "filters" declared
|
|
592
|
-
this.isPartiallyFiltered = (
|
|
504
|
+
this.isPartiallyFiltered = (this.ref['constructor']?.[Symbol.metadata]?.[-2] !== undefined);
|
|
593
505
|
// TODO: support "partially filtered", where the instance is visible, but only a field is not.
|
|
594
506
|
// Detect if parent has "filters" declared
|
|
595
507
|
while (parent && !this.isFiltered) {
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
508
|
+
const metadata = parent['constructor'][Symbol.metadata];
|
|
509
|
+
const fieldName = metadata?.[parentIndex];
|
|
510
|
+
const isParentOwned = metadata?.[fieldName]?.tag !== undefined;
|
|
599
511
|
this.isFiltered = isParentOwned || parent[$changes].isFiltered; // metadata?.[-2]
|
|
600
512
|
parent = parent[$changes].parent;
|
|
601
513
|
}
|
|
@@ -607,18 +519,16 @@
|
|
|
607
519
|
//
|
|
608
520
|
if (this.isFiltered && this.changes.size > 0) {
|
|
609
521
|
// swap changes reference
|
|
610
|
-
|
|
522
|
+
const changes = this.changes;
|
|
611
523
|
this.changes = this.filteredChanges;
|
|
612
524
|
this.filteredChanges = changes;
|
|
613
525
|
// swap "all changes" reference
|
|
614
|
-
|
|
526
|
+
const allFilteredChanges = this.allFilteredChanges;
|
|
615
527
|
this.allFilteredChanges = this.allChanges;
|
|
616
528
|
this.allChanges = allFilteredChanges;
|
|
617
529
|
}
|
|
618
|
-
}
|
|
619
|
-
|
|
620
|
-
}());
|
|
621
|
-
_a = $isNew;
|
|
530
|
+
}
|
|
531
|
+
}
|
|
622
532
|
|
|
623
533
|
/**
|
|
624
534
|
* Copyright (c) 2018 Endel Dreyer
|
|
@@ -646,12 +556,35 @@
|
|
|
646
556
|
* msgpack implementation highly based on notepack.io
|
|
647
557
|
* https://github.com/darrachequesne/notepack
|
|
648
558
|
*/
|
|
649
|
-
|
|
559
|
+
let textEncoder;
|
|
650
560
|
// @ts-ignore
|
|
651
561
|
try {
|
|
652
562
|
textEncoder = new TextEncoder();
|
|
653
563
|
}
|
|
654
564
|
catch (e) { }
|
|
565
|
+
const hasBufferByteLength = (typeof Buffer !== 'undefined' && Buffer.byteLength);
|
|
566
|
+
const utf8Length = (hasBufferByteLength)
|
|
567
|
+
? Buffer.byteLength // node
|
|
568
|
+
: function (str, _) {
|
|
569
|
+
var c = 0, length = 0;
|
|
570
|
+
for (var i = 0, l = str.length; i < l; i++) {
|
|
571
|
+
c = str.charCodeAt(i);
|
|
572
|
+
if (c < 0x80) {
|
|
573
|
+
length += 1;
|
|
574
|
+
}
|
|
575
|
+
else if (c < 0x800) {
|
|
576
|
+
length += 2;
|
|
577
|
+
}
|
|
578
|
+
else if (c < 0xd800 || c >= 0xe000) {
|
|
579
|
+
length += 3;
|
|
580
|
+
}
|
|
581
|
+
else {
|
|
582
|
+
i++;
|
|
583
|
+
length += 4;
|
|
584
|
+
}
|
|
585
|
+
}
|
|
586
|
+
return length;
|
|
587
|
+
};
|
|
655
588
|
function utf8Write(view, str, it) {
|
|
656
589
|
var c = 0;
|
|
657
590
|
for (var i = 0, l = str.length; i < l; i++) {
|
|
@@ -699,24 +632,24 @@
|
|
|
699
632
|
bytes[it.offset++] = (value >> 24) & 255;
|
|
700
633
|
}
|
|
701
634
|
function uint32$1(bytes, value, it) {
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
635
|
+
const b4 = value >> 24;
|
|
636
|
+
const b3 = value >> 16;
|
|
637
|
+
const b2 = value >> 8;
|
|
638
|
+
const b1 = value;
|
|
706
639
|
bytes[it.offset++] = b1 & 255;
|
|
707
640
|
bytes[it.offset++] = b2 & 255;
|
|
708
641
|
bytes[it.offset++] = b3 & 255;
|
|
709
642
|
bytes[it.offset++] = b4 & 255;
|
|
710
643
|
}
|
|
711
644
|
function int64$1(bytes, value, it) {
|
|
712
|
-
|
|
713
|
-
|
|
645
|
+
const high = Math.floor(value / Math.pow(2, 32));
|
|
646
|
+
const low = value >>> 0;
|
|
714
647
|
uint32$1(bytes, low, it);
|
|
715
648
|
uint32$1(bytes, high, it);
|
|
716
649
|
}
|
|
717
650
|
function uint64$1(bytes, value, it) {
|
|
718
|
-
|
|
719
|
-
|
|
651
|
+
const high = (value / Math.pow(2, 32)) >> 0;
|
|
652
|
+
const low = value >>> 0;
|
|
720
653
|
uint32$1(bytes, low, it);
|
|
721
654
|
uint32$1(bytes, high, it);
|
|
722
655
|
}
|
|
@@ -726,9 +659,9 @@
|
|
|
726
659
|
function float64$1(bytes, value, it) {
|
|
727
660
|
writeFloat64(bytes, value, it);
|
|
728
661
|
}
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
662
|
+
const _int32$1 = new Int32Array(2);
|
|
663
|
+
const _float32$1 = new Float32Array(_int32$1.buffer);
|
|
664
|
+
const _float64$1 = new Float64Array(_int32$1.buffer);
|
|
732
665
|
function writeFloat32(bytes, value, it) {
|
|
733
666
|
_float32$1[0] = value;
|
|
734
667
|
int32$1(bytes, _int32$1[0], it);
|
|
@@ -746,9 +679,8 @@
|
|
|
746
679
|
if (!value) {
|
|
747
680
|
value = "";
|
|
748
681
|
}
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
var size = 0;
|
|
682
|
+
let length = utf8Length(value, "utf8");
|
|
683
|
+
let size = 0;
|
|
752
684
|
// fixstr
|
|
753
685
|
if (length < 0x20) {
|
|
754
686
|
bytes[it.offset++] = length | 0xa0;
|
|
@@ -858,6 +790,7 @@
|
|
|
858
790
|
|
|
859
791
|
var encode = /*#__PURE__*/Object.freeze({
|
|
860
792
|
__proto__: null,
|
|
793
|
+
utf8Length: utf8Length,
|
|
861
794
|
utf8Write: utf8Write,
|
|
862
795
|
int8: int8$1,
|
|
863
796
|
uint8: uint8$1,
|
|
@@ -876,16 +809,11 @@
|
|
|
876
809
|
number: number$1
|
|
877
810
|
});
|
|
878
811
|
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
function EncodeSchemaError() {
|
|
882
|
-
return _super !== null && _super.apply(this, arguments) || this;
|
|
883
|
-
}
|
|
884
|
-
return EncodeSchemaError;
|
|
885
|
-
}(Error));
|
|
812
|
+
class EncodeSchemaError extends Error {
|
|
813
|
+
}
|
|
886
814
|
function assertType(value, type, klass, field) {
|
|
887
|
-
|
|
888
|
-
|
|
815
|
+
let typeofTarget;
|
|
816
|
+
let allowNull = false;
|
|
889
817
|
switch (type) {
|
|
890
818
|
case "number":
|
|
891
819
|
case "int8":
|
|
@@ -900,7 +828,7 @@
|
|
|
900
828
|
case "float64":
|
|
901
829
|
typeofTarget = "number";
|
|
902
830
|
if (isNaN(value)) {
|
|
903
|
-
console.log(
|
|
831
|
+
console.log(`trying to encode "NaN" in ${klass.constructor.name}#${field}`);
|
|
904
832
|
}
|
|
905
833
|
break;
|
|
906
834
|
case "string":
|
|
@@ -912,25 +840,25 @@
|
|
|
912
840
|
return;
|
|
913
841
|
}
|
|
914
842
|
if (typeof (value) !== typeofTarget && (!allowNull || (allowNull && value !== null))) {
|
|
915
|
-
|
|
916
|
-
throw new EncodeSchemaError(
|
|
843
|
+
let foundValue = `'${JSON.stringify(value)}'${(value && value.constructor && ` (${value.constructor.name})`) || ''}`;
|
|
844
|
+
throw new EncodeSchemaError(`a '${typeofTarget}' was expected, but ${foundValue} was provided in ${klass.constructor.name}#${field}`);
|
|
917
845
|
}
|
|
918
846
|
}
|
|
919
847
|
function assertInstanceType(value, type, klass, field) {
|
|
920
848
|
if (!(value instanceof type)) {
|
|
921
|
-
throw new EncodeSchemaError(
|
|
849
|
+
throw new EncodeSchemaError(`a '${type.name}' was expected, but '${value && value.constructor.name}' was provided in ${klass.constructor.name}#${field}`);
|
|
922
850
|
}
|
|
923
851
|
}
|
|
924
852
|
|
|
925
853
|
function encodePrimitiveType(type, bytes, value, klass, field, it) {
|
|
926
854
|
assertType(value, type, klass, field);
|
|
927
|
-
|
|
855
|
+
const encodeFunc = encode[type];
|
|
928
856
|
if (encodeFunc) {
|
|
929
857
|
encodeFunc(bytes, value, it);
|
|
930
858
|
// encodeFunc(bytes, value);
|
|
931
859
|
}
|
|
932
860
|
else {
|
|
933
|
-
throw new EncodeSchemaError(
|
|
861
|
+
throw new EncodeSchemaError(`a '${type}' was expected, but ${value} was provided in ${klass.constructor.name}#${field}`);
|
|
934
862
|
}
|
|
935
863
|
}
|
|
936
864
|
function encodeValue(encoder, bytes, ref, type, value, field, operation, it) {
|
|
@@ -957,7 +885,7 @@
|
|
|
957
885
|
//
|
|
958
886
|
// Custom type (MapSchema, ArraySchema, etc)
|
|
959
887
|
//
|
|
960
|
-
|
|
888
|
+
const definition = getType(Object.keys(type)[0]);
|
|
961
889
|
//
|
|
962
890
|
// ensure a ArraySchema has been provided
|
|
963
891
|
//
|
|
@@ -973,12 +901,12 @@
|
|
|
973
901
|
* Used for Schema instances.
|
|
974
902
|
* @private
|
|
975
903
|
*/
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
904
|
+
const encodeSchemaOperation = function (encoder, bytes, changeTree, index, operation, it) {
|
|
905
|
+
const ref = changeTree.ref;
|
|
906
|
+
const metadata = ref['constructor'][Symbol.metadata];
|
|
907
|
+
const field = metadata[index];
|
|
908
|
+
const type = metadata[field].type;
|
|
909
|
+
const value = ref[field];
|
|
982
910
|
// "compress" field index + operation
|
|
983
911
|
bytes[it.offset++] = (index | operation) & 255;
|
|
984
912
|
// Do not encode value for DELETE operations
|
|
@@ -992,8 +920,8 @@
|
|
|
992
920
|
* Used for collections (MapSchema, CollectionSchema, SetSchema)
|
|
993
921
|
* @private
|
|
994
922
|
*/
|
|
995
|
-
|
|
996
|
-
|
|
923
|
+
const encodeKeyValueOperation = function (encoder, bytes, changeTree, field, operation, it) {
|
|
924
|
+
const ref = changeTree.ref;
|
|
997
925
|
// encode operation
|
|
998
926
|
bytes[it.offset++] = operation & 255;
|
|
999
927
|
// custom operations
|
|
@@ -1014,12 +942,12 @@
|
|
|
1014
942
|
//
|
|
1015
943
|
// MapSchema dynamic key
|
|
1016
944
|
//
|
|
1017
|
-
|
|
945
|
+
const dynamicIndex = changeTree.ref['$indexes'].get(field);
|
|
1018
946
|
string$1(bytes, dynamicIndex, it);
|
|
1019
947
|
}
|
|
1020
948
|
}
|
|
1021
|
-
|
|
1022
|
-
|
|
949
|
+
const type = changeTree.getType(field);
|
|
950
|
+
const value = changeTree.getValue(field);
|
|
1023
951
|
// TODO: inline this function call small performance gain
|
|
1024
952
|
encodeValue(encoder, bytes, ref, type, value, field, operation, it);
|
|
1025
953
|
};
|
|
@@ -1027,15 +955,15 @@
|
|
|
1027
955
|
* Used for collections (MapSchema, ArraySchema, etc.)
|
|
1028
956
|
* @private
|
|
1029
957
|
*/
|
|
1030
|
-
|
|
1031
|
-
|
|
958
|
+
const encodeArray = function (encoder, bytes, changeTree, field, operation, it, isEncodeAll, hasView) {
|
|
959
|
+
const ref = changeTree.ref;
|
|
1032
960
|
if (hasView &&
|
|
1033
961
|
operation === exports.OPERATION.DELETE &&
|
|
1034
962
|
typeof (changeTree.getType(field)) !== "string") {
|
|
1035
963
|
// encode delete by refId (array of schemas)
|
|
1036
964
|
bytes[it.offset++] = exports.OPERATION.DELETE_BY_REFID;
|
|
1037
|
-
|
|
1038
|
-
|
|
965
|
+
const value = ref['tmpItems'][field];
|
|
966
|
+
const refId = value[$changes].refId;
|
|
1039
967
|
number$1(bytes, refId, it);
|
|
1040
968
|
return;
|
|
1041
969
|
}
|
|
@@ -1051,8 +979,8 @@
|
|
|
1051
979
|
if (operation === exports.OPERATION.DELETE) {
|
|
1052
980
|
return;
|
|
1053
981
|
}
|
|
1054
|
-
|
|
1055
|
-
|
|
982
|
+
const type = changeTree.getType(field);
|
|
983
|
+
const value = changeTree.getValue(field, isEncodeAll);
|
|
1056
984
|
// console.log("encodeArray -> ", {
|
|
1057
985
|
// ref: changeTree.ref.constructor.name,
|
|
1058
986
|
// field,
|
|
@@ -1086,9 +1014,9 @@
|
|
|
1086
1014
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
1087
1015
|
* SOFTWARE
|
|
1088
1016
|
*/
|
|
1089
|
-
function utf8Read(bytes,
|
|
1017
|
+
function utf8Read(bytes, it, length) {
|
|
1090
1018
|
var string = '', chr = 0;
|
|
1091
|
-
for (var i = offset, end = offset + length; i < end; i++) {
|
|
1019
|
+
for (var i = it.offset, end = it.offset + length; i < end; i++) {
|
|
1092
1020
|
var byte = bytes[i];
|
|
1093
1021
|
if ((byte & 0x80) === 0x00) {
|
|
1094
1022
|
string += String.fromCharCode(byte);
|
|
@@ -1123,6 +1051,7 @@
|
|
|
1123
1051
|
// (do not throw error to avoid server/client from crashing due to hack attemps)
|
|
1124
1052
|
// throw new Error('Invalid byte ' + byte.toString(16));
|
|
1125
1053
|
}
|
|
1054
|
+
it.offset += length;
|
|
1126
1055
|
return string;
|
|
1127
1056
|
}
|
|
1128
1057
|
function int8(bytes, it) {
|
|
@@ -1150,18 +1079,18 @@
|
|
|
1150
1079
|
return readFloat64(bytes, it);
|
|
1151
1080
|
}
|
|
1152
1081
|
function int64(bytes, it) {
|
|
1153
|
-
|
|
1154
|
-
|
|
1082
|
+
const low = uint32(bytes, it);
|
|
1083
|
+
const high = int32(bytes, it) * Math.pow(2, 32);
|
|
1155
1084
|
return high + low;
|
|
1156
1085
|
}
|
|
1157
1086
|
function uint64(bytes, it) {
|
|
1158
|
-
|
|
1159
|
-
|
|
1087
|
+
const low = uint32(bytes, it);
|
|
1088
|
+
const high = uint32(bytes, it) * Math.pow(2, 32);
|
|
1160
1089
|
return high + low;
|
|
1161
1090
|
}
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1091
|
+
const _int32 = new Int32Array(2);
|
|
1092
|
+
const _float32 = new Float32Array(_int32.buffer);
|
|
1093
|
+
const _float64 = new Float64Array(_int32.buffer);
|
|
1165
1094
|
function readFloat32(bytes, it) {
|
|
1166
1095
|
_int32[0] = int32(bytes, it);
|
|
1167
1096
|
return _float32[0];
|
|
@@ -1175,8 +1104,8 @@
|
|
|
1175
1104
|
return uint8(bytes, it) > 0;
|
|
1176
1105
|
}
|
|
1177
1106
|
function string(bytes, it) {
|
|
1178
|
-
|
|
1179
|
-
|
|
1107
|
+
const prefix = bytes[it.offset++];
|
|
1108
|
+
let length;
|
|
1180
1109
|
if (prefix < 0xc0) {
|
|
1181
1110
|
// fixstr
|
|
1182
1111
|
length = prefix & 0x1f;
|
|
@@ -1190,12 +1119,10 @@
|
|
|
1190
1119
|
else if (prefix === 0xdb) {
|
|
1191
1120
|
length = uint32(bytes, it);
|
|
1192
1121
|
}
|
|
1193
|
-
|
|
1194
|
-
it.offset += length;
|
|
1195
|
-
return value;
|
|
1122
|
+
return utf8Read(bytes, it, length);
|
|
1196
1123
|
}
|
|
1197
1124
|
function stringCheck(bytes, it) {
|
|
1198
|
-
|
|
1125
|
+
const prefix = bytes[it.offset];
|
|
1199
1126
|
return (
|
|
1200
1127
|
// fixstr
|
|
1201
1128
|
(prefix < 0xc0 && prefix > 0xa0) ||
|
|
@@ -1207,7 +1134,7 @@
|
|
|
1207
1134
|
prefix === 0xdb);
|
|
1208
1135
|
}
|
|
1209
1136
|
function number(bytes, it) {
|
|
1210
|
-
|
|
1137
|
+
const prefix = bytes[it.offset++];
|
|
1211
1138
|
if (prefix < 0x80) {
|
|
1212
1139
|
// positive fixint
|
|
1213
1140
|
return prefix;
|
|
@@ -1258,7 +1185,7 @@
|
|
|
1258
1185
|
}
|
|
1259
1186
|
}
|
|
1260
1187
|
function numberCheck(bytes, it) {
|
|
1261
|
-
|
|
1188
|
+
const prefix = bytes[it.offset];
|
|
1262
1189
|
// positive fixint - 0x00 - 0x7f
|
|
1263
1190
|
// float 32 - 0xca
|
|
1264
1191
|
// float 64 - 0xcb
|
|
@@ -1296,6 +1223,7 @@
|
|
|
1296
1223
|
|
|
1297
1224
|
var decode = /*#__PURE__*/Object.freeze({
|
|
1298
1225
|
__proto__: null,
|
|
1226
|
+
utf8Read: utf8Read,
|
|
1299
1227
|
int8: int8,
|
|
1300
1228
|
uint8: uint8,
|
|
1301
1229
|
int16: int16,
|
|
@@ -1317,14 +1245,14 @@
|
|
|
1317
1245
|
switchStructureCheck: switchStructureCheck
|
|
1318
1246
|
});
|
|
1319
1247
|
|
|
1320
|
-
|
|
1248
|
+
const DEFINITION_MISMATCH = -1;
|
|
1321
1249
|
function decodeValue(decoder, operation, ref, index, type, bytes, it, allChanges) {
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1250
|
+
const $root = decoder.root;
|
|
1251
|
+
const previousValue = ref[$getByIndex](index);
|
|
1252
|
+
let value;
|
|
1325
1253
|
if ((operation & exports.OPERATION.DELETE) === exports.OPERATION.DELETE) {
|
|
1326
1254
|
// Flag `refId` for garbage collection.
|
|
1327
|
-
|
|
1255
|
+
const previousRefId = $root.refIds.get(previousValue);
|
|
1328
1256
|
if (previousRefId !== undefined) {
|
|
1329
1257
|
$root.removeRef(previousRefId);
|
|
1330
1258
|
}
|
|
@@ -1351,10 +1279,10 @@
|
|
|
1351
1279
|
}
|
|
1352
1280
|
if (operation === exports.OPERATION.DELETE) ;
|
|
1353
1281
|
else if (Schema.is(type)) {
|
|
1354
|
-
|
|
1282
|
+
const refId = number(bytes, it);
|
|
1355
1283
|
value = $root.refs.get(refId);
|
|
1356
1284
|
if (previousValue) {
|
|
1357
|
-
|
|
1285
|
+
const previousRefId = $root.refIds.get(previousValue);
|
|
1358
1286
|
if (previousRefId &&
|
|
1359
1287
|
refId !== previousRefId &&
|
|
1360
1288
|
// FIXME: we may need to check for REPLACE operation as well
|
|
@@ -1363,7 +1291,7 @@
|
|
|
1363
1291
|
}
|
|
1364
1292
|
}
|
|
1365
1293
|
if ((operation & exports.OPERATION.ADD) === exports.OPERATION.ADD) {
|
|
1366
|
-
|
|
1294
|
+
const childType = decoder.getInstanceType(bytes, it, type);
|
|
1367
1295
|
if (!value) {
|
|
1368
1296
|
value = decoder.createInstanceOfType(childType);
|
|
1369
1297
|
}
|
|
@@ -1377,28 +1305,28 @@
|
|
|
1377
1305
|
value = decode[type](bytes, it);
|
|
1378
1306
|
}
|
|
1379
1307
|
else {
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
|
|
1308
|
+
const typeDef = getType(Object.keys(type)[0]);
|
|
1309
|
+
const refId = number(bytes, it);
|
|
1310
|
+
const valueRef = ($root.refs.has(refId))
|
|
1383
1311
|
? previousValue || $root.refs.get(refId)
|
|
1384
1312
|
: new typeDef.constructor();
|
|
1385
1313
|
value = valueRef.clone(true);
|
|
1386
1314
|
value[$childType] = Object.values(type)[0]; // cache childType for ArraySchema and MapSchema
|
|
1387
1315
|
if (previousValue) {
|
|
1388
|
-
|
|
1316
|
+
let previousRefId = $root.refIds.get(previousValue);
|
|
1389
1317
|
if (previousRefId !== undefined && refId !== previousRefId) {
|
|
1390
1318
|
$root.removeRef(previousRefId);
|
|
1391
1319
|
//
|
|
1392
1320
|
// enqueue onRemove if structure has been replaced.
|
|
1393
1321
|
//
|
|
1394
|
-
|
|
1395
|
-
|
|
1322
|
+
const entries = previousValue.entries();
|
|
1323
|
+
let iter;
|
|
1396
1324
|
while ((iter = entries.next()) && !iter.done) {
|
|
1397
|
-
|
|
1325
|
+
const [key, value] = iter.value;
|
|
1398
1326
|
// if value is a schema, remove its reference
|
|
1399
1327
|
// FIXME: not sure if this is necessary, add more tests to confirm
|
|
1400
|
-
if (typeof (
|
|
1401
|
-
previousRefId = $root.refIds.get(
|
|
1328
|
+
if (typeof (value) === "object") {
|
|
1329
|
+
previousRefId = $root.refIds.get(value);
|
|
1402
1330
|
$root.removeRef(previousRefId);
|
|
1403
1331
|
}
|
|
1404
1332
|
allChanges.push({
|
|
@@ -1407,45 +1335,45 @@
|
|
|
1407
1335
|
op: exports.OPERATION.DELETE,
|
|
1408
1336
|
field: key,
|
|
1409
1337
|
value: undefined,
|
|
1410
|
-
previousValue:
|
|
1338
|
+
previousValue: value,
|
|
1411
1339
|
});
|
|
1412
1340
|
}
|
|
1413
1341
|
}
|
|
1414
1342
|
}
|
|
1415
1343
|
$root.addRef(refId, value, (valueRef !== previousValue));
|
|
1416
1344
|
}
|
|
1417
|
-
return { value
|
|
1345
|
+
return { value, previousValue };
|
|
1418
1346
|
}
|
|
1419
|
-
|
|
1420
|
-
|
|
1421
|
-
|
|
1347
|
+
const decodeSchemaOperation = function (decoder, bytes, it, ref, allChanges) {
|
|
1348
|
+
const first_byte = bytes[it.offset++];
|
|
1349
|
+
const metadata = ref['constructor'][Symbol.metadata];
|
|
1422
1350
|
// "compressed" index + operation
|
|
1423
|
-
|
|
1424
|
-
|
|
1351
|
+
const operation = (first_byte >> 6) << 6;
|
|
1352
|
+
const index = first_byte % (operation || 255);
|
|
1425
1353
|
// skip early if field is not defined
|
|
1426
|
-
|
|
1354
|
+
const field = metadata[index];
|
|
1427
1355
|
if (field === undefined) {
|
|
1428
1356
|
return DEFINITION_MISMATCH;
|
|
1429
1357
|
}
|
|
1430
|
-
|
|
1358
|
+
const { value, previousValue } = decodeValue(decoder, operation, ref, index, metadata[field].type, bytes, it, allChanges);
|
|
1431
1359
|
if (value !== null && value !== undefined) {
|
|
1432
1360
|
ref[field] = value;
|
|
1433
1361
|
}
|
|
1434
1362
|
// add change
|
|
1435
1363
|
if (previousValue !== value) {
|
|
1436
1364
|
allChanges.push({
|
|
1437
|
-
ref
|
|
1365
|
+
ref,
|
|
1438
1366
|
refId: decoder.currentRefId,
|
|
1439
1367
|
op: operation,
|
|
1440
1368
|
field: field,
|
|
1441
|
-
value
|
|
1442
|
-
previousValue
|
|
1369
|
+
value,
|
|
1370
|
+
previousValue,
|
|
1443
1371
|
});
|
|
1444
1372
|
}
|
|
1445
1373
|
};
|
|
1446
|
-
|
|
1374
|
+
const decodeKeyValueOperation = function (decoder, bytes, it, ref, allChanges) {
|
|
1447
1375
|
// "uncompressed" index + operation (array/map items)
|
|
1448
|
-
|
|
1376
|
+
const operation = bytes[it.offset++];
|
|
1449
1377
|
if (operation === exports.OPERATION.CLEAR) {
|
|
1450
1378
|
//
|
|
1451
1379
|
// When decoding:
|
|
@@ -1456,9 +1384,9 @@
|
|
|
1456
1384
|
ref.clear();
|
|
1457
1385
|
return;
|
|
1458
1386
|
}
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
|
-
|
|
1387
|
+
const index = number(bytes, it);
|
|
1388
|
+
const type = ref[$childType];
|
|
1389
|
+
let dynamicIndex;
|
|
1462
1390
|
if ((operation & exports.OPERATION.ADD) === exports.OPERATION.ADD) { // ADD or DELETE_AND_ADD
|
|
1463
1391
|
if (typeof (ref['set']) === "function") {
|
|
1464
1392
|
dynamicIndex = string(bytes, it); // MapSchema
|
|
@@ -1472,7 +1400,7 @@
|
|
|
1472
1400
|
// get dynamic index from "ref"
|
|
1473
1401
|
dynamicIndex = ref['getIndex'](index);
|
|
1474
1402
|
}
|
|
1475
|
-
|
|
1403
|
+
const { value, previousValue } = decodeValue(decoder, operation, ref, index, type, bytes, it, allChanges);
|
|
1476
1404
|
if (value !== null && value !== undefined) {
|
|
1477
1405
|
if (typeof (ref['set']) === "function") {
|
|
1478
1406
|
// MapSchema
|
|
@@ -1484,28 +1412,28 @@
|
|
|
1484
1412
|
}
|
|
1485
1413
|
else if (typeof (ref['add']) === "function") {
|
|
1486
1414
|
// CollectionSchema && SetSchema
|
|
1487
|
-
|
|
1488
|
-
if (typeof (
|
|
1489
|
-
ref['setIndex'](
|
|
1415
|
+
const index = ref.add(value);
|
|
1416
|
+
if (typeof (index) === "number") {
|
|
1417
|
+
ref['setIndex'](index, index);
|
|
1490
1418
|
}
|
|
1491
1419
|
}
|
|
1492
1420
|
}
|
|
1493
1421
|
// add change
|
|
1494
1422
|
if (previousValue !== value) {
|
|
1495
1423
|
allChanges.push({
|
|
1496
|
-
ref
|
|
1424
|
+
ref,
|
|
1497
1425
|
refId: decoder.currentRefId,
|
|
1498
1426
|
op: operation,
|
|
1499
1427
|
field: "", // FIXME: remove this
|
|
1500
|
-
dynamicIndex
|
|
1501
|
-
value
|
|
1502
|
-
previousValue
|
|
1428
|
+
dynamicIndex,
|
|
1429
|
+
value,
|
|
1430
|
+
previousValue,
|
|
1503
1431
|
});
|
|
1504
1432
|
}
|
|
1505
1433
|
};
|
|
1506
|
-
|
|
1434
|
+
const decodeArray = function (decoder, bytes, it, ref, allChanges) {
|
|
1507
1435
|
// "uncompressed" index + operation (array/map items)
|
|
1508
|
-
|
|
1436
|
+
const operation = bytes[it.offset++];
|
|
1509
1437
|
if (operation === exports.OPERATION.CLEAR) {
|
|
1510
1438
|
//
|
|
1511
1439
|
// When decoding:
|
|
@@ -1518,25 +1446,25 @@
|
|
|
1518
1446
|
}
|
|
1519
1447
|
else if (operation === exports.OPERATION.DELETE_BY_REFID) {
|
|
1520
1448
|
// TODO: refactor here, try to follow same flow as below
|
|
1521
|
-
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
ref[$deleteByIndex](
|
|
1449
|
+
const refId = number(bytes, it);
|
|
1450
|
+
const previousValue = decoder.root.refs.get(refId);
|
|
1451
|
+
const index = ref.findIndex((value) => value === previousValue);
|
|
1452
|
+
ref[$deleteByIndex](index);
|
|
1525
1453
|
allChanges.push({
|
|
1526
|
-
ref
|
|
1454
|
+
ref,
|
|
1527
1455
|
refId: decoder.currentRefId,
|
|
1528
1456
|
op: exports.OPERATION.DELETE,
|
|
1529
1457
|
field: "", // FIXME: remove this
|
|
1530
|
-
dynamicIndex:
|
|
1458
|
+
dynamicIndex: index,
|
|
1531
1459
|
value: undefined,
|
|
1532
|
-
previousValue
|
|
1460
|
+
previousValue,
|
|
1533
1461
|
});
|
|
1534
1462
|
return;
|
|
1535
1463
|
}
|
|
1536
|
-
|
|
1537
|
-
|
|
1538
|
-
|
|
1539
|
-
|
|
1464
|
+
const index = number(bytes, it);
|
|
1465
|
+
const type = ref[$childType];
|
|
1466
|
+
let dynamicIndex = index;
|
|
1467
|
+
const { value, previousValue } = decodeValue(decoder, operation, ref, index, type, bytes, it, allChanges);
|
|
1540
1468
|
if (value !== null && value !== undefined &&
|
|
1541
1469
|
value !== previousValue // avoid setting same value twice (if index === 0 it will result in a "unshift" for ArraySchema)
|
|
1542
1470
|
) {
|
|
@@ -1546,20 +1474,21 @@
|
|
|
1546
1474
|
// add change
|
|
1547
1475
|
if (previousValue !== value) {
|
|
1548
1476
|
allChanges.push({
|
|
1549
|
-
ref
|
|
1477
|
+
ref,
|
|
1550
1478
|
refId: decoder.currentRefId,
|
|
1551
1479
|
op: operation,
|
|
1552
1480
|
field: "", // FIXME: remove this
|
|
1553
|
-
dynamicIndex
|
|
1554
|
-
value
|
|
1555
|
-
previousValue
|
|
1481
|
+
dynamicIndex,
|
|
1482
|
+
value,
|
|
1483
|
+
previousValue,
|
|
1556
1484
|
});
|
|
1557
1485
|
}
|
|
1558
1486
|
};
|
|
1559
1487
|
|
|
1560
|
-
var
|
|
1561
|
-
|
|
1562
|
-
|
|
1488
|
+
var _a$4, _b$4;
|
|
1489
|
+
const DEFAULT_SORT = (a, b) => {
|
|
1490
|
+
const A = a.toString();
|
|
1491
|
+
const B = b.toString();
|
|
1563
1492
|
if (A < B)
|
|
1564
1493
|
return -1;
|
|
1565
1494
|
else if (A > B)
|
|
@@ -1567,13 +1496,33 @@
|
|
|
1567
1496
|
else
|
|
1568
1497
|
return 0;
|
|
1569
1498
|
};
|
|
1570
|
-
|
|
1571
|
-
|
|
1572
|
-
|
|
1573
|
-
|
|
1574
|
-
|
|
1575
|
-
|
|
1576
|
-
|
|
1499
|
+
class ArraySchema {
|
|
1500
|
+
static { this[_a$4] = encodeArray; }
|
|
1501
|
+
static { this[_b$4] = decodeArray; }
|
|
1502
|
+
/**
|
|
1503
|
+
* Determine if a property must be filtered.
|
|
1504
|
+
* - If returns false, the property is NOT going to be encoded.
|
|
1505
|
+
* - If returns true, the property is going to be encoded.
|
|
1506
|
+
*
|
|
1507
|
+
* Encoding with "filters" happens in two steps:
|
|
1508
|
+
* - First, the encoder iterates over all "not owned" properties and encodes them.
|
|
1509
|
+
* - Then, the encoder iterates over all "owned" properties per instance and encodes them.
|
|
1510
|
+
*/
|
|
1511
|
+
static [(_a$4 = $encoder, _b$4 = $decoder, $filter)](ref, index, view) {
|
|
1512
|
+
// console.log("ArraSchema[$filter] VIEW??", !view)
|
|
1513
|
+
return (!view ||
|
|
1514
|
+
typeof (ref[$childType]) === "string" ||
|
|
1515
|
+
// view.items.has(ref[$getByIndex](index)[$changes])
|
|
1516
|
+
view.items.has(ref['tmpItems'][index]?.[$changes]));
|
|
1517
|
+
}
|
|
1518
|
+
static is(type) {
|
|
1519
|
+
return (
|
|
1520
|
+
// type format: ["string"]
|
|
1521
|
+
Array.isArray(type) ||
|
|
1522
|
+
// type format: { array: "string" }
|
|
1523
|
+
(type['array'] !== undefined));
|
|
1524
|
+
}
|
|
1525
|
+
constructor(...items) {
|
|
1577
1526
|
this.items = [];
|
|
1578
1527
|
this.tmpItems = [];
|
|
1579
1528
|
this.deletedIndexes = {};
|
|
@@ -1583,18 +1532,18 @@
|
|
|
1583
1532
|
writable: true,
|
|
1584
1533
|
configurable: true,
|
|
1585
1534
|
});
|
|
1586
|
-
|
|
1587
|
-
get:
|
|
1535
|
+
const proxy = new Proxy(this, {
|
|
1536
|
+
get: (obj, prop) => {
|
|
1588
1537
|
if (typeof (prop) !== "symbol" &&
|
|
1589
1538
|
!isNaN(prop) // https://stackoverflow.com/a/175787/892698
|
|
1590
1539
|
) {
|
|
1591
|
-
return
|
|
1540
|
+
return this.items[prop];
|
|
1592
1541
|
}
|
|
1593
1542
|
else {
|
|
1594
1543
|
return Reflect.get(obj, prop);
|
|
1595
1544
|
}
|
|
1596
1545
|
},
|
|
1597
|
-
set:
|
|
1546
|
+
set: (obj, key, setValue) => {
|
|
1598
1547
|
if (typeof (key) !== "symbol" && !isNaN(key)) {
|
|
1599
1548
|
if (setValue === undefined || setValue === null) {
|
|
1600
1549
|
obj.$deleteAt(key);
|
|
@@ -1603,26 +1552,26 @@
|
|
|
1603
1552
|
if (setValue[$changes]) {
|
|
1604
1553
|
if (obj.items[key] !== undefined) {
|
|
1605
1554
|
if (setValue[$changes][$isNew]) {
|
|
1606
|
-
|
|
1555
|
+
this[$changes].indexedOperation(Number(key), exports.OPERATION.MOVE_AND_ADD);
|
|
1607
1556
|
}
|
|
1608
1557
|
else {
|
|
1609
1558
|
if ((obj[$changes].getChange(Number(key)) & exports.OPERATION.DELETE) === exports.OPERATION.DELETE) {
|
|
1610
|
-
|
|
1559
|
+
this[$changes].indexedOperation(Number(key), exports.OPERATION.DELETE_AND_MOVE);
|
|
1611
1560
|
}
|
|
1612
1561
|
else {
|
|
1613
|
-
|
|
1562
|
+
this[$changes].indexedOperation(Number(key), exports.OPERATION.MOVE);
|
|
1614
1563
|
}
|
|
1615
1564
|
}
|
|
1616
1565
|
}
|
|
1617
1566
|
else if (setValue[$changes][$isNew]) {
|
|
1618
|
-
|
|
1567
|
+
this[$changes].indexedOperation(Number(key), exports.OPERATION.ADD);
|
|
1619
1568
|
}
|
|
1620
1569
|
}
|
|
1621
1570
|
else {
|
|
1622
1571
|
obj.$changeAt(Number(key), setValue);
|
|
1623
1572
|
}
|
|
1624
|
-
|
|
1625
|
-
|
|
1573
|
+
this.items[key] = setValue;
|
|
1574
|
+
this.tmpItems[key] = setValue;
|
|
1626
1575
|
}
|
|
1627
1576
|
return true;
|
|
1628
1577
|
}
|
|
@@ -1630,7 +1579,7 @@
|
|
|
1630
1579
|
return Reflect.set(obj, key, setValue);
|
|
1631
1580
|
}
|
|
1632
1581
|
},
|
|
1633
|
-
deleteProperty:
|
|
1582
|
+
deleteProperty: (obj, prop) => {
|
|
1634
1583
|
if (typeof (prop) === "number") {
|
|
1635
1584
|
obj.$deleteAt(prop);
|
|
1636
1585
|
}
|
|
@@ -1639,9 +1588,9 @@
|
|
|
1639
1588
|
}
|
|
1640
1589
|
return true;
|
|
1641
1590
|
},
|
|
1642
|
-
has:
|
|
1591
|
+
has: (obj, key) => {
|
|
1643
1592
|
if (typeof (key) !== "symbol" && !isNaN(Number(key))) {
|
|
1644
|
-
return Reflect.has(
|
|
1593
|
+
return Reflect.has(this.items, key);
|
|
1645
1594
|
}
|
|
1646
1595
|
return Reflect.has(obj, key);
|
|
1647
1596
|
}
|
|
@@ -1650,82 +1599,48 @@
|
|
|
1650
1599
|
this.push.apply(this, items);
|
|
1651
1600
|
return proxy;
|
|
1652
1601
|
}
|
|
1653
|
-
|
|
1654
|
-
|
|
1655
|
-
|
|
1656
|
-
|
|
1657
|
-
|
|
1658
|
-
|
|
1659
|
-
|
|
1660
|
-
|
|
1661
|
-
|
|
1662
|
-
|
|
1663
|
-
|
|
1664
|
-
|
|
1665
|
-
return
|
|
1666
|
-
|
|
1667
|
-
|
|
1668
|
-
|
|
1669
|
-
|
|
1670
|
-
ArraySchema.is = function (type) {
|
|
1671
|
-
return (
|
|
1672
|
-
// type format: ["string"]
|
|
1673
|
-
Array.isArray(type) ||
|
|
1674
|
-
// type format: { array: "string" }
|
|
1675
|
-
(type['array'] !== undefined));
|
|
1676
|
-
};
|
|
1677
|
-
Object.defineProperty(ArraySchema.prototype, "length", {
|
|
1678
|
-
get: function () {
|
|
1679
|
-
return this.items.length;
|
|
1680
|
-
},
|
|
1681
|
-
set: function (newLength) {
|
|
1682
|
-
if (newLength === 0) {
|
|
1683
|
-
this.clear();
|
|
1684
|
-
}
|
|
1685
|
-
else if (newLength < this.items.length) {
|
|
1686
|
-
this.splice(newLength, this.length - newLength);
|
|
1687
|
-
}
|
|
1688
|
-
else {
|
|
1689
|
-
console.warn("ArraySchema: can't set .length to a higher value than its length.");
|
|
1690
|
-
}
|
|
1691
|
-
},
|
|
1692
|
-
enumerable: false,
|
|
1693
|
-
configurable: true
|
|
1694
|
-
});
|
|
1695
|
-
ArraySchema.prototype.push = function () {
|
|
1696
|
-
var _this = this;
|
|
1697
|
-
var values = [];
|
|
1698
|
-
for (var _i = 0; _i < arguments.length; _i++) {
|
|
1699
|
-
values[_i] = arguments[_i];
|
|
1700
|
-
}
|
|
1701
|
-
var length = this.tmpItems.length;
|
|
1702
|
-
values.forEach(function (value, i) {
|
|
1703
|
-
var _c;
|
|
1602
|
+
set length(newLength) {
|
|
1603
|
+
if (newLength === 0) {
|
|
1604
|
+
this.clear();
|
|
1605
|
+
}
|
|
1606
|
+
else if (newLength < this.items.length) {
|
|
1607
|
+
this.splice(newLength, this.length - newLength);
|
|
1608
|
+
}
|
|
1609
|
+
else {
|
|
1610
|
+
console.warn("ArraySchema: can't set .length to a higher value than its length.");
|
|
1611
|
+
}
|
|
1612
|
+
}
|
|
1613
|
+
get length() {
|
|
1614
|
+
return this.items.length;
|
|
1615
|
+
}
|
|
1616
|
+
push(...values) {
|
|
1617
|
+
let length = this.tmpItems.length;
|
|
1618
|
+
values.forEach((value, i) => {
|
|
1704
1619
|
// skip null values
|
|
1705
1620
|
if (value === undefined || value === null) {
|
|
1706
1621
|
return;
|
|
1707
1622
|
}
|
|
1708
|
-
|
|
1709
|
-
changeTree.indexedOperation(length, exports.OPERATION.ADD,
|
|
1623
|
+
const changeTree = this[$changes];
|
|
1624
|
+
changeTree.indexedOperation(length, exports.OPERATION.ADD, this.items.length);
|
|
1710
1625
|
// changeTree.indexes[length] = length;
|
|
1711
|
-
|
|
1712
|
-
|
|
1626
|
+
this.items.push(value);
|
|
1627
|
+
this.tmpItems.push(value);
|
|
1713
1628
|
//
|
|
1714
1629
|
// set value's parent after the value is set
|
|
1715
1630
|
// (to avoid encoding "refId" operations before parent's "ADD" operation)
|
|
1716
1631
|
//
|
|
1717
|
-
|
|
1632
|
+
value[$changes]?.setParent(this, changeTree.root, length);
|
|
1718
1633
|
length++;
|
|
1719
1634
|
});
|
|
1720
1635
|
return length;
|
|
1721
|
-
}
|
|
1636
|
+
}
|
|
1722
1637
|
/**
|
|
1723
1638
|
* Removes the last element from an array and returns it.
|
|
1724
1639
|
*/
|
|
1725
|
-
|
|
1726
|
-
|
|
1640
|
+
pop() {
|
|
1641
|
+
let index = -1;
|
|
1727
1642
|
// find last non-undefined index
|
|
1728
|
-
for (
|
|
1643
|
+
for (let i = this.tmpItems.length - 1; i >= 0; i--) {
|
|
1729
1644
|
// if (this.tmpItems[i] !== undefined) {
|
|
1730
1645
|
if (this.deletedIndexes[i] !== true) {
|
|
1731
1646
|
index = i;
|
|
@@ -1739,16 +1654,15 @@
|
|
|
1739
1654
|
// this.tmpItems[index] = undefined;
|
|
1740
1655
|
this.deletedIndexes[index] = true;
|
|
1741
1656
|
return this.items.pop();
|
|
1742
|
-
}
|
|
1743
|
-
|
|
1657
|
+
}
|
|
1658
|
+
at(index) {
|
|
1744
1659
|
// Allow negative indexing from the end
|
|
1745
1660
|
if (index < 0)
|
|
1746
1661
|
index += this.length;
|
|
1747
1662
|
return this.items[index];
|
|
1748
|
-
}
|
|
1663
|
+
}
|
|
1749
1664
|
// encoding only
|
|
1750
|
-
|
|
1751
|
-
var _c, _d, _e, _f;
|
|
1665
|
+
$changeAt(index, value) {
|
|
1752
1666
|
if (value === undefined || value === null) {
|
|
1753
1667
|
console.error("ArraySchema items cannot be null nor undefined; Use `deleteAt(index)` instead.");
|
|
1754
1668
|
return;
|
|
@@ -1757,21 +1671,21 @@
|
|
|
1757
1671
|
if (this.items[index] === value) {
|
|
1758
1672
|
return;
|
|
1759
1673
|
}
|
|
1760
|
-
|
|
1761
|
-
|
|
1674
|
+
const changeTree = this[$changes];
|
|
1675
|
+
const operation = changeTree.indexes?.[index]?.op ?? exports.OPERATION.ADD;
|
|
1762
1676
|
changeTree.change(index, operation);
|
|
1763
1677
|
//
|
|
1764
1678
|
// set value's parent after the value is set
|
|
1765
1679
|
// (to avoid encoding "refId" operations before parent's "ADD" operation)
|
|
1766
1680
|
//
|
|
1767
|
-
|
|
1768
|
-
}
|
|
1681
|
+
value[$changes]?.setParent(this, changeTree.root, index);
|
|
1682
|
+
}
|
|
1769
1683
|
// encoding only
|
|
1770
|
-
|
|
1684
|
+
$deleteAt(index, operation) {
|
|
1771
1685
|
this[$changes].delete(index, operation);
|
|
1772
|
-
}
|
|
1686
|
+
}
|
|
1773
1687
|
// decoding only
|
|
1774
|
-
|
|
1688
|
+
$setAt(index, value, operation) {
|
|
1775
1689
|
if (index === 0 &&
|
|
1776
1690
|
operation === exports.OPERATION.ADD &&
|
|
1777
1691
|
this.items[index] !== undefined) {
|
|
@@ -1785,17 +1699,16 @@
|
|
|
1785
1699
|
else {
|
|
1786
1700
|
this.items[index] = value;
|
|
1787
1701
|
}
|
|
1788
|
-
}
|
|
1789
|
-
|
|
1702
|
+
}
|
|
1703
|
+
clear() {
|
|
1790
1704
|
// skip if already clear
|
|
1791
1705
|
if (this.items.length === 0) {
|
|
1792
1706
|
return;
|
|
1793
1707
|
}
|
|
1794
1708
|
// discard previous operations.
|
|
1795
|
-
|
|
1709
|
+
const changeTree = this[$changes];
|
|
1796
1710
|
// discard children
|
|
1797
|
-
changeTree.forEachChild(
|
|
1798
|
-
var _c, _d, _e;
|
|
1711
|
+
changeTree.forEachChild((changeTree, _) => {
|
|
1799
1712
|
changeTree.discard(true);
|
|
1800
1713
|
//
|
|
1801
1714
|
// TODO: add tests with instance sharing + .clear()
|
|
@@ -1803,70 +1716,64 @@
|
|
|
1803
1716
|
//
|
|
1804
1717
|
// TODO: do not use [$changes] at decoding time.
|
|
1805
1718
|
//
|
|
1806
|
-
|
|
1807
|
-
|
|
1808
|
-
|
|
1719
|
+
changeTree.root?.changes.delete(changeTree);
|
|
1720
|
+
changeTree.root?.allChanges.delete(changeTree);
|
|
1721
|
+
changeTree.root?.allFilteredChanges.delete(changeTree);
|
|
1809
1722
|
});
|
|
1810
1723
|
changeTree.discard(true);
|
|
1811
1724
|
changeTree.operation(exports.OPERATION.CLEAR);
|
|
1812
1725
|
this.items.length = 0;
|
|
1813
1726
|
this.tmpItems.length = 0;
|
|
1814
|
-
}
|
|
1727
|
+
}
|
|
1815
1728
|
/**
|
|
1816
1729
|
* Combines two or more arrays.
|
|
1817
1730
|
* @param items Additional items to add to the end of array1.
|
|
1818
1731
|
*/
|
|
1819
1732
|
// @ts-ignore
|
|
1820
|
-
|
|
1821
|
-
|
|
1822
|
-
|
|
1823
|
-
for (var _i = 0; _i < arguments.length; _i++) {
|
|
1824
|
-
items[_i] = arguments[_i];
|
|
1825
|
-
}
|
|
1826
|
-
return new (ArraySchema.bind.apply(ArraySchema, __spreadArray([void 0], (_c = this.items).concat.apply(_c, items), false)))();
|
|
1827
|
-
};
|
|
1733
|
+
concat(...items) {
|
|
1734
|
+
return new ArraySchema(...this.items.concat(...items));
|
|
1735
|
+
}
|
|
1828
1736
|
/**
|
|
1829
1737
|
* Adds all the elements of an array separated by the specified separator string.
|
|
1830
1738
|
* @param separator A string used to separate one element of an array from the next in the resulting String. If omitted, the array elements are separated with a comma.
|
|
1831
1739
|
*/
|
|
1832
|
-
|
|
1740
|
+
join(separator) {
|
|
1833
1741
|
return this.items.join(separator);
|
|
1834
|
-
}
|
|
1742
|
+
}
|
|
1835
1743
|
/**
|
|
1836
1744
|
* Reverses the elements in an Array.
|
|
1837
1745
|
*/
|
|
1838
1746
|
// @ts-ignore
|
|
1839
|
-
|
|
1747
|
+
reverse() {
|
|
1840
1748
|
this[$changes].operation(exports.OPERATION.REVERSE);
|
|
1841
1749
|
this.items.reverse();
|
|
1842
1750
|
this.tmpItems.reverse();
|
|
1843
1751
|
return this;
|
|
1844
|
-
}
|
|
1752
|
+
}
|
|
1845
1753
|
/**
|
|
1846
1754
|
* Removes the first element from an array and returns it.
|
|
1847
1755
|
*/
|
|
1848
|
-
|
|
1849
|
-
var _this = this;
|
|
1756
|
+
shift() {
|
|
1850
1757
|
if (this.items.length === 0) {
|
|
1851
1758
|
return undefined;
|
|
1852
1759
|
}
|
|
1853
1760
|
// const index = Number(Object.keys(changeTree.indexes)[0]);
|
|
1854
|
-
|
|
1855
|
-
|
|
1761
|
+
const index = this.tmpItems.findIndex((item, i) => item === this.items[0]);
|
|
1762
|
+
const changeTree = this[$changes];
|
|
1856
1763
|
changeTree.delete(index);
|
|
1857
1764
|
changeTree.shiftAllChangeIndexes(-1, index);
|
|
1858
1765
|
return this.items.shift();
|
|
1859
|
-
}
|
|
1766
|
+
}
|
|
1860
1767
|
/**
|
|
1861
1768
|
* Returns a section of an array.
|
|
1862
1769
|
* @param start The beginning of the specified portion of the array.
|
|
1863
1770
|
* @param end The end of the specified portion of the array. This is exclusive of the element at the index 'end'.
|
|
1864
1771
|
*/
|
|
1865
|
-
|
|
1866
|
-
|
|
1867
|
-
sliced.push
|
|
1772
|
+
slice(start, end) {
|
|
1773
|
+
const sliced = new ArraySchema();
|
|
1774
|
+
sliced.push(...this.items.slice(start, end));
|
|
1868
1775
|
return sliced;
|
|
1869
|
-
}
|
|
1776
|
+
}
|
|
1870
1777
|
/**
|
|
1871
1778
|
* Sorts an array.
|
|
1872
1779
|
* @param compareFn Function used to determine the order of the elements. It is expected to return
|
|
@@ -1876,53 +1783,45 @@
|
|
|
1876
1783
|
* [11,2,22,1].sort((a, b) => a - b)
|
|
1877
1784
|
* ```
|
|
1878
1785
|
*/
|
|
1879
|
-
|
|
1880
|
-
|
|
1881
|
-
|
|
1882
|
-
var sortedItems = this.items.sort(compareFn);
|
|
1786
|
+
sort(compareFn = DEFAULT_SORT) {
|
|
1787
|
+
const changeTree = this[$changes];
|
|
1788
|
+
const sortedItems = this.items.sort(compareFn);
|
|
1883
1789
|
// wouldn't OPERATION.MOVE make more sense here?
|
|
1884
|
-
sortedItems.forEach(
|
|
1790
|
+
sortedItems.forEach((_, i) => changeTree.change(i, exports.OPERATION.REPLACE));
|
|
1885
1791
|
this.tmpItems.sort(compareFn);
|
|
1886
1792
|
return this;
|
|
1887
|
-
}
|
|
1793
|
+
}
|
|
1888
1794
|
/**
|
|
1889
1795
|
* Removes elements from an array and, if necessary, inserts new elements in their place, returning the deleted elements.
|
|
1890
1796
|
* @param start The zero-based location in the array from which to start removing elements.
|
|
1891
1797
|
* @param deleteCount The number of elements to remove.
|
|
1892
1798
|
* @param insertItems Elements to insert into the array in place of the deleted elements.
|
|
1893
1799
|
*/
|
|
1894
|
-
|
|
1895
|
-
|
|
1896
|
-
|
|
1897
|
-
|
|
1898
|
-
var insertItems = [];
|
|
1899
|
-
for (var _i = 2; _i < arguments.length; _i++) {
|
|
1900
|
-
insertItems[_i - 2] = arguments[_i];
|
|
1901
|
-
}
|
|
1902
|
-
var changeTree = this[$changes];
|
|
1903
|
-
var tmpItemsLength = this.tmpItems.length;
|
|
1904
|
-
var insertCount = insertItems.length;
|
|
1800
|
+
splice(start, deleteCount = this.items.length - start, ...insertItems) {
|
|
1801
|
+
const changeTree = this[$changes];
|
|
1802
|
+
const tmpItemsLength = this.tmpItems.length;
|
|
1803
|
+
const insertCount = insertItems.length;
|
|
1905
1804
|
// build up-to-date list of indexes, excluding removed values.
|
|
1906
|
-
|
|
1907
|
-
for (
|
|
1805
|
+
const indexes = [];
|
|
1806
|
+
for (let i = 0; i < tmpItemsLength; i++) {
|
|
1908
1807
|
// if (this.tmpItems[i] !== undefined) {
|
|
1909
1808
|
if (this.deletedIndexes[i] !== true) {
|
|
1910
1809
|
indexes.push(i);
|
|
1911
1810
|
}
|
|
1912
1811
|
}
|
|
1913
1812
|
// delete operations at correct index
|
|
1914
|
-
for (
|
|
1915
|
-
|
|
1813
|
+
for (let i = start; i < start + deleteCount; i++) {
|
|
1814
|
+
const index = indexes[i];
|
|
1916
1815
|
changeTree.delete(index);
|
|
1917
1816
|
// this.tmpItems[index] = undefined;
|
|
1918
1817
|
this.deletedIndexes[index] = true;
|
|
1919
1818
|
}
|
|
1920
1819
|
// force insert operations
|
|
1921
|
-
for (
|
|
1922
|
-
|
|
1820
|
+
for (let i = 0; i < insertCount; i++) {
|
|
1821
|
+
const addIndex = indexes[start] + i;
|
|
1923
1822
|
changeTree.indexedOperation(addIndex, exports.OPERATION.ADD);
|
|
1924
1823
|
// set value's parent/root
|
|
1925
|
-
|
|
1824
|
+
insertItems[i][$changes]?.setParent(this, changeTree.root, addIndex);
|
|
1926
1825
|
}
|
|
1927
1826
|
//
|
|
1928
1827
|
// delete exceeding indexes from "allChanges"
|
|
@@ -1931,19 +1830,14 @@
|
|
|
1931
1830
|
if (deleteCount > insertCount) {
|
|
1932
1831
|
changeTree.shiftAllChangeIndexes(-(deleteCount - insertCount), indexes[start + insertCount]);
|
|
1933
1832
|
}
|
|
1934
|
-
return
|
|
1935
|
-
}
|
|
1833
|
+
return this.items.splice(start, deleteCount, ...insertItems);
|
|
1834
|
+
}
|
|
1936
1835
|
/**
|
|
1937
1836
|
* Inserts new elements at the start of an array.
|
|
1938
1837
|
* @param items Elements to insert at the start of the Array.
|
|
1939
1838
|
*/
|
|
1940
|
-
|
|
1941
|
-
|
|
1942
|
-
var items = [];
|
|
1943
|
-
for (var _i = 0; _i < arguments.length; _i++) {
|
|
1944
|
-
items[_i] = arguments[_i];
|
|
1945
|
-
}
|
|
1946
|
-
var changeTree = this[$changes];
|
|
1839
|
+
unshift(...items) {
|
|
1840
|
+
const changeTree = this[$changes];
|
|
1947
1841
|
// shift indexes
|
|
1948
1842
|
changeTree.shiftChangeIndexes(items.length);
|
|
1949
1843
|
// new index
|
|
@@ -1954,29 +1848,28 @@
|
|
|
1954
1848
|
changeTree.allChanges.set(this.items.length, exports.OPERATION.ADD);
|
|
1955
1849
|
}
|
|
1956
1850
|
// FIXME: should we use OPERATION.MOVE here instead?
|
|
1957
|
-
items.forEach(
|
|
1851
|
+
items.forEach((_, index) => {
|
|
1958
1852
|
changeTree.change(index, exports.OPERATION.ADD);
|
|
1959
1853
|
});
|
|
1960
|
-
|
|
1961
|
-
return
|
|
1962
|
-
}
|
|
1854
|
+
this.tmpItems.unshift(...items);
|
|
1855
|
+
return this.items.unshift(...items);
|
|
1856
|
+
}
|
|
1963
1857
|
/**
|
|
1964
1858
|
* Returns the index of the first occurrence of a value in an array.
|
|
1965
1859
|
* @param searchElement The value to locate in the array.
|
|
1966
1860
|
* @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the search starts at index 0.
|
|
1967
1861
|
*/
|
|
1968
|
-
|
|
1862
|
+
indexOf(searchElement, fromIndex) {
|
|
1969
1863
|
return this.items.indexOf(searchElement, fromIndex);
|
|
1970
|
-
}
|
|
1864
|
+
}
|
|
1971
1865
|
/**
|
|
1972
1866
|
* Returns the index of the last occurrence of a specified value in an array.
|
|
1973
1867
|
* @param searchElement The value to locate in the array.
|
|
1974
1868
|
* @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the search starts at the last index in the array.
|
|
1975
1869
|
*/
|
|
1976
|
-
|
|
1977
|
-
if (fromIndex === void 0) { fromIndex = this.length - 1; }
|
|
1870
|
+
lastIndexOf(searchElement, fromIndex = this.length - 1) {
|
|
1978
1871
|
return this.items.lastIndexOf(searchElement, fromIndex);
|
|
1979
|
-
}
|
|
1872
|
+
}
|
|
1980
1873
|
/**
|
|
1981
1874
|
* Determines whether all the members of an array satisfy the specified test.
|
|
1982
1875
|
* @param callbackfn A function that accepts up to three arguments. The every method calls
|
|
@@ -1985,9 +1878,9 @@
|
|
|
1985
1878
|
* @param thisArg An object to which the this keyword can refer in the callbackfn function.
|
|
1986
1879
|
* If thisArg is omitted, undefined is used as the this value.
|
|
1987
1880
|
*/
|
|
1988
|
-
|
|
1881
|
+
every(callbackfn, thisArg) {
|
|
1989
1882
|
return this.items.every(callbackfn, thisArg);
|
|
1990
|
-
}
|
|
1883
|
+
}
|
|
1991
1884
|
/**
|
|
1992
1885
|
* Determines whether the specified callback function returns true for any element of an array.
|
|
1993
1886
|
* @param callbackfn A function that accepts up to three arguments. The some method calls
|
|
@@ -1996,44 +1889,44 @@
|
|
|
1996
1889
|
* @param thisArg An object to which the this keyword can refer in the callbackfn function.
|
|
1997
1890
|
* If thisArg is omitted, undefined is used as the this value.
|
|
1998
1891
|
*/
|
|
1999
|
-
|
|
1892
|
+
some(callbackfn, thisArg) {
|
|
2000
1893
|
return this.items.some(callbackfn, thisArg);
|
|
2001
|
-
}
|
|
1894
|
+
}
|
|
2002
1895
|
/**
|
|
2003
1896
|
* Performs the specified action for each element in an array.
|
|
2004
1897
|
* @param callbackfn A function that accepts up to three arguments. forEach calls the callbackfn function one time for each element in the array.
|
|
2005
1898
|
* @param thisArg An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value.
|
|
2006
1899
|
*/
|
|
2007
|
-
|
|
1900
|
+
forEach(callbackfn, thisArg) {
|
|
2008
1901
|
return this.items.forEach(callbackfn, thisArg);
|
|
2009
|
-
}
|
|
1902
|
+
}
|
|
2010
1903
|
/**
|
|
2011
1904
|
* Calls a defined callback function on each element of an array, and returns an array that contains the results.
|
|
2012
1905
|
* @param callbackfn A function that accepts up to three arguments. The map method calls the callbackfn function one time for each element in the array.
|
|
2013
1906
|
* @param thisArg An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value.
|
|
2014
1907
|
*/
|
|
2015
|
-
|
|
1908
|
+
map(callbackfn, thisArg) {
|
|
2016
1909
|
return this.items.map(callbackfn, thisArg);
|
|
2017
|
-
}
|
|
2018
|
-
|
|
1910
|
+
}
|
|
1911
|
+
filter(callbackfn, thisArg) {
|
|
2019
1912
|
return this.items.filter(callbackfn, thisArg);
|
|
2020
|
-
}
|
|
1913
|
+
}
|
|
2021
1914
|
/**
|
|
2022
1915
|
* Calls the specified callback function for all the elements in an array. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
|
|
2023
1916
|
* @param callbackfn A function that accepts up to four arguments. The reduce method calls the callbackfn function one time for each element in the array.
|
|
2024
1917
|
* @param initialValue If initialValue is specified, it is used as the initial value to start the accumulation. The first call to the callbackfn function provides this value as an argument instead of an array value.
|
|
2025
1918
|
*/
|
|
2026
|
-
|
|
1919
|
+
reduce(callbackfn, initialValue) {
|
|
2027
1920
|
return this.items.reduce(callbackfn, initialValue);
|
|
2028
|
-
}
|
|
1921
|
+
}
|
|
2029
1922
|
/**
|
|
2030
1923
|
* Calls the specified callback function for all the elements in an array, in descending order. The return value of the callback function is the accumulated result, and is provided as an argument in the next call to the callback function.
|
|
2031
1924
|
* @param callbackfn A function that accepts up to four arguments. The reduceRight method calls the callbackfn function one time for each element in the array.
|
|
2032
1925
|
* @param initialValue If initialValue is specified, it is used as the initial value to start the accumulation. The first call to the callbackfn function provides this value as an argument instead of an array value.
|
|
2033
1926
|
*/
|
|
2034
|
-
|
|
1927
|
+
reduceRight(callbackfn, initialValue) {
|
|
2035
1928
|
return this.items.reduceRight(callbackfn, initialValue);
|
|
2036
|
-
}
|
|
1929
|
+
}
|
|
2037
1930
|
/**
|
|
2038
1931
|
* Returns the value of the first element in the array where predicate is true, and undefined
|
|
2039
1932
|
* otherwise.
|
|
@@ -2043,9 +1936,9 @@
|
|
|
2043
1936
|
* @param thisArg If provided, it will be used as the this value for each invocation of
|
|
2044
1937
|
* predicate. If it is not provided, undefined is used instead.
|
|
2045
1938
|
*/
|
|
2046
|
-
|
|
1939
|
+
find(predicate, thisArg) {
|
|
2047
1940
|
return this.items.find(predicate, thisArg);
|
|
2048
|
-
}
|
|
1941
|
+
}
|
|
2049
1942
|
/**
|
|
2050
1943
|
* Returns the index of the first element in the array where predicate is true, and -1
|
|
2051
1944
|
* otherwise.
|
|
@@ -2055,9 +1948,9 @@
|
|
|
2055
1948
|
* @param thisArg If provided, it will be used as the this value for each invocation of
|
|
2056
1949
|
* predicate. If it is not provided, undefined is used instead.
|
|
2057
1950
|
*/
|
|
2058
|
-
|
|
1951
|
+
findIndex(predicate, thisArg) {
|
|
2059
1952
|
return this.items.findIndex(predicate, thisArg);
|
|
2060
|
-
}
|
|
1953
|
+
}
|
|
2061
1954
|
/**
|
|
2062
1955
|
* Returns the this object after filling the section identified by start and end with value
|
|
2063
1956
|
* @param value value to fill array section with
|
|
@@ -2066,12 +1959,12 @@
|
|
|
2066
1959
|
* @param end index to stop filling the array at. If end is negative, it is treated as
|
|
2067
1960
|
* length+end.
|
|
2068
1961
|
*/
|
|
2069
|
-
|
|
1962
|
+
fill(value, start, end) {
|
|
2070
1963
|
//
|
|
2071
1964
|
// TODO
|
|
2072
1965
|
//
|
|
2073
1966
|
throw new Error("ArraySchema#fill() not implemented");
|
|
2074
|
-
}
|
|
1967
|
+
}
|
|
2075
1968
|
/**
|
|
2076
1969
|
* Returns the this object after copying a section of the array identified by start and end
|
|
2077
1970
|
* to the same array starting at position target
|
|
@@ -2081,55 +1974,52 @@
|
|
|
2081
1974
|
* is treated as length+end.
|
|
2082
1975
|
* @param end If not specified, length of the this object is used as its default value.
|
|
2083
1976
|
*/
|
|
2084
|
-
|
|
1977
|
+
copyWithin(target, start, end) {
|
|
2085
1978
|
//
|
|
2086
1979
|
// TODO
|
|
2087
1980
|
//
|
|
2088
1981
|
throw new Error("ArraySchema#copyWithin() not implemented");
|
|
2089
|
-
}
|
|
1982
|
+
}
|
|
2090
1983
|
/**
|
|
2091
1984
|
* Returns a string representation of an array.
|
|
2092
1985
|
*/
|
|
2093
|
-
|
|
1986
|
+
toString() {
|
|
2094
1987
|
return this.items.toString();
|
|
2095
|
-
}
|
|
1988
|
+
}
|
|
2096
1989
|
/**
|
|
2097
1990
|
* Returns a string representation of an array. The elements are converted to string using their toLocalString methods.
|
|
2098
1991
|
*/
|
|
2099
|
-
|
|
1992
|
+
toLocaleString() {
|
|
2100
1993
|
return this.items.toLocaleString();
|
|
2101
|
-
}
|
|
1994
|
+
}
|
|
1995
|
+
;
|
|
2102
1996
|
/** Iterator */
|
|
2103
|
-
|
|
1997
|
+
[Symbol.iterator]() {
|
|
2104
1998
|
return this.items[Symbol.iterator]();
|
|
2105
|
-
}
|
|
2106
|
-
|
|
2107
|
-
|
|
2108
|
-
|
|
2109
|
-
},
|
|
2110
|
-
enumerable: false,
|
|
2111
|
-
configurable: true
|
|
2112
|
-
});
|
|
1999
|
+
}
|
|
2000
|
+
static get [Symbol.species]() {
|
|
2001
|
+
return ArraySchema;
|
|
2002
|
+
}
|
|
2113
2003
|
/**
|
|
2114
2004
|
* Returns an iterable of key, value pairs for every entry in the array
|
|
2115
2005
|
*/
|
|
2116
|
-
|
|
2006
|
+
entries() { return this.items.entries(); }
|
|
2117
2007
|
/**
|
|
2118
2008
|
* Returns an iterable of keys in the array
|
|
2119
2009
|
*/
|
|
2120
|
-
|
|
2010
|
+
keys() { return this.items.keys(); }
|
|
2121
2011
|
/**
|
|
2122
2012
|
* Returns an iterable of values in the array
|
|
2123
2013
|
*/
|
|
2124
|
-
|
|
2014
|
+
values() { return this.items.values(); }
|
|
2125
2015
|
/**
|
|
2126
2016
|
* Determines whether an array includes a certain element, returning true or false as appropriate.
|
|
2127
2017
|
* @param searchElement The element to search for.
|
|
2128
2018
|
* @param fromIndex The position in this array at which to begin searching for searchElement.
|
|
2129
2019
|
*/
|
|
2130
|
-
|
|
2020
|
+
includes(searchElement, fromIndex) {
|
|
2131
2021
|
return this.items.includes(searchElement, fromIndex);
|
|
2132
|
-
}
|
|
2022
|
+
}
|
|
2133
2023
|
//
|
|
2134
2024
|
// ES2022
|
|
2135
2025
|
//
|
|
@@ -2144,10 +2034,10 @@
|
|
|
2144
2034
|
* thisArg is omitted, undefined is used as the this value.
|
|
2145
2035
|
*/
|
|
2146
2036
|
// @ts-ignore
|
|
2147
|
-
|
|
2037
|
+
flatMap(callback, thisArg) {
|
|
2148
2038
|
// @ts-ignore
|
|
2149
2039
|
throw new Error("ArraySchema#flatMap() is not supported.");
|
|
2150
|
-
}
|
|
2040
|
+
}
|
|
2151
2041
|
/**
|
|
2152
2042
|
* Returns a new array with all sub-array elements concatenated into it recursively up to the
|
|
2153
2043
|
* specified depth.
|
|
@@ -2155,44 +2045,43 @@
|
|
|
2155
2045
|
* @param depth The maximum recursion depth
|
|
2156
2046
|
*/
|
|
2157
2047
|
// @ts-ignore
|
|
2158
|
-
|
|
2048
|
+
flat(depth) {
|
|
2159
2049
|
throw new Error("ArraySchema#flat() is not supported.");
|
|
2160
|
-
}
|
|
2161
|
-
|
|
2050
|
+
}
|
|
2051
|
+
findLast() {
|
|
2162
2052
|
// @ts-ignore
|
|
2163
2053
|
return this.items.findLast.apply(this.items, arguments);
|
|
2164
|
-
}
|
|
2165
|
-
|
|
2054
|
+
}
|
|
2055
|
+
findLastIndex(...args) {
|
|
2166
2056
|
// @ts-ignore
|
|
2167
2057
|
return this.items.findLastIndex.apply(this.items, arguments);
|
|
2168
|
-
}
|
|
2058
|
+
}
|
|
2169
2059
|
//
|
|
2170
2060
|
// ES2023
|
|
2171
2061
|
//
|
|
2172
|
-
|
|
2173
|
-
|
|
2062
|
+
with(index, value) {
|
|
2063
|
+
const copy = this.items.slice();
|
|
2174
2064
|
copy[index] = value;
|
|
2175
|
-
return new
|
|
2176
|
-
}
|
|
2177
|
-
|
|
2065
|
+
return new ArraySchema(...copy);
|
|
2066
|
+
}
|
|
2067
|
+
toReversed() {
|
|
2178
2068
|
return this.items.slice().reverse();
|
|
2179
|
-
}
|
|
2180
|
-
|
|
2069
|
+
}
|
|
2070
|
+
toSorted(compareFn) {
|
|
2181
2071
|
return this.items.slice().sort(compareFn);
|
|
2182
|
-
}
|
|
2072
|
+
}
|
|
2183
2073
|
// @ts-ignore
|
|
2184
|
-
|
|
2074
|
+
toSpliced(start, deleteCount, ...items) {
|
|
2185
2075
|
// @ts-ignore
|
|
2186
2076
|
return this.items.toSpliced.apply(copy, arguments);
|
|
2187
|
-
}
|
|
2188
|
-
|
|
2077
|
+
}
|
|
2078
|
+
[($getByIndex)](index, isEncodeAll = false) {
|
|
2189
2079
|
//
|
|
2190
2080
|
// TODO: avoid unecessary `this.tmpItems` check during decoding.
|
|
2191
2081
|
//
|
|
2192
2082
|
// ENCODING uses `this.tmpItems` (or `this.items` if `isEncodeAll` is true)
|
|
2193
2083
|
// DECODING uses `this.items`
|
|
2194
2084
|
//
|
|
2195
|
-
if (isEncodeAll === void 0) { isEncodeAll = false; }
|
|
2196
2085
|
return (isEncodeAll)
|
|
2197
2086
|
? this.items[index]
|
|
2198
2087
|
: this.deletedIndexes[index]
|
|
@@ -2201,63 +2090,79 @@
|
|
|
2201
2090
|
// return (isEncodeAll)
|
|
2202
2091
|
// ? this.items[index]
|
|
2203
2092
|
// : this.tmpItems[index] ?? this.items[index];
|
|
2204
|
-
}
|
|
2205
|
-
|
|
2093
|
+
}
|
|
2094
|
+
[$deleteByIndex](index) {
|
|
2206
2095
|
this.items[index] = undefined;
|
|
2207
|
-
}
|
|
2208
|
-
|
|
2096
|
+
}
|
|
2097
|
+
[$onEncodeEnd]() {
|
|
2209
2098
|
this.tmpItems = this.items.slice();
|
|
2210
2099
|
this.deletedIndexes = {};
|
|
2211
|
-
}
|
|
2212
|
-
|
|
2213
|
-
this.items = this.items.filter(
|
|
2214
|
-
}
|
|
2215
|
-
|
|
2100
|
+
}
|
|
2101
|
+
[$onDecodeEnd]() {
|
|
2102
|
+
this.items = this.items.filter((item) => item !== undefined);
|
|
2103
|
+
}
|
|
2104
|
+
toArray() {
|
|
2216
2105
|
return this.items.slice(0);
|
|
2217
|
-
}
|
|
2218
|
-
|
|
2219
|
-
return this.toArray().map(
|
|
2106
|
+
}
|
|
2107
|
+
toJSON() {
|
|
2108
|
+
return this.toArray().map((value) => {
|
|
2220
2109
|
return (typeof (value['toJSON']) === "function")
|
|
2221
2110
|
? value['toJSON']()
|
|
2222
2111
|
: value;
|
|
2223
2112
|
});
|
|
2224
|
-
}
|
|
2113
|
+
}
|
|
2225
2114
|
//
|
|
2226
2115
|
// Decoding utilities
|
|
2227
2116
|
//
|
|
2228
|
-
|
|
2229
|
-
|
|
2117
|
+
clone(isDecoding) {
|
|
2118
|
+
let cloned;
|
|
2230
2119
|
if (isDecoding) {
|
|
2231
2120
|
cloned = new ArraySchema();
|
|
2232
|
-
cloned.push
|
|
2121
|
+
cloned.push(...this.items);
|
|
2233
2122
|
}
|
|
2234
2123
|
else {
|
|
2235
|
-
cloned = new
|
|
2124
|
+
cloned = new ArraySchema(...this.map(item => ((item[$changes])
|
|
2236
2125
|
? item.clone()
|
|
2237
|
-
: item)
|
|
2126
|
+
: item)));
|
|
2238
2127
|
}
|
|
2239
2128
|
return cloned;
|
|
2240
|
-
}
|
|
2241
|
-
|
|
2242
|
-
|
|
2243
|
-
ArraySchema[_b] = decodeArray;
|
|
2244
|
-
return ArraySchema;
|
|
2245
|
-
}());
|
|
2129
|
+
}
|
|
2130
|
+
;
|
|
2131
|
+
}
|
|
2246
2132
|
registerType("array", { constructor: ArraySchema });
|
|
2247
2133
|
|
|
2248
|
-
var
|
|
2249
|
-
|
|
2250
|
-
|
|
2251
|
-
|
|
2134
|
+
var _a$3, _b$3;
|
|
2135
|
+
class MapSchema {
|
|
2136
|
+
static { this[_a$3] = encodeKeyValueOperation; }
|
|
2137
|
+
static { this[_b$3] = decodeKeyValueOperation; }
|
|
2138
|
+
/**
|
|
2139
|
+
* Determine if a property must be filtered.
|
|
2140
|
+
* - If returns false, the property is NOT going to be encoded.
|
|
2141
|
+
* - If returns true, the property is going to be encoded.
|
|
2142
|
+
*
|
|
2143
|
+
* Encoding with "filters" happens in two steps:
|
|
2144
|
+
* - First, the encoder iterates over all "not owned" properties and encodes them.
|
|
2145
|
+
* - Then, the encoder iterates over all "owned" properties per instance and encodes them.
|
|
2146
|
+
*/
|
|
2147
|
+
static [(_a$3 = $encoder, _b$3 = $decoder, $filter)](ref, index, view) {
|
|
2148
|
+
return (!view ||
|
|
2149
|
+
typeof (ref[$childType]) === "string" ||
|
|
2150
|
+
view.items.has(ref[$getByIndex](index)[$changes]));
|
|
2151
|
+
}
|
|
2152
|
+
static is(type) {
|
|
2153
|
+
return type['map'] !== undefined;
|
|
2154
|
+
}
|
|
2155
|
+
constructor(initialValues) {
|
|
2156
|
+
this.$items = new Map();
|
|
2252
2157
|
this.$indexes = new Map();
|
|
2253
2158
|
this[$changes] = new ChangeTree(this);
|
|
2254
2159
|
if (initialValues) {
|
|
2255
2160
|
if (initialValues instanceof Map ||
|
|
2256
2161
|
initialValues instanceof MapSchema) {
|
|
2257
|
-
initialValues.forEach(
|
|
2162
|
+
initialValues.forEach((v, k) => this.set(k, v));
|
|
2258
2163
|
}
|
|
2259
2164
|
else {
|
|
2260
|
-
for (
|
|
2165
|
+
for (const k in initialValues) {
|
|
2261
2166
|
this.set(k, initialValues[k]);
|
|
2262
2167
|
}
|
|
2263
2168
|
}
|
|
@@ -2269,53 +2174,27 @@
|
|
|
2269
2174
|
configurable: true,
|
|
2270
2175
|
});
|
|
2271
2176
|
}
|
|
2272
|
-
/**
|
|
2273
|
-
* Determine if a property must be filtered.
|
|
2274
|
-
* - If returns false, the property is NOT going to be encoded.
|
|
2275
|
-
* - If returns true, the property is going to be encoded.
|
|
2276
|
-
*
|
|
2277
|
-
* Encoding with "filters" happens in two steps:
|
|
2278
|
-
* - First, the encoder iterates over all "not owned" properties and encodes them.
|
|
2279
|
-
* - Then, the encoder iterates over all "owned" properties per instance and encodes them.
|
|
2280
|
-
*/
|
|
2281
|
-
MapSchema[(_a = $encoder, _b = $decoder, $filter)] = function (ref, index, view) {
|
|
2282
|
-
return (!view ||
|
|
2283
|
-
typeof (ref[$childType]) === "string" ||
|
|
2284
|
-
view.items.has(ref[$getByIndex](index)[$changes]));
|
|
2285
|
-
};
|
|
2286
|
-
MapSchema.is = function (type) {
|
|
2287
|
-
return type['map'] !== undefined;
|
|
2288
|
-
};
|
|
2289
2177
|
/** Iterator */
|
|
2290
|
-
|
|
2291
|
-
|
|
2292
|
-
|
|
2293
|
-
|
|
2294
|
-
configurable: true
|
|
2295
|
-
});
|
|
2296
|
-
Object.defineProperty(MapSchema, Symbol.species, {
|
|
2297
|
-
get: function () { return MapSchema; },
|
|
2298
|
-
enumerable: false,
|
|
2299
|
-
configurable: true
|
|
2300
|
-
});
|
|
2301
|
-
MapSchema.prototype.set = function (key, value) {
|
|
2302
|
-
var _c;
|
|
2178
|
+
[Symbol.iterator]() { return this.$items[Symbol.iterator](); }
|
|
2179
|
+
get [Symbol.toStringTag]() { return this.$items[Symbol.toStringTag]; }
|
|
2180
|
+
static get [Symbol.species]() { return MapSchema; }
|
|
2181
|
+
set(key, value) {
|
|
2303
2182
|
if (value === undefined || value === null) {
|
|
2304
|
-
throw new Error(
|
|
2183
|
+
throw new Error(`MapSchema#set('${key}', ${value}): trying to set ${value} value on '${key}'.`);
|
|
2305
2184
|
}
|
|
2306
2185
|
// Force "key" as string
|
|
2307
2186
|
// See: https://github.com/colyseus/colyseus/issues/561#issuecomment-1646733468
|
|
2308
2187
|
key = key.toString();
|
|
2309
|
-
|
|
2188
|
+
const changeTree = this[$changes];
|
|
2310
2189
|
// get "index" for this value.
|
|
2311
|
-
|
|
2312
|
-
|
|
2190
|
+
const isReplace = typeof (changeTree.indexes[key]) !== "undefined";
|
|
2191
|
+
const index = (isReplace)
|
|
2313
2192
|
? changeTree.indexes[key]
|
|
2314
|
-
:
|
|
2315
|
-
|
|
2193
|
+
: changeTree.indexes[-1] ?? 0;
|
|
2194
|
+
let operation = (isReplace)
|
|
2316
2195
|
? exports.OPERATION.REPLACE
|
|
2317
2196
|
: exports.OPERATION.ADD;
|
|
2318
|
-
|
|
2197
|
+
const isRef = (value[$changes]) !== undefined;
|
|
2319
2198
|
//
|
|
2320
2199
|
// (encoding)
|
|
2321
2200
|
// set a unique id to relate directly with this key/value.
|
|
@@ -2344,17 +2223,17 @@
|
|
|
2344
2223
|
value[$changes].setParent(this, changeTree.root, index);
|
|
2345
2224
|
}
|
|
2346
2225
|
return this;
|
|
2347
|
-
}
|
|
2348
|
-
|
|
2226
|
+
}
|
|
2227
|
+
get(key) {
|
|
2349
2228
|
return this.$items.get(key);
|
|
2350
|
-
}
|
|
2351
|
-
|
|
2352
|
-
|
|
2229
|
+
}
|
|
2230
|
+
delete(key) {
|
|
2231
|
+
const index = this[$changes].indexes[key];
|
|
2353
2232
|
this[$changes].delete(index);
|
|
2354
2233
|
return this.$items.delete(key);
|
|
2355
|
-
}
|
|
2356
|
-
|
|
2357
|
-
|
|
2234
|
+
}
|
|
2235
|
+
clear() {
|
|
2236
|
+
const changeTree = this[$changes];
|
|
2358
2237
|
// discard previous operations.
|
|
2359
2238
|
changeTree.discard(true);
|
|
2360
2239
|
changeTree.indexes = {};
|
|
@@ -2363,69 +2242,64 @@
|
|
|
2363
2242
|
// clear items
|
|
2364
2243
|
this.$items.clear();
|
|
2365
2244
|
changeTree.operation(exports.OPERATION.CLEAR);
|
|
2366
|
-
}
|
|
2367
|
-
|
|
2245
|
+
}
|
|
2246
|
+
has(key) {
|
|
2368
2247
|
return this.$items.has(key);
|
|
2369
|
-
}
|
|
2370
|
-
|
|
2248
|
+
}
|
|
2249
|
+
forEach(callbackfn) {
|
|
2371
2250
|
this.$items.forEach(callbackfn);
|
|
2372
|
-
}
|
|
2373
|
-
|
|
2251
|
+
}
|
|
2252
|
+
entries() {
|
|
2374
2253
|
return this.$items.entries();
|
|
2375
|
-
}
|
|
2376
|
-
|
|
2254
|
+
}
|
|
2255
|
+
keys() {
|
|
2377
2256
|
return this.$items.keys();
|
|
2378
|
-
}
|
|
2379
|
-
|
|
2257
|
+
}
|
|
2258
|
+
values() {
|
|
2380
2259
|
return this.$items.values();
|
|
2381
|
-
}
|
|
2382
|
-
|
|
2383
|
-
|
|
2384
|
-
|
|
2385
|
-
|
|
2386
|
-
enumerable: false,
|
|
2387
|
-
configurable: true
|
|
2388
|
-
});
|
|
2389
|
-
MapSchema.prototype.setIndex = function (index, key) {
|
|
2260
|
+
}
|
|
2261
|
+
get size() {
|
|
2262
|
+
return this.$items.size;
|
|
2263
|
+
}
|
|
2264
|
+
setIndex(index, key) {
|
|
2390
2265
|
this.$indexes.set(index, key);
|
|
2391
|
-
}
|
|
2392
|
-
|
|
2266
|
+
}
|
|
2267
|
+
getIndex(index) {
|
|
2393
2268
|
return this.$indexes.get(index);
|
|
2394
|
-
}
|
|
2395
|
-
|
|
2269
|
+
}
|
|
2270
|
+
[$getByIndex](index) {
|
|
2396
2271
|
return this.$items.get(this.$indexes.get(index));
|
|
2397
|
-
}
|
|
2398
|
-
|
|
2399
|
-
|
|
2272
|
+
}
|
|
2273
|
+
[$deleteByIndex](index) {
|
|
2274
|
+
const key = this.$indexes.get(index);
|
|
2400
2275
|
this.$items.delete(key);
|
|
2401
2276
|
this.$indexes.delete(index);
|
|
2402
|
-
}
|
|
2403
|
-
|
|
2404
|
-
|
|
2405
|
-
|
|
2406
|
-
for (
|
|
2407
|
-
var _c = changes_1[_i], fieldIndex = _c[0], operation = _c[1];
|
|
2277
|
+
}
|
|
2278
|
+
[$onEncodeEnd]() {
|
|
2279
|
+
const changeTree = this[$changes];
|
|
2280
|
+
const changes = changeTree.changes.entries();
|
|
2281
|
+
for (const [fieldIndex, operation] of changes) {
|
|
2408
2282
|
if (operation === exports.OPERATION.DELETE) {
|
|
2409
|
-
|
|
2283
|
+
const index = this[$getByIndex](fieldIndex);
|
|
2410
2284
|
delete changeTree.indexes[index];
|
|
2411
2285
|
}
|
|
2412
2286
|
}
|
|
2413
|
-
}
|
|
2414
|
-
|
|
2415
|
-
|
|
2416
|
-
this.forEach(
|
|
2287
|
+
}
|
|
2288
|
+
toJSON() {
|
|
2289
|
+
const map = {};
|
|
2290
|
+
this.forEach((value, key) => {
|
|
2417
2291
|
map[key] = (typeof (value['toJSON']) === "function")
|
|
2418
2292
|
? value['toJSON']()
|
|
2419
2293
|
: value;
|
|
2420
2294
|
});
|
|
2421
2295
|
return map;
|
|
2422
|
-
}
|
|
2296
|
+
}
|
|
2423
2297
|
//
|
|
2424
2298
|
// Decoding utilities
|
|
2425
2299
|
//
|
|
2426
2300
|
// @ts-ignore
|
|
2427
|
-
|
|
2428
|
-
|
|
2301
|
+
clone(isDecoding) {
|
|
2302
|
+
let cloned;
|
|
2429
2303
|
if (isDecoding) {
|
|
2430
2304
|
// client-side
|
|
2431
2305
|
cloned = Object.assign(new MapSchema(), this);
|
|
@@ -2433,7 +2307,7 @@
|
|
|
2433
2307
|
else {
|
|
2434
2308
|
// server-side
|
|
2435
2309
|
cloned = new MapSchema();
|
|
2436
|
-
this.forEach(
|
|
2310
|
+
this.forEach((value, key) => {
|
|
2437
2311
|
if (value[$changes]) {
|
|
2438
2312
|
cloned.set(key, value['clone']());
|
|
2439
2313
|
}
|
|
@@ -2443,43 +2317,43 @@
|
|
|
2443
2317
|
});
|
|
2444
2318
|
}
|
|
2445
2319
|
return cloned;
|
|
2446
|
-
}
|
|
2447
|
-
|
|
2448
|
-
MapSchema[_a] = encodeKeyValueOperation;
|
|
2449
|
-
MapSchema[_b] = decodeKeyValueOperation;
|
|
2450
|
-
return MapSchema;
|
|
2451
|
-
}());
|
|
2320
|
+
}
|
|
2321
|
+
}
|
|
2452
2322
|
registerType("map", { constructor: MapSchema });
|
|
2453
2323
|
|
|
2454
|
-
|
|
2455
|
-
|
|
2456
|
-
|
|
2457
|
-
|
|
2458
|
-
|
|
2459
|
-
|
|
2460
|
-
|
|
2461
|
-
|
|
2462
|
-
|
|
2463
|
-
}
|
|
2464
|
-
TypeContext.register = function (target) {
|
|
2465
|
-
var parent = Object.getPrototypeOf(target);
|
|
2324
|
+
const DEFAULT_VIEW_TAG = -1;
|
|
2325
|
+
class TypeContext {
|
|
2326
|
+
/**
|
|
2327
|
+
* For inheritance support
|
|
2328
|
+
* Keeps track of which classes extends which. (parent -> children)
|
|
2329
|
+
*/
|
|
2330
|
+
static { this.inheritedTypes = new Map(); }
|
|
2331
|
+
static register(target) {
|
|
2332
|
+
const parent = Object.getPrototypeOf(target);
|
|
2466
2333
|
if (parent !== Schema) {
|
|
2467
|
-
|
|
2334
|
+
let inherits = TypeContext.inheritedTypes.get(parent);
|
|
2468
2335
|
if (!inherits) {
|
|
2469
2336
|
inherits = new Set();
|
|
2470
2337
|
TypeContext.inheritedTypes.set(parent, inherits);
|
|
2471
2338
|
}
|
|
2472
2339
|
inherits.add(target);
|
|
2473
2340
|
}
|
|
2474
|
-
}
|
|
2475
|
-
|
|
2341
|
+
}
|
|
2342
|
+
constructor(rootClass) {
|
|
2343
|
+
this.types = {};
|
|
2344
|
+
this.schemas = new Map();
|
|
2345
|
+
this.hasFilters = false;
|
|
2346
|
+
if (rootClass) {
|
|
2347
|
+
this.discoverTypes(rootClass);
|
|
2348
|
+
}
|
|
2349
|
+
}
|
|
2350
|
+
has(schema) {
|
|
2476
2351
|
return this.schemas.has(schema);
|
|
2477
|
-
}
|
|
2478
|
-
|
|
2352
|
+
}
|
|
2353
|
+
get(typeid) {
|
|
2479
2354
|
return this.types[typeid];
|
|
2480
|
-
}
|
|
2481
|
-
|
|
2482
|
-
if (typeid === void 0) { typeid = this.schemas.size; }
|
|
2355
|
+
}
|
|
2356
|
+
add(schema, typeid = this.schemas.size) {
|
|
2483
2357
|
// skip if already registered
|
|
2484
2358
|
if (this.schemas.has(schema)) {
|
|
2485
2359
|
return false;
|
|
@@ -2487,62 +2361,54 @@
|
|
|
2487
2361
|
this.types[typeid] = schema;
|
|
2488
2362
|
this.schemas.set(schema, typeid);
|
|
2489
2363
|
return true;
|
|
2490
|
-
}
|
|
2491
|
-
|
|
2364
|
+
}
|
|
2365
|
+
getTypeId(klass) {
|
|
2492
2366
|
return this.schemas.get(klass);
|
|
2493
|
-
}
|
|
2494
|
-
|
|
2495
|
-
var _this = this;
|
|
2496
|
-
var _a;
|
|
2367
|
+
}
|
|
2368
|
+
discoverTypes(klass) {
|
|
2497
2369
|
if (!this.add(klass)) {
|
|
2498
2370
|
return;
|
|
2499
2371
|
}
|
|
2500
2372
|
// add classes inherited from this base class
|
|
2501
|
-
|
|
2502
|
-
|
|
2373
|
+
TypeContext.inheritedTypes.get(klass)?.forEach((child) => {
|
|
2374
|
+
this.discoverTypes(child);
|
|
2503
2375
|
});
|
|
2504
2376
|
// skip if no fields are defined for this class.
|
|
2505
2377
|
if (klass[Symbol.metadata] === undefined) {
|
|
2506
2378
|
klass[Symbol.metadata] = {};
|
|
2507
2379
|
}
|
|
2508
2380
|
// const metadata = Metadata.getFor(klass);
|
|
2509
|
-
|
|
2381
|
+
const metadata = klass[Symbol.metadata];
|
|
2510
2382
|
// if any schema/field has filters, mark "context" as having filters.
|
|
2511
2383
|
if (metadata[-2]) {
|
|
2512
2384
|
this.hasFilters = true;
|
|
2513
2385
|
}
|
|
2514
|
-
for (
|
|
2515
|
-
|
|
2386
|
+
for (const field in metadata) {
|
|
2387
|
+
const fieldType = metadata[field].type;
|
|
2516
2388
|
if (typeof (fieldType) === "string") {
|
|
2517
2389
|
continue;
|
|
2518
2390
|
}
|
|
2519
2391
|
if (Array.isArray(fieldType)) {
|
|
2520
|
-
|
|
2521
|
-
if (
|
|
2392
|
+
const type = fieldType[0];
|
|
2393
|
+
if (type === "string") {
|
|
2522
2394
|
continue;
|
|
2523
2395
|
}
|
|
2524
|
-
this.discoverTypes(
|
|
2396
|
+
this.discoverTypes(type);
|
|
2525
2397
|
}
|
|
2526
2398
|
else if (typeof (fieldType) === "function") {
|
|
2527
2399
|
this.discoverTypes(fieldType);
|
|
2528
2400
|
}
|
|
2529
2401
|
else {
|
|
2530
|
-
|
|
2402
|
+
const type = Object.values(fieldType)[0];
|
|
2531
2403
|
// skip primitive types
|
|
2532
|
-
if (typeof (
|
|
2404
|
+
if (typeof (type) === "string") {
|
|
2533
2405
|
continue;
|
|
2534
2406
|
}
|
|
2535
|
-
this.discoverTypes(
|
|
2407
|
+
this.discoverTypes(type);
|
|
2536
2408
|
}
|
|
2537
2409
|
}
|
|
2538
|
-
}
|
|
2539
|
-
|
|
2540
|
-
* For inheritance support
|
|
2541
|
-
* Keeps track of which classes extends which. (parent -> children)
|
|
2542
|
-
*/
|
|
2543
|
-
TypeContext.inheritedTypes = new Map();
|
|
2544
|
-
return TypeContext;
|
|
2545
|
-
}());
|
|
2410
|
+
}
|
|
2411
|
+
}
|
|
2546
2412
|
/**
|
|
2547
2413
|
* [See documentation](https://docs.colyseus.io/state/schema/)
|
|
2548
2414
|
*
|
|
@@ -2685,24 +2551,21 @@
|
|
|
2685
2551
|
// };
|
|
2686
2552
|
// }
|
|
2687
2553
|
// }
|
|
2688
|
-
function view(tag) {
|
|
2689
|
-
if (tag === void 0) { tag = DEFAULT_VIEW_TAG; }
|
|
2554
|
+
function view(tag = DEFAULT_VIEW_TAG) {
|
|
2690
2555
|
return function (target, fieldName) {
|
|
2691
|
-
|
|
2692
|
-
|
|
2693
|
-
|
|
2694
|
-
|
|
2695
|
-
var parentMetadata = parentClass[Symbol.metadata];
|
|
2696
|
-
var metadata = ((_a = constructor[_d = Symbol.metadata]) !== null && _a !== void 0 ? _a : (constructor[_d] = Object.assign({}, constructor[Symbol.metadata], parentMetadata !== null && parentMetadata !== void 0 ? parentMetadata : Object.create(null))));
|
|
2556
|
+
const constructor = target.constructor;
|
|
2557
|
+
const parentClass = Object.getPrototypeOf(constructor);
|
|
2558
|
+
const parentMetadata = parentClass[Symbol.metadata];
|
|
2559
|
+
const metadata = (constructor[Symbol.metadata] ??= Object.assign({}, constructor[Symbol.metadata], parentMetadata ?? Object.create(null)));
|
|
2697
2560
|
if (!metadata[fieldName]) {
|
|
2698
2561
|
//
|
|
2699
2562
|
// detect index for this field, considering inheritance
|
|
2700
2563
|
//
|
|
2701
2564
|
metadata[fieldName] = {
|
|
2702
2565
|
type: undefined,
|
|
2703
|
-
index: (
|
|
2704
|
-
|
|
2705
|
-
|
|
2566
|
+
index: (metadata[-1] // current structure already has fields defined
|
|
2567
|
+
?? (parentMetadata && parentMetadata[-1]) // parent structure has fields defined
|
|
2568
|
+
?? -1) + 1 // no fields defined
|
|
2706
2569
|
};
|
|
2707
2570
|
}
|
|
2708
2571
|
Metadata.setTag(metadata, fieldName, tag);
|
|
@@ -2710,18 +2573,16 @@
|
|
|
2710
2573
|
}
|
|
2711
2574
|
function type(type, options) {
|
|
2712
2575
|
return function (target, field) {
|
|
2713
|
-
|
|
2714
|
-
var _d;
|
|
2715
|
-
var constructor = target.constructor;
|
|
2576
|
+
const constructor = target.constructor;
|
|
2716
2577
|
if (!type) {
|
|
2717
|
-
throw new Error(
|
|
2578
|
+
throw new Error(`${constructor.name}: @type() reference provided for "${field}" is undefined. Make sure you don't have any circular dependencies.`);
|
|
2718
2579
|
}
|
|
2719
2580
|
// for inheritance support
|
|
2720
2581
|
TypeContext.register(constructor);
|
|
2721
|
-
|
|
2722
|
-
|
|
2723
|
-
|
|
2724
|
-
|
|
2582
|
+
const parentClass = Object.getPrototypeOf(constructor);
|
|
2583
|
+
const parentMetadata = parentClass[Symbol.metadata];
|
|
2584
|
+
const metadata = (constructor[Symbol.metadata] ??= Object.assign({}, constructor[Symbol.metadata], parentMetadata ?? Object.create(null)));
|
|
2585
|
+
let fieldIndex;
|
|
2725
2586
|
/**
|
|
2726
2587
|
* skip if descriptor already exists for this field (`@deprecated()`)
|
|
2727
2588
|
*/
|
|
@@ -2734,11 +2595,11 @@
|
|
|
2734
2595
|
// trying to define same property multiple times across inheritance.
|
|
2735
2596
|
// https://github.com/colyseus/colyseus-unity3d/issues/131#issuecomment-814308572
|
|
2736
2597
|
try {
|
|
2737
|
-
throw new Error(
|
|
2598
|
+
throw new Error(`@colyseus/schema: Duplicate '${field}' definition on '${constructor.name}'.\nCheck @type() annotation`);
|
|
2738
2599
|
}
|
|
2739
2600
|
catch (e) {
|
|
2740
|
-
|
|
2741
|
-
throw new Error(
|
|
2601
|
+
const definitionAtLine = e.stack.split("\n")[4].trim();
|
|
2602
|
+
throw new Error(`${e.message} ${definitionAtLine}`);
|
|
2742
2603
|
}
|
|
2743
2604
|
}
|
|
2744
2605
|
else {
|
|
@@ -2749,9 +2610,9 @@
|
|
|
2749
2610
|
//
|
|
2750
2611
|
// detect index for this field, considering inheritance
|
|
2751
2612
|
//
|
|
2752
|
-
fieldIndex =
|
|
2753
|
-
|
|
2754
|
-
|
|
2613
|
+
fieldIndex = metadata[-1] // current structure already has fields defined
|
|
2614
|
+
?? (parentMetadata && parentMetadata[-1]) // parent structure has fields defined
|
|
2615
|
+
?? -1; // no fields defined
|
|
2755
2616
|
fieldIndex++;
|
|
2756
2617
|
}
|
|
2757
2618
|
if (options && options.manual) {
|
|
@@ -2763,13 +2624,13 @@
|
|
|
2763
2624
|
});
|
|
2764
2625
|
}
|
|
2765
2626
|
else {
|
|
2766
|
-
|
|
2627
|
+
const complexTypeKlass = (Array.isArray(type))
|
|
2767
2628
|
? getType("array")
|
|
2768
2629
|
: (typeof (Object.keys(type)[0]) === "string") && getType(Object.keys(type)[0]);
|
|
2769
|
-
|
|
2630
|
+
const childType = (complexTypeKlass)
|
|
2770
2631
|
? Object.values(type)[0]
|
|
2771
2632
|
: type;
|
|
2772
|
-
Metadata.addField(metadata, fieldIndex, field, type, getPropertyDescriptor(
|
|
2633
|
+
Metadata.addField(metadata, fieldIndex, field, type, getPropertyDescriptor(`_${field}`, fieldIndex, childType, complexTypeKlass, metadata, field));
|
|
2773
2634
|
}
|
|
2774
2635
|
};
|
|
2775
2636
|
}
|
|
@@ -2777,8 +2638,7 @@
|
|
|
2777
2638
|
return {
|
|
2778
2639
|
get: function () { return this[fieldCached]; },
|
|
2779
2640
|
set: function (value) {
|
|
2780
|
-
|
|
2781
|
-
var previousValue = this[fieldCached] || undefined;
|
|
2641
|
+
const previousValue = this[fieldCached] || undefined;
|
|
2782
2642
|
// skip if value is the same as cached.
|
|
2783
2643
|
if (value === previousValue) {
|
|
2784
2644
|
return;
|
|
@@ -2788,7 +2648,7 @@
|
|
|
2788
2648
|
if (complexTypeKlass) {
|
|
2789
2649
|
// automaticallty transform Array into ArraySchema
|
|
2790
2650
|
if (complexTypeKlass.constructor === ArraySchema && !(value instanceof ArraySchema)) {
|
|
2791
|
-
value = new
|
|
2651
|
+
value = new ArraySchema(...value);
|
|
2792
2652
|
}
|
|
2793
2653
|
// automaticallty transform Map into MapSchema
|
|
2794
2654
|
if (complexTypeKlass.constructor === MapSchema && !(value instanceof MapSchema)) {
|
|
@@ -2801,7 +2661,7 @@
|
|
|
2801
2661
|
// TODO: if there are other references to this instance, we should not remove it from root.
|
|
2802
2662
|
//
|
|
2803
2663
|
if (previousValue !== undefined && previousValue[$changes]) {
|
|
2804
|
-
|
|
2664
|
+
this[$changes].root?.remove(previousValue[$changes]);
|
|
2805
2665
|
}
|
|
2806
2666
|
// flag the change for encoding.
|
|
2807
2667
|
this.constructor[$track](this[$changes], fieldIndex, exports.OPERATION.ADD);
|
|
@@ -2829,33 +2689,30 @@
|
|
|
2829
2689
|
* `@deprecated()` flag a field as deprecated.
|
|
2830
2690
|
* The previous `@type()` annotation should remain along with this one.
|
|
2831
2691
|
*/
|
|
2832
|
-
function deprecated(throws) {
|
|
2833
|
-
if (throws === void 0) { throws = true; }
|
|
2692
|
+
function deprecated(throws = true) {
|
|
2834
2693
|
return function (klass, field) {
|
|
2835
|
-
var _a, _b, _c;
|
|
2836
|
-
var _d;
|
|
2837
2694
|
//
|
|
2838
2695
|
// FIXME: the following block of code is repeated across `@type()`, `@deprecated()` and `@unreliable()` decorators.
|
|
2839
2696
|
//
|
|
2840
|
-
|
|
2841
|
-
|
|
2842
|
-
|
|
2843
|
-
|
|
2697
|
+
const constructor = klass.constructor;
|
|
2698
|
+
const parentClass = Object.getPrototypeOf(constructor);
|
|
2699
|
+
const parentMetadata = parentClass[Symbol.metadata];
|
|
2700
|
+
const metadata = (constructor[Symbol.metadata] ??= Object.assign({}, constructor[Symbol.metadata], parentMetadata ?? Object.create(null)));
|
|
2844
2701
|
if (!metadata[field]) {
|
|
2845
2702
|
//
|
|
2846
2703
|
// detect index for this field, considering inheritance
|
|
2847
2704
|
//
|
|
2848
2705
|
metadata[field] = {
|
|
2849
2706
|
type: undefined,
|
|
2850
|
-
index: (
|
|
2851
|
-
|
|
2852
|
-
|
|
2707
|
+
index: (metadata[-1] // current structure already has fields defined
|
|
2708
|
+
?? (parentMetadata && parentMetadata[-1]) // parent structure has fields defined
|
|
2709
|
+
?? -1) + 1 // no fields defined
|
|
2853
2710
|
};
|
|
2854
2711
|
}
|
|
2855
2712
|
metadata[field].deprecated = true;
|
|
2856
2713
|
if (throws) {
|
|
2857
2714
|
metadata[field].descriptor = {
|
|
2858
|
-
get: function () { throw new Error(
|
|
2715
|
+
get: function () { throw new Error(`${field} is deprecated.`); },
|
|
2859
2716
|
set: function (value) { },
|
|
2860
2717
|
enumerable: false,
|
|
2861
2718
|
configurable: true
|
|
@@ -2870,27 +2727,25 @@
|
|
|
2870
2727
|
};
|
|
2871
2728
|
}
|
|
2872
2729
|
function defineTypes(target, fields, options) {
|
|
2873
|
-
for (
|
|
2730
|
+
for (let field in fields) {
|
|
2874
2731
|
type(fields[field], options)(target.prototype, field);
|
|
2875
2732
|
}
|
|
2876
2733
|
return target;
|
|
2877
2734
|
}
|
|
2878
2735
|
|
|
2879
2736
|
function getIndent(level) {
|
|
2880
|
-
return (new Array(level).fill(0)).map(
|
|
2881
|
-
return (i === level - 1) ? "\u2514\u2500 " : " ";
|
|
2882
|
-
}).join("");
|
|
2737
|
+
return (new Array(level).fill(0)).map((_, i) => (i === level - 1) ? `└─ ` : ` `).join("");
|
|
2883
2738
|
}
|
|
2884
2739
|
function dumpChanges(schema) {
|
|
2885
|
-
|
|
2886
|
-
|
|
2740
|
+
const $root = schema[$changes].root;
|
|
2741
|
+
const dump = {
|
|
2887
2742
|
ops: {},
|
|
2888
2743
|
refs: []
|
|
2889
2744
|
};
|
|
2890
|
-
$root.changes.forEach(
|
|
2891
|
-
dump.refs.push(
|
|
2892
|
-
operations.forEach(
|
|
2893
|
-
|
|
2745
|
+
$root.changes.forEach((operations, changeTree) => {
|
|
2746
|
+
dump.refs.push(`refId#${changeTree.refId}`);
|
|
2747
|
+
operations.forEach((op, index) => {
|
|
2748
|
+
const opName = exports.OPERATION[op];
|
|
2894
2749
|
if (!dump.ops[opName]) {
|
|
2895
2750
|
dump.ops[opName] = 0;
|
|
2896
2751
|
}
|
|
@@ -2905,7 +2760,7 @@
|
|
|
2905
2760
|
return number;
|
|
2906
2761
|
}
|
|
2907
2762
|
// Find the position of the most significant bit
|
|
2908
|
-
|
|
2763
|
+
let msbPosition = 0;
|
|
2909
2764
|
while (number > 0) {
|
|
2910
2765
|
number >>= 1;
|
|
2911
2766
|
msbPosition++;
|
|
@@ -2914,40 +2769,29 @@
|
|
|
2914
2769
|
return 1 << msbPosition;
|
|
2915
2770
|
}
|
|
2916
2771
|
|
|
2772
|
+
var _a$2, _b$2;
|
|
2917
2773
|
/**
|
|
2918
2774
|
* Schema encoder / decoder
|
|
2919
2775
|
*/
|
|
2920
|
-
|
|
2921
|
-
|
|
2922
|
-
|
|
2923
|
-
var args = [];
|
|
2924
|
-
for (var _i = 0; _i < arguments.length; _i++) {
|
|
2925
|
-
args[_i] = arguments[_i];
|
|
2926
|
-
}
|
|
2927
|
-
Schema.initialize(this);
|
|
2928
|
-
//
|
|
2929
|
-
// Assign initial values
|
|
2930
|
-
//
|
|
2931
|
-
if (args[0]) {
|
|
2932
|
-
this.assign(args[0]);
|
|
2933
|
-
}
|
|
2934
|
-
}
|
|
2776
|
+
class Schema {
|
|
2777
|
+
static { this[_a$2] = encodeSchemaOperation; }
|
|
2778
|
+
static { this[_b$2] = decodeSchemaOperation; }
|
|
2935
2779
|
/**
|
|
2936
2780
|
* Assign the property descriptors required to track changes on this instance.
|
|
2937
2781
|
* @param instance
|
|
2938
2782
|
*/
|
|
2939
|
-
|
|
2783
|
+
static initialize(instance) {
|
|
2940
2784
|
Object.defineProperty(instance, $changes, {
|
|
2941
2785
|
value: new ChangeTree(instance),
|
|
2942
2786
|
enumerable: false,
|
|
2943
2787
|
writable: true
|
|
2944
2788
|
});
|
|
2945
|
-
|
|
2789
|
+
const metadata = instance.constructor[Symbol.metadata];
|
|
2946
2790
|
// Define property descriptors
|
|
2947
|
-
for (
|
|
2791
|
+
for (const field in metadata) {
|
|
2948
2792
|
if (metadata[field].descriptor) {
|
|
2949
2793
|
// for encoder
|
|
2950
|
-
Object.defineProperty(instance,
|
|
2794
|
+
Object.defineProperty(instance, `_${field}`, {
|
|
2951
2795
|
value: undefined,
|
|
2952
2796
|
writable: true,
|
|
2953
2797
|
enumerable: false,
|
|
@@ -2971,19 +2815,18 @@
|
|
|
2971
2815
|
// instance[field] = args[0][field];
|
|
2972
2816
|
// }
|
|
2973
2817
|
}
|
|
2974
|
-
}
|
|
2975
|
-
|
|
2818
|
+
}
|
|
2819
|
+
static is(type) {
|
|
2976
2820
|
return typeof (type[Symbol.metadata]) === "object";
|
|
2977
2821
|
// const metadata = type[Symbol.metadata];
|
|
2978
2822
|
// return metadata && Object.prototype.hasOwnProperty.call(metadata, -1);
|
|
2979
|
-
}
|
|
2823
|
+
}
|
|
2980
2824
|
/**
|
|
2981
2825
|
* Track property changes
|
|
2982
2826
|
*/
|
|
2983
|
-
|
|
2984
|
-
if (operation === void 0) { operation = exports.OPERATION.ADD; }
|
|
2827
|
+
static [(_a$2 = $encoder, _b$2 = $decoder, $track)](changeTree, index, operation = exports.OPERATION.ADD) {
|
|
2985
2828
|
changeTree.change(index, operation);
|
|
2986
|
-
}
|
|
2829
|
+
}
|
|
2987
2830
|
/**
|
|
2988
2831
|
* Determine if a property must be filtered.
|
|
2989
2832
|
* - If returns false, the property is NOT going to be encoded.
|
|
@@ -2993,10 +2836,9 @@
|
|
|
2993
2836
|
* - First, the encoder iterates over all "not owned" properties and encodes them.
|
|
2994
2837
|
* - Then, the encoder iterates over all "owned" properties per instance and encodes them.
|
|
2995
2838
|
*/
|
|
2996
|
-
|
|
2997
|
-
|
|
2998
|
-
|
|
2999
|
-
var tag = metadata[metadata[index]].tag;
|
|
2839
|
+
static [$filter](ref, index, view) {
|
|
2840
|
+
const metadata = ref.constructor[Symbol.metadata];
|
|
2841
|
+
const tag = metadata[metadata[index]].tag;
|
|
3000
2842
|
if (view === undefined) {
|
|
3001
2843
|
// shared pass/encode: encode if doesn't have a tag
|
|
3002
2844
|
return tag === undefined;
|
|
@@ -3011,34 +2853,43 @@
|
|
|
3011
2853
|
}
|
|
3012
2854
|
else {
|
|
3013
2855
|
// view pass: custom tag
|
|
3014
|
-
|
|
2856
|
+
const tags = view.tags?.get(ref[$changes]);
|
|
3015
2857
|
return tags && tags.has(tag);
|
|
3016
2858
|
}
|
|
3017
|
-
}
|
|
3018
|
-
|
|
2859
|
+
}
|
|
2860
|
+
// allow inherited classes to have a constructor
|
|
2861
|
+
constructor(...args) {
|
|
2862
|
+
Schema.initialize(this);
|
|
2863
|
+
//
|
|
2864
|
+
// Assign initial values
|
|
2865
|
+
//
|
|
2866
|
+
if (args[0]) {
|
|
2867
|
+
this.assign(args[0]);
|
|
2868
|
+
}
|
|
2869
|
+
}
|
|
2870
|
+
assign(props) {
|
|
3019
2871
|
Object.assign(this, props);
|
|
3020
2872
|
return this;
|
|
3021
|
-
}
|
|
2873
|
+
}
|
|
3022
2874
|
/**
|
|
3023
2875
|
* (Server-side): Flag a property to be encoded for the next patch.
|
|
3024
2876
|
* @param instance Schema instance
|
|
3025
2877
|
* @param property string representing the property name, or number representing the index of the property.
|
|
3026
2878
|
* @param operation OPERATION to perform (detected automatically)
|
|
3027
2879
|
*/
|
|
3028
|
-
|
|
2880
|
+
setDirty(property, operation) {
|
|
3029
2881
|
this[$changes].change(this.constructor[Symbol.metadata][property].index, operation);
|
|
3030
|
-
}
|
|
3031
|
-
|
|
3032
|
-
|
|
3033
|
-
|
|
3034
|
-
var metadata = this.constructor[Symbol.metadata];
|
|
2882
|
+
}
|
|
2883
|
+
clone() {
|
|
2884
|
+
const cloned = new (this.constructor);
|
|
2885
|
+
const metadata = this.constructor[Symbol.metadata];
|
|
3035
2886
|
//
|
|
3036
2887
|
// TODO: clone all properties, not only annotated ones
|
|
3037
2888
|
//
|
|
3038
2889
|
// for (const field in this) {
|
|
3039
|
-
for (
|
|
2890
|
+
for (const field in metadata) {
|
|
3040
2891
|
if (typeof (this[field]) === "object" &&
|
|
3041
|
-
typeof (
|
|
2892
|
+
typeof (this[field]?.clone) === "function") {
|
|
3042
2893
|
// deep clone
|
|
3043
2894
|
cloned[field] = this[field].clone();
|
|
3044
2895
|
}
|
|
@@ -3048,12 +2899,12 @@
|
|
|
3048
2899
|
}
|
|
3049
2900
|
}
|
|
3050
2901
|
return cloned;
|
|
3051
|
-
}
|
|
3052
|
-
|
|
3053
|
-
|
|
3054
|
-
|
|
3055
|
-
for (
|
|
3056
|
-
|
|
2902
|
+
}
|
|
2903
|
+
toJSON() {
|
|
2904
|
+
const metadata = this.constructor[Symbol.metadata];
|
|
2905
|
+
const obj = {};
|
|
2906
|
+
for (const fieldName in metadata) {
|
|
2907
|
+
const field = metadata[fieldName];
|
|
3057
2908
|
if (!field.deprecated && this[fieldName] !== null && typeof (this[fieldName]) !== "undefined") {
|
|
3058
2909
|
obj[fieldName] = (typeof (this[fieldName]['toJSON']) === "function")
|
|
3059
2910
|
? this[fieldName]['toJSON']()
|
|
@@ -3061,30 +2912,25 @@
|
|
|
3061
2912
|
}
|
|
3062
2913
|
}
|
|
3063
2914
|
return obj;
|
|
3064
|
-
}
|
|
3065
|
-
|
|
2915
|
+
}
|
|
2916
|
+
discardAllChanges() {
|
|
3066
2917
|
this[$changes].discardAll();
|
|
3067
|
-
}
|
|
3068
|
-
|
|
2918
|
+
}
|
|
2919
|
+
[$getByIndex](index) {
|
|
3069
2920
|
return this[this.constructor[Symbol.metadata][index]];
|
|
3070
|
-
}
|
|
3071
|
-
|
|
2921
|
+
}
|
|
2922
|
+
[$deleteByIndex](index) {
|
|
3072
2923
|
this[this.constructor[Symbol.metadata][index]] = undefined;
|
|
3073
|
-
}
|
|
3074
|
-
|
|
3075
|
-
|
|
3076
|
-
|
|
3077
|
-
|
|
3078
|
-
|
|
3079
|
-
|
|
3080
|
-
|
|
3081
|
-
var output = "";
|
|
3082
|
-
output += "".concat(getIndent(level)).concat(ref.constructor.name, " (").concat(ref[$changes].refId, ")").concat(contents, "\n");
|
|
3083
|
-
changeTree.forEachChild(function (childChangeTree) {
|
|
3084
|
-
return output += _this.debugRefIds(childChangeTree.ref, jsonContents, level + 1);
|
|
3085
|
-
});
|
|
2924
|
+
}
|
|
2925
|
+
static debugRefIds(instance, jsonContents = true, level = 0) {
|
|
2926
|
+
const ref = instance;
|
|
2927
|
+
const changeTree = ref[$changes];
|
|
2928
|
+
const contents = (jsonContents) ? ` - ${JSON.stringify(ref.toJSON())}` : "";
|
|
2929
|
+
let output = "";
|
|
2930
|
+
output += `${getIndent(level)}${ref.constructor.name} (${ref[$changes].refId})${contents}\n`;
|
|
2931
|
+
changeTree.forEachChild((childChangeTree) => output += this.debugRefIds(childChangeTree.ref, jsonContents, level + 1));
|
|
3086
2932
|
return output;
|
|
3087
|
-
}
|
|
2933
|
+
}
|
|
3088
2934
|
/**
|
|
3089
2935
|
* Return a string representation of the changes on a Schema instance.
|
|
3090
2936
|
* The list of changes is cleared after each encode.
|
|
@@ -3093,46 +2939,39 @@
|
|
|
3093
2939
|
* @param isEncodeAll Return "full encode" instead of current change set.
|
|
3094
2940
|
* @returns
|
|
3095
2941
|
*/
|
|
3096
|
-
|
|
3097
|
-
|
|
3098
|
-
|
|
3099
|
-
|
|
3100
|
-
|
|
3101
|
-
var changeSetName = (isEncodeAll) ? "allChanges" : "changes";
|
|
3102
|
-
var output = "".concat(instance.constructor.name, " (").concat(changeTree.refId, ") -> .").concat(changeSetName, ":\n");
|
|
2942
|
+
static debugChanges(instance, isEncodeAll = false) {
|
|
2943
|
+
const changeTree = instance[$changes];
|
|
2944
|
+
const changeSet = (isEncodeAll) ? changeTree.allChanges : changeTree.changes;
|
|
2945
|
+
const changeSetName = (isEncodeAll) ? "allChanges" : "changes";
|
|
2946
|
+
let output = `${instance.constructor.name} (${changeTree.refId}) -> .${changeSetName}:\n`;
|
|
3103
2947
|
function dumpChangeSet(changeSet) {
|
|
3104
2948
|
Array.from(changeSet)
|
|
3105
|
-
.sort(
|
|
3106
|
-
.forEach(
|
|
3107
|
-
var index = _c[0], operation = _c[1];
|
|
3108
|
-
return output += "- [".concat(index, "]: ").concat(exports.OPERATION[operation], " (").concat(JSON.stringify(changeTree.getValue(index, isEncodeAll)), ")\n");
|
|
3109
|
-
});
|
|
2949
|
+
.sort((a, b) => a[0] - b[0])
|
|
2950
|
+
.forEach(([index, operation]) => output += `- [${index}]: ${exports.OPERATION[operation]} (${JSON.stringify(changeTree.getValue(index, isEncodeAll))})\n`);
|
|
3110
2951
|
}
|
|
3111
2952
|
dumpChangeSet(changeSet);
|
|
3112
2953
|
// display filtered changes
|
|
3113
|
-
if (!isEncodeAll &&
|
|
3114
|
-
output +=
|
|
2954
|
+
if (!isEncodeAll && changeTree.filteredChanges?.size > 0) {
|
|
2955
|
+
output += `${instance.constructor.name} (${changeTree.refId}) -> .filteredChanges:\n`;
|
|
3115
2956
|
dumpChangeSet(changeTree.filteredChanges);
|
|
3116
2957
|
}
|
|
3117
2958
|
// display filtered changes
|
|
3118
|
-
if (isEncodeAll &&
|
|
3119
|
-
output +=
|
|
2959
|
+
if (isEncodeAll && changeTree.allFilteredChanges?.size > 0) {
|
|
2960
|
+
output += `${instance.constructor.name} (${changeTree.refId}) -> .allFilteredChanges:\n`;
|
|
3120
2961
|
dumpChangeSet(changeTree.allFilteredChanges);
|
|
3121
2962
|
}
|
|
3122
2963
|
return output;
|
|
3123
|
-
}
|
|
3124
|
-
|
|
3125
|
-
|
|
3126
|
-
|
|
3127
|
-
|
|
3128
|
-
|
|
3129
|
-
|
|
3130
|
-
|
|
3131
|
-
|
|
3132
|
-
|
|
3133
|
-
|
|
3134
|
-
var parentChangeTrees = [];
|
|
3135
|
-
var parentChangeTree = (_c = changeTree.parent) === null || _c === void 0 ? void 0 : _c[$changes];
|
|
2964
|
+
}
|
|
2965
|
+
static debugChangesDeep(ref) {
|
|
2966
|
+
let output = "";
|
|
2967
|
+
const rootChangeTree = ref[$changes];
|
|
2968
|
+
const changeTrees = new Map();
|
|
2969
|
+
let totalInstances = 0;
|
|
2970
|
+
let totalOperations = 0;
|
|
2971
|
+
for (const [changeTree, changes] of (rootChangeTree.root.changes.entries())) {
|
|
2972
|
+
let includeChangeTree = false;
|
|
2973
|
+
let parentChangeTrees = [];
|
|
2974
|
+
let parentChangeTree = changeTree.parent?.[$changes];
|
|
3136
2975
|
if (changeTree === rootChangeTree) {
|
|
3137
2976
|
includeChangeTree = true;
|
|
3138
2977
|
}
|
|
@@ -3143,7 +2982,7 @@
|
|
|
3143
2982
|
includeChangeTree = true;
|
|
3144
2983
|
break;
|
|
3145
2984
|
}
|
|
3146
|
-
parentChangeTree =
|
|
2985
|
+
parentChangeTree = parentChangeTree.parent?.[$changes];
|
|
3147
2986
|
}
|
|
3148
2987
|
}
|
|
3149
2988
|
if (includeChangeTree) {
|
|
@@ -3153,55 +2992,36 @@
|
|
|
3153
2992
|
}
|
|
3154
2993
|
}
|
|
3155
2994
|
output += "---\n";
|
|
3156
|
-
output +=
|
|
3157
|
-
output +=
|
|
3158
|
-
output +=
|
|
2995
|
+
output += `root refId: ${rootChangeTree.refId}\n`;
|
|
2996
|
+
output += `Total instances: ${totalInstances}\n`;
|
|
2997
|
+
output += `Total changes: ${totalOperations}\n`;
|
|
3159
2998
|
output += "---\n";
|
|
3160
2999
|
// based on root.changes, display a tree of changes that has the "ref" instance as parent
|
|
3161
|
-
|
|
3162
|
-
for (
|
|
3163
|
-
|
|
3164
|
-
parentChangeTrees.forEach(function (parentChangeTree, level) {
|
|
3000
|
+
const visitedParents = new WeakSet();
|
|
3001
|
+
for (const [changeTree, parentChangeTrees] of changeTrees.entries()) {
|
|
3002
|
+
parentChangeTrees.forEach((parentChangeTree, level) => {
|
|
3165
3003
|
if (!visitedParents.has(parentChangeTree)) {
|
|
3166
|
-
output +=
|
|
3004
|
+
output += `${getIndent(level)}${parentChangeTree.ref.constructor.name} (refId: ${parentChangeTree.refId})\n`;
|
|
3167
3005
|
visitedParents.add(parentChangeTree);
|
|
3168
3006
|
}
|
|
3169
3007
|
});
|
|
3170
|
-
|
|
3171
|
-
|
|
3172
|
-
|
|
3173
|
-
|
|
3174
|
-
output +=
|
|
3175
|
-
for (
|
|
3176
|
-
|
|
3177
|
-
output += "".concat(getIndent(level + 1)).concat(exports.OPERATION[operation], ": ").concat(index, "\n");
|
|
3008
|
+
const changes = changeTree.changes;
|
|
3009
|
+
const level = parentChangeTrees.length;
|
|
3010
|
+
const indent = getIndent(level);
|
|
3011
|
+
const parentIndex = (level > 0) ? `(${changeTree.parentIndex}) ` : "";
|
|
3012
|
+
output += `${indent}${parentIndex}${changeTree.ref.constructor.name} (refId: ${changeTree.refId}) - changes: ${changes.size}\n`;
|
|
3013
|
+
for (const [index, operation] of changes) {
|
|
3014
|
+
output += `${getIndent(level + 1)}${exports.OPERATION[operation]}: ${index}\n`;
|
|
3178
3015
|
}
|
|
3179
3016
|
}
|
|
3180
|
-
return
|
|
3181
|
-
};
|
|
3182
|
-
var _a, _b;
|
|
3183
|
-
Schema[_a] = encodeSchemaOperation;
|
|
3184
|
-
Schema[_b] = decodeSchemaOperation;
|
|
3185
|
-
return Schema;
|
|
3186
|
-
}());
|
|
3187
|
-
|
|
3188
|
-
var CollectionSchema = /** @class */ (function () {
|
|
3189
|
-
function CollectionSchema(initialValues) {
|
|
3190
|
-
var _this = this;
|
|
3191
|
-
this.$items = new Map();
|
|
3192
|
-
this.$indexes = new Map();
|
|
3193
|
-
this.$refId = 0;
|
|
3194
|
-
this[$changes] = new ChangeTree(this);
|
|
3195
|
-
if (initialValues) {
|
|
3196
|
-
initialValues.forEach(function (v) { return _this.add(v); });
|
|
3197
|
-
}
|
|
3198
|
-
Object.defineProperty(this, $childType, {
|
|
3199
|
-
value: undefined,
|
|
3200
|
-
enumerable: false,
|
|
3201
|
-
writable: true,
|
|
3202
|
-
configurable: true,
|
|
3203
|
-
});
|
|
3017
|
+
return `${output}`;
|
|
3204
3018
|
}
|
|
3019
|
+
}
|
|
3020
|
+
|
|
3021
|
+
var _a$1, _b$1;
|
|
3022
|
+
class CollectionSchema {
|
|
3023
|
+
static { this[_a$1] = encodeKeyValueOperation; }
|
|
3024
|
+
static { this[_b$1] = decodeKeyValueOperation; }
|
|
3205
3025
|
/**
|
|
3206
3026
|
* Determine if a property must be filtered.
|
|
3207
3027
|
* - If returns false, the property is NOT going to be encoded.
|
|
@@ -3211,18 +3031,33 @@
|
|
|
3211
3031
|
* - First, the encoder iterates over all "not owned" properties and encodes them.
|
|
3212
3032
|
* - Then, the encoder iterates over all "owned" properties per instance and encodes them.
|
|
3213
3033
|
*/
|
|
3214
|
-
|
|
3034
|
+
static [(_a$1 = $encoder, _b$1 = $decoder, $filter)](ref, index, view) {
|
|
3215
3035
|
return (!view ||
|
|
3216
3036
|
typeof (ref[$childType]) === "string" ||
|
|
3217
3037
|
view.items.has(ref[$getByIndex](index)[$changes]));
|
|
3218
|
-
}
|
|
3219
|
-
|
|
3038
|
+
}
|
|
3039
|
+
static is(type) {
|
|
3220
3040
|
return type['collection'] !== undefined;
|
|
3221
|
-
}
|
|
3222
|
-
|
|
3041
|
+
}
|
|
3042
|
+
constructor(initialValues) {
|
|
3043
|
+
this.$items = new Map();
|
|
3044
|
+
this.$indexes = new Map();
|
|
3045
|
+
this.$refId = 0;
|
|
3046
|
+
this[$changes] = new ChangeTree(this);
|
|
3047
|
+
if (initialValues) {
|
|
3048
|
+
initialValues.forEach((v) => this.add(v));
|
|
3049
|
+
}
|
|
3050
|
+
Object.defineProperty(this, $childType, {
|
|
3051
|
+
value: undefined,
|
|
3052
|
+
enumerable: false,
|
|
3053
|
+
writable: true,
|
|
3054
|
+
configurable: true,
|
|
3055
|
+
});
|
|
3056
|
+
}
|
|
3057
|
+
add(value) {
|
|
3223
3058
|
// set "index" for reference.
|
|
3224
|
-
|
|
3225
|
-
|
|
3059
|
+
const index = this.$refId++;
|
|
3060
|
+
const isRef = (value[$changes]) !== undefined;
|
|
3226
3061
|
if (isRef) {
|
|
3227
3062
|
value[$changes].setParent(this, this[$changes].root, index);
|
|
3228
3063
|
}
|
|
@@ -3231,18 +3066,18 @@
|
|
|
3231
3066
|
this.$items.set(index, value);
|
|
3232
3067
|
this[$changes].change(index);
|
|
3233
3068
|
return index;
|
|
3234
|
-
}
|
|
3235
|
-
|
|
3236
|
-
|
|
3069
|
+
}
|
|
3070
|
+
at(index) {
|
|
3071
|
+
const key = Array.from(this.$items.keys())[index];
|
|
3237
3072
|
return this.$items.get(key);
|
|
3238
|
-
}
|
|
3239
|
-
|
|
3073
|
+
}
|
|
3074
|
+
entries() {
|
|
3240
3075
|
return this.$items.entries();
|
|
3241
|
-
}
|
|
3242
|
-
|
|
3243
|
-
|
|
3244
|
-
|
|
3245
|
-
|
|
3076
|
+
}
|
|
3077
|
+
delete(item) {
|
|
3078
|
+
const entries = this.$items.entries();
|
|
3079
|
+
let index;
|
|
3080
|
+
let entry;
|
|
3246
3081
|
while (entry = entries.next()) {
|
|
3247
3082
|
if (entry.done) {
|
|
3248
3083
|
break;
|
|
@@ -3258,9 +3093,9 @@
|
|
|
3258
3093
|
this[$changes].delete(index);
|
|
3259
3094
|
this.$indexes.delete(index);
|
|
3260
3095
|
return this.$items.delete(index);
|
|
3261
|
-
}
|
|
3262
|
-
|
|
3263
|
-
|
|
3096
|
+
}
|
|
3097
|
+
clear() {
|
|
3098
|
+
const changeTree = this[$changes];
|
|
3264
3099
|
// discard previous operations.
|
|
3265
3100
|
changeTree.discard(true);
|
|
3266
3101
|
changeTree.indexes = {};
|
|
@@ -3269,59 +3104,54 @@
|
|
|
3269
3104
|
// clear items
|
|
3270
3105
|
this.$items.clear();
|
|
3271
3106
|
changeTree.operation(exports.OPERATION.CLEAR);
|
|
3272
|
-
}
|
|
3273
|
-
|
|
3274
|
-
return Array.from(this.$items.values()).some(
|
|
3275
|
-
}
|
|
3276
|
-
|
|
3277
|
-
|
|
3278
|
-
|
|
3279
|
-
|
|
3280
|
-
CollectionSchema.prototype.values = function () {
|
|
3107
|
+
}
|
|
3108
|
+
has(value) {
|
|
3109
|
+
return Array.from(this.$items.values()).some((v) => v === value);
|
|
3110
|
+
}
|
|
3111
|
+
forEach(callbackfn) {
|
|
3112
|
+
this.$items.forEach((value, key, _) => callbackfn(value, key, this));
|
|
3113
|
+
}
|
|
3114
|
+
values() {
|
|
3281
3115
|
return this.$items.values();
|
|
3282
|
-
}
|
|
3283
|
-
|
|
3284
|
-
|
|
3285
|
-
|
|
3286
|
-
},
|
|
3287
|
-
enumerable: false,
|
|
3288
|
-
configurable: true
|
|
3289
|
-
});
|
|
3116
|
+
}
|
|
3117
|
+
get size() {
|
|
3118
|
+
return this.$items.size;
|
|
3119
|
+
}
|
|
3290
3120
|
/** Iterator */
|
|
3291
|
-
|
|
3121
|
+
[Symbol.iterator]() {
|
|
3292
3122
|
return this.$items.values();
|
|
3293
|
-
}
|
|
3294
|
-
|
|
3123
|
+
}
|
|
3124
|
+
setIndex(index, key) {
|
|
3295
3125
|
this.$indexes.set(index, key);
|
|
3296
|
-
}
|
|
3297
|
-
|
|
3126
|
+
}
|
|
3127
|
+
getIndex(index) {
|
|
3298
3128
|
return this.$indexes.get(index);
|
|
3299
|
-
}
|
|
3300
|
-
|
|
3129
|
+
}
|
|
3130
|
+
[$getByIndex](index) {
|
|
3301
3131
|
return this.$items.get(this.$indexes.get(index));
|
|
3302
|
-
}
|
|
3303
|
-
|
|
3304
|
-
|
|
3132
|
+
}
|
|
3133
|
+
[$deleteByIndex](index) {
|
|
3134
|
+
const key = this.$indexes.get(index);
|
|
3305
3135
|
this.$items.delete(key);
|
|
3306
3136
|
this.$indexes.delete(index);
|
|
3307
|
-
}
|
|
3308
|
-
|
|
3137
|
+
}
|
|
3138
|
+
toArray() {
|
|
3309
3139
|
return Array.from(this.$items.values());
|
|
3310
|
-
}
|
|
3311
|
-
|
|
3312
|
-
|
|
3313
|
-
this.forEach(
|
|
3140
|
+
}
|
|
3141
|
+
toJSON() {
|
|
3142
|
+
const values = [];
|
|
3143
|
+
this.forEach((value, key) => {
|
|
3314
3144
|
values.push((typeof (value['toJSON']) === "function")
|
|
3315
3145
|
? value['toJSON']()
|
|
3316
3146
|
: value);
|
|
3317
3147
|
});
|
|
3318
3148
|
return values;
|
|
3319
|
-
}
|
|
3149
|
+
}
|
|
3320
3150
|
//
|
|
3321
3151
|
// Decoding utilities
|
|
3322
3152
|
//
|
|
3323
|
-
|
|
3324
|
-
|
|
3153
|
+
clone(isDecoding) {
|
|
3154
|
+
let cloned;
|
|
3325
3155
|
if (isDecoding) {
|
|
3326
3156
|
// client-side
|
|
3327
3157
|
cloned = Object.assign(new CollectionSchema(), this);
|
|
@@ -3329,7 +3159,7 @@
|
|
|
3329
3159
|
else {
|
|
3330
3160
|
// server-side
|
|
3331
3161
|
cloned = new CollectionSchema();
|
|
3332
|
-
this.forEach(
|
|
3162
|
+
this.forEach((value) => {
|
|
3333
3163
|
if (value[$changes]) {
|
|
3334
3164
|
cloned.add(value['clone']());
|
|
3335
3165
|
}
|
|
@@ -3339,31 +3169,14 @@
|
|
|
3339
3169
|
});
|
|
3340
3170
|
}
|
|
3341
3171
|
return cloned;
|
|
3342
|
-
}
|
|
3343
|
-
|
|
3344
|
-
CollectionSchema[_a] = encodeKeyValueOperation;
|
|
3345
|
-
CollectionSchema[_b] = decodeKeyValueOperation;
|
|
3346
|
-
return CollectionSchema;
|
|
3347
|
-
}());
|
|
3172
|
+
}
|
|
3173
|
+
}
|
|
3348
3174
|
registerType("collection", { constructor: CollectionSchema, });
|
|
3349
3175
|
|
|
3350
|
-
var
|
|
3351
|
-
|
|
3352
|
-
|
|
3353
|
-
|
|
3354
|
-
this.$indexes = new Map();
|
|
3355
|
-
this.$refId = 0;
|
|
3356
|
-
this[$changes] = new ChangeTree(this);
|
|
3357
|
-
if (initialValues) {
|
|
3358
|
-
initialValues.forEach(function (v) { return _this.add(v); });
|
|
3359
|
-
}
|
|
3360
|
-
Object.defineProperty(this, $childType, {
|
|
3361
|
-
value: undefined,
|
|
3362
|
-
enumerable: false,
|
|
3363
|
-
writable: true,
|
|
3364
|
-
configurable: true,
|
|
3365
|
-
});
|
|
3366
|
-
}
|
|
3176
|
+
var _a, _b;
|
|
3177
|
+
class SetSchema {
|
|
3178
|
+
static { this[_a] = encodeKeyValueOperation; }
|
|
3179
|
+
static { this[_b] = decodeKeyValueOperation; }
|
|
3367
3180
|
/**
|
|
3368
3181
|
* Determine if a property must be filtered.
|
|
3369
3182
|
* - If returns false, the property is NOT going to be encoded.
|
|
@@ -3373,39 +3186,53 @@
|
|
|
3373
3186
|
* - First, the encoder iterates over all "not owned" properties and encodes them.
|
|
3374
3187
|
* - Then, the encoder iterates over all "owned" properties per instance and encodes them.
|
|
3375
3188
|
*/
|
|
3376
|
-
|
|
3189
|
+
static [(_a = $encoder, _b = $decoder, $filter)](ref, index, view) {
|
|
3377
3190
|
return (!view ||
|
|
3378
3191
|
typeof (ref[$childType]) === "string" ||
|
|
3379
3192
|
view.items.has(ref[$getByIndex](index)[$changes]));
|
|
3380
|
-
}
|
|
3381
|
-
|
|
3193
|
+
}
|
|
3194
|
+
static is(type) {
|
|
3382
3195
|
return type['set'] !== undefined;
|
|
3383
|
-
}
|
|
3384
|
-
|
|
3385
|
-
|
|
3196
|
+
}
|
|
3197
|
+
constructor(initialValues) {
|
|
3198
|
+
this.$items = new Map();
|
|
3199
|
+
this.$indexes = new Map();
|
|
3200
|
+
this.$refId = 0;
|
|
3201
|
+
this[$changes] = new ChangeTree(this);
|
|
3202
|
+
if (initialValues) {
|
|
3203
|
+
initialValues.forEach((v) => this.add(v));
|
|
3204
|
+
}
|
|
3205
|
+
Object.defineProperty(this, $childType, {
|
|
3206
|
+
value: undefined,
|
|
3207
|
+
enumerable: false,
|
|
3208
|
+
writable: true,
|
|
3209
|
+
configurable: true,
|
|
3210
|
+
});
|
|
3211
|
+
}
|
|
3212
|
+
add(value) {
|
|
3386
3213
|
// immediatelly return false if value already added.
|
|
3387
3214
|
if (this.has(value)) {
|
|
3388
3215
|
return false;
|
|
3389
3216
|
}
|
|
3390
3217
|
// set "index" for reference.
|
|
3391
|
-
|
|
3218
|
+
const index = this.$refId++;
|
|
3392
3219
|
if ((value[$changes]) !== undefined) {
|
|
3393
3220
|
value[$changes].setParent(this, this[$changes].root, index);
|
|
3394
3221
|
}
|
|
3395
|
-
|
|
3222
|
+
const operation = this[$changes].indexes[index]?.op ?? exports.OPERATION.ADD;
|
|
3396
3223
|
this[$changes].indexes[index] = index;
|
|
3397
3224
|
this.$indexes.set(index, index);
|
|
3398
3225
|
this.$items.set(index, value);
|
|
3399
3226
|
this[$changes].change(index, operation);
|
|
3400
3227
|
return index;
|
|
3401
|
-
}
|
|
3402
|
-
|
|
3228
|
+
}
|
|
3229
|
+
entries() {
|
|
3403
3230
|
return this.$items.entries();
|
|
3404
|
-
}
|
|
3405
|
-
|
|
3406
|
-
|
|
3407
|
-
|
|
3408
|
-
|
|
3231
|
+
}
|
|
3232
|
+
delete(item) {
|
|
3233
|
+
const entries = this.$items.entries();
|
|
3234
|
+
let index;
|
|
3235
|
+
let entry;
|
|
3409
3236
|
while (entry = entries.next()) {
|
|
3410
3237
|
if (entry.done) {
|
|
3411
3238
|
break;
|
|
@@ -3421,9 +3248,9 @@
|
|
|
3421
3248
|
this[$changes].delete(index);
|
|
3422
3249
|
this.$indexes.delete(index);
|
|
3423
3250
|
return this.$items.delete(index);
|
|
3424
|
-
}
|
|
3425
|
-
|
|
3426
|
-
|
|
3251
|
+
}
|
|
3252
|
+
clear() {
|
|
3253
|
+
const changeTree = this[$changes];
|
|
3427
3254
|
// discard previous operations.
|
|
3428
3255
|
changeTree.discard(true);
|
|
3429
3256
|
changeTree.indexes = {};
|
|
@@ -3432,11 +3259,11 @@
|
|
|
3432
3259
|
// clear items
|
|
3433
3260
|
this.$items.clear();
|
|
3434
3261
|
changeTree.operation(exports.OPERATION.CLEAR);
|
|
3435
|
-
}
|
|
3436
|
-
|
|
3437
|
-
|
|
3438
|
-
|
|
3439
|
-
|
|
3262
|
+
}
|
|
3263
|
+
has(value) {
|
|
3264
|
+
const values = this.$items.values();
|
|
3265
|
+
let has = false;
|
|
3266
|
+
let entry;
|
|
3440
3267
|
while (entry = values.next()) {
|
|
3441
3268
|
if (entry.done) {
|
|
3442
3269
|
break;
|
|
@@ -3447,56 +3274,51 @@
|
|
|
3447
3274
|
}
|
|
3448
3275
|
}
|
|
3449
3276
|
return has;
|
|
3450
|
-
}
|
|
3451
|
-
|
|
3452
|
-
|
|
3453
|
-
|
|
3454
|
-
|
|
3455
|
-
SetSchema.prototype.values = function () {
|
|
3277
|
+
}
|
|
3278
|
+
forEach(callbackfn) {
|
|
3279
|
+
this.$items.forEach((value, key, _) => callbackfn(value, key, this));
|
|
3280
|
+
}
|
|
3281
|
+
values() {
|
|
3456
3282
|
return this.$items.values();
|
|
3457
|
-
}
|
|
3458
|
-
|
|
3459
|
-
|
|
3460
|
-
|
|
3461
|
-
},
|
|
3462
|
-
enumerable: false,
|
|
3463
|
-
configurable: true
|
|
3464
|
-
});
|
|
3283
|
+
}
|
|
3284
|
+
get size() {
|
|
3285
|
+
return this.$items.size;
|
|
3286
|
+
}
|
|
3465
3287
|
/** Iterator */
|
|
3466
|
-
|
|
3288
|
+
[Symbol.iterator]() {
|
|
3467
3289
|
return this.$items.values();
|
|
3468
|
-
}
|
|
3469
|
-
|
|
3290
|
+
}
|
|
3291
|
+
setIndex(index, key) {
|
|
3470
3292
|
this.$indexes.set(index, key);
|
|
3471
|
-
}
|
|
3472
|
-
|
|
3293
|
+
}
|
|
3294
|
+
getIndex(index) {
|
|
3473
3295
|
return this.$indexes.get(index);
|
|
3474
|
-
}
|
|
3475
|
-
|
|
3296
|
+
}
|
|
3297
|
+
[$getByIndex](index) {
|
|
3476
3298
|
return this.$items.get(this.$indexes.get(index));
|
|
3477
|
-
}
|
|
3478
|
-
|
|
3479
|
-
|
|
3299
|
+
}
|
|
3300
|
+
[$deleteByIndex](index) {
|
|
3301
|
+
const key = this.$indexes.get(index);
|
|
3480
3302
|
this.$items.delete(key);
|
|
3481
3303
|
this.$indexes.delete(index);
|
|
3482
|
-
}
|
|
3483
|
-
|
|
3304
|
+
}
|
|
3305
|
+
toArray() {
|
|
3484
3306
|
return Array.from(this.$items.values());
|
|
3485
|
-
}
|
|
3486
|
-
|
|
3487
|
-
|
|
3488
|
-
this.forEach(
|
|
3307
|
+
}
|
|
3308
|
+
toJSON() {
|
|
3309
|
+
const values = [];
|
|
3310
|
+
this.forEach((value, key) => {
|
|
3489
3311
|
values.push((typeof (value['toJSON']) === "function")
|
|
3490
3312
|
? value['toJSON']()
|
|
3491
3313
|
: value);
|
|
3492
3314
|
});
|
|
3493
3315
|
return values;
|
|
3494
|
-
}
|
|
3316
|
+
}
|
|
3495
3317
|
//
|
|
3496
3318
|
// Decoding utilities
|
|
3497
3319
|
//
|
|
3498
|
-
|
|
3499
|
-
|
|
3320
|
+
clone(isDecoding) {
|
|
3321
|
+
let cloned;
|
|
3500
3322
|
if (isDecoding) {
|
|
3501
3323
|
// client-side
|
|
3502
3324
|
cloned = Object.assign(new SetSchema(), this);
|
|
@@ -3504,7 +3326,7 @@
|
|
|
3504
3326
|
else {
|
|
3505
3327
|
// server-side
|
|
3506
3328
|
cloned = new SetSchema();
|
|
3507
|
-
this.forEach(
|
|
3329
|
+
this.forEach((value) => {
|
|
3508
3330
|
if (value[$changes]) {
|
|
3509
3331
|
cloned.add(value['clone']());
|
|
3510
3332
|
}
|
|
@@ -3514,16 +3336,40 @@
|
|
|
3514
3336
|
});
|
|
3515
3337
|
}
|
|
3516
3338
|
return cloned;
|
|
3517
|
-
}
|
|
3518
|
-
|
|
3519
|
-
SetSchema[_a] = encodeKeyValueOperation;
|
|
3520
|
-
SetSchema[_b] = decodeKeyValueOperation;
|
|
3521
|
-
return SetSchema;
|
|
3522
|
-
}());
|
|
3339
|
+
}
|
|
3340
|
+
}
|
|
3523
3341
|
registerType("set", { constructor: SetSchema });
|
|
3524
3342
|
|
|
3525
|
-
|
|
3526
|
-
|
|
3343
|
+
/******************************************************************************
|
|
3344
|
+
Copyright (c) Microsoft Corporation.
|
|
3345
|
+
|
|
3346
|
+
Permission to use, copy, modify, and/or distribute this software for any
|
|
3347
|
+
purpose with or without fee is hereby granted.
|
|
3348
|
+
|
|
3349
|
+
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
|
3350
|
+
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
|
3351
|
+
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
|
3352
|
+
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
|
3353
|
+
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
|
3354
|
+
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
|
3355
|
+
PERFORMANCE OF THIS SOFTWARE.
|
|
3356
|
+
***************************************************************************** */
|
|
3357
|
+
|
|
3358
|
+
function __decorate(decorators, target, key, desc) {
|
|
3359
|
+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
|
3360
|
+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
|
3361
|
+
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
|
3362
|
+
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
|
3363
|
+
}
|
|
3364
|
+
|
|
3365
|
+
typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
|
|
3366
|
+
var e = new Error(message);
|
|
3367
|
+
return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
|
|
3368
|
+
};
|
|
3369
|
+
|
|
3370
|
+
class Encoder {
|
|
3371
|
+
static { this.BUFFER_SIZE = 8 * 1024; } // 8KB
|
|
3372
|
+
constructor(root) {
|
|
3527
3373
|
this.sharedBuffer = Buffer.allocUnsafeSlow(Encoder.BUFFER_SIZE);
|
|
3528
3374
|
this.setRoot(root);
|
|
3529
3375
|
//
|
|
@@ -3536,26 +3382,22 @@
|
|
|
3536
3382
|
// console.log("type:", id, schema.name, Object.keys(schema[Symbol.metadata]));
|
|
3537
3383
|
// });
|
|
3538
3384
|
}
|
|
3539
|
-
|
|
3540
|
-
this
|
|
3385
|
+
setRoot(state) {
|
|
3386
|
+
this.root = new Root();
|
|
3541
3387
|
this.state = state;
|
|
3542
|
-
state[$changes].setRoot(this
|
|
3543
|
-
}
|
|
3544
|
-
|
|
3545
|
-
|
|
3546
|
-
|
|
3547
|
-
|
|
3548
|
-
|
|
3549
|
-
|
|
3550
|
-
|
|
3551
|
-
|
|
3552
|
-
|
|
3553
|
-
|
|
3554
|
-
|
|
3555
|
-
var ref = changeTree.ref;
|
|
3556
|
-
var ctor = ref['constructor'];
|
|
3557
|
-
var encoder = ctor[$encoder];
|
|
3558
|
-
var filter = ctor[$filter];
|
|
3388
|
+
state[$changes].setRoot(this.root);
|
|
3389
|
+
}
|
|
3390
|
+
encode(it = { offset: 0 }, view, buffer = this.sharedBuffer, changeTrees = this.root.changes) {
|
|
3391
|
+
const initialOffset = it.offset; // cache current offset in case we need to resize the buffer
|
|
3392
|
+
const isEncodeAll = this.root.allChanges === changeTrees;
|
|
3393
|
+
const hasView = (view !== undefined);
|
|
3394
|
+
const rootChangeTree = this.state[$changes];
|
|
3395
|
+
const changeTreesIterator = changeTrees.entries();
|
|
3396
|
+
for (const [changeTree, changes] of changeTreesIterator) {
|
|
3397
|
+
const ref = changeTree.ref;
|
|
3398
|
+
const ctor = ref['constructor'];
|
|
3399
|
+
const encoder = ctor[$encoder];
|
|
3400
|
+
const filter = ctor[$filter];
|
|
3559
3401
|
if (hasView) {
|
|
3560
3402
|
if (!view.items.has(changeTree)) {
|
|
3561
3403
|
view.invisible.add(changeTree);
|
|
@@ -3567,12 +3409,11 @@
|
|
|
3567
3409
|
}
|
|
3568
3410
|
// skip root `refId` if it's the first change tree
|
|
3569
3411
|
if (it.offset !== initialOffset || changeTree !== rootChangeTree) {
|
|
3570
|
-
|
|
3571
|
-
number$1(
|
|
3412
|
+
buffer[it.offset++] = SWITCH_TO_STRUCTURE & 255;
|
|
3413
|
+
number$1(buffer, changeTree.refId, it);
|
|
3572
3414
|
}
|
|
3573
|
-
|
|
3574
|
-
for (
|
|
3575
|
-
var _c = changesIterator_1[_b], fieldIndex = _c[0], operation = _c[1];
|
|
3415
|
+
const changesIterator = changes.entries();
|
|
3416
|
+
for (const [fieldIndex, operation] of changesIterator) {
|
|
3576
3417
|
//
|
|
3577
3418
|
// first pass (encodeAll), identify "filtered" operations without encoding them
|
|
3578
3419
|
// they will be encoded per client, based on their view.
|
|
@@ -3591,17 +3432,21 @@
|
|
|
3591
3432
|
// fieldIndex,
|
|
3592
3433
|
// operation: OPERATION[operation],
|
|
3593
3434
|
// });
|
|
3594
|
-
encoder(this,
|
|
3435
|
+
encoder(this, buffer, changeTree, fieldIndex, operation, it, isEncodeAll, hasView);
|
|
3595
3436
|
}
|
|
3596
3437
|
}
|
|
3597
|
-
if (it.offset >
|
|
3598
|
-
|
|
3599
|
-
console.warn("@colyseus/schema encode buffer overflow. Current buffer size: " +
|
|
3438
|
+
if (it.offset > buffer.byteLength) {
|
|
3439
|
+
const newSize = getNextPowerOf2(buffer.byteLength * 2);
|
|
3440
|
+
console.warn("@colyseus/schema encode buffer overflow. Current buffer size: " + buffer.byteLength + ", encoding offset: " + it.offset + ", new size: " + newSize);
|
|
3600
3441
|
//
|
|
3601
3442
|
// resize buffer and re-encode (TODO: can we avoid re-encoding here?)
|
|
3602
3443
|
//
|
|
3603
|
-
|
|
3604
|
-
|
|
3444
|
+
buffer = Buffer.allocUnsafeSlow(newSize);
|
|
3445
|
+
// assign resized buffer to local sharedBuffer
|
|
3446
|
+
if (buffer === this.sharedBuffer) {
|
|
3447
|
+
this.sharedBuffer = buffer;
|
|
3448
|
+
}
|
|
3449
|
+
return this.encode({ offset: initialOffset }, view, buffer);
|
|
3605
3450
|
}
|
|
3606
3451
|
else {
|
|
3607
3452
|
//
|
|
@@ -3613,62 +3458,56 @@
|
|
|
3613
3458
|
//
|
|
3614
3459
|
this.onEndEncode(changeTrees);
|
|
3615
3460
|
}
|
|
3616
|
-
|
|
3617
|
-
return bytes.slice(0, it.offset);
|
|
3461
|
+
return buffer.subarray(0, it.offset);
|
|
3618
3462
|
}
|
|
3619
|
-
}
|
|
3620
|
-
|
|
3621
|
-
// console.log(`encodeAll(), this
|
|
3622
|
-
|
|
3623
|
-
//
|
|
3624
|
-
// console.log("->", item[0].refId, item[0].ref.toJSON());
|
|
3463
|
+
}
|
|
3464
|
+
encodeAll(it = { offset: 0 }, buffer = this.sharedBuffer) {
|
|
3465
|
+
// console.log(`encodeAll(), this.root.allChanges (${this.root.allChanges.size})`);
|
|
3466
|
+
// Array.from(this.root.allChanges.entries()).map((item) => {
|
|
3467
|
+
// console.log("->", { ref: item[0].ref.constructor.name, refId: item[0].refId, changes: item[1].size });
|
|
3625
3468
|
// });
|
|
3626
|
-
return this.encode(it, undefined,
|
|
3627
|
-
}
|
|
3628
|
-
|
|
3629
|
-
|
|
3630
|
-
|
|
3631
|
-
// console.log(`encodeAllView(), this.$root.allFilteredChanges (${this.$root.allFilteredChanges.size})`);
|
|
3469
|
+
return this.encode(it, undefined, buffer, this.root.allChanges);
|
|
3470
|
+
}
|
|
3471
|
+
encodeAllView(view, sharedOffset, it, bytes = this.sharedBuffer) {
|
|
3472
|
+
const viewOffset = it.offset;
|
|
3473
|
+
// console.log(`encodeAllView(), this.root.allFilteredChanges (${this.root.allFilteredChanges.size})`);
|
|
3632
3474
|
// this.debugAllFilteredChanges();
|
|
3633
3475
|
// try to encode "filtered" changes
|
|
3634
|
-
this.encode(it, view, bytes, this
|
|
3476
|
+
this.encode(it, view, bytes, this.root.allFilteredChanges);
|
|
3635
3477
|
return Buffer.concat([
|
|
3636
|
-
bytes.
|
|
3637
|
-
bytes.
|
|
3478
|
+
bytes.subarray(0, sharedOffset),
|
|
3479
|
+
bytes.subarray(viewOffset, it.offset)
|
|
3638
3480
|
]);
|
|
3639
|
-
}
|
|
3640
|
-
|
|
3641
|
-
|
|
3642
|
-
|
|
3643
|
-
|
|
3644
|
-
|
|
3645
|
-
|
|
3646
|
-
|
|
3647
|
-
|
|
3648
|
-
|
|
3649
|
-
|
|
3650
|
-
|
|
3651
|
-
|
|
3652
|
-
var viewOffset = it.offset;
|
|
3481
|
+
}
|
|
3482
|
+
debugAllFilteredChanges() {
|
|
3483
|
+
Array.from(this.root.allFilteredChanges.entries()).map((item) => {
|
|
3484
|
+
console.log("->", { refId: item[0].refId, changes: item[1].size }, item[0].ref.toJSON());
|
|
3485
|
+
if (Array.isArray(item[0].ref.toJSON())) {
|
|
3486
|
+
item[1].forEach((op, key) => {
|
|
3487
|
+
console.log(" ->", { key, op: exports.OPERATION[op] });
|
|
3488
|
+
});
|
|
3489
|
+
}
|
|
3490
|
+
});
|
|
3491
|
+
}
|
|
3492
|
+
encodeView(view, sharedOffset, it, bytes = this.sharedBuffer) {
|
|
3493
|
+
const viewOffset = it.offset;
|
|
3653
3494
|
// try to encode "filtered" changes
|
|
3654
|
-
this.encode(it, view, bytes, this
|
|
3495
|
+
this.encode(it, view, bytes, this.root.filteredChanges);
|
|
3655
3496
|
// encode visibility changes (add/remove for this view)
|
|
3656
|
-
|
|
3657
|
-
for (
|
|
3658
|
-
var _a = viewChangesIterator_1[_i], changeTree = _a[0], changes = _a[1];
|
|
3497
|
+
const viewChangesIterator = view.changes.entries();
|
|
3498
|
+
for (const [changeTree, changes] of viewChangesIterator) {
|
|
3659
3499
|
if (changes.size === 0) {
|
|
3660
3500
|
// FIXME: avoid having empty changes if no changes were made
|
|
3661
3501
|
// console.log("changes.size === 0", changeTree.ref.constructor.name);
|
|
3662
3502
|
continue;
|
|
3663
3503
|
}
|
|
3664
|
-
|
|
3665
|
-
|
|
3666
|
-
|
|
3504
|
+
const ref = changeTree.ref;
|
|
3505
|
+
const ctor = ref['constructor'];
|
|
3506
|
+
const encoder = ctor[$encoder];
|
|
3667
3507
|
bytes[it.offset++] = SWITCH_TO_STRUCTURE & 255;
|
|
3668
3508
|
number$1(bytes, changeTree.refId, it);
|
|
3669
|
-
|
|
3670
|
-
for (
|
|
3671
|
-
var _c = changesIterator_2[_b], fieldIndex = _c[0], operation = _c[1];
|
|
3509
|
+
const changesIterator = changes.entries();
|
|
3510
|
+
for (const [fieldIndex, operation] of changesIterator) {
|
|
3672
3511
|
// isEncodeAll = false
|
|
3673
3512
|
// hasView = true
|
|
3674
3513
|
encoder(this, bytes, changeTree, fieldIndex, operation, it, false, true);
|
|
@@ -3681,66 +3520,59 @@
|
|
|
3681
3520
|
// clear "view" changes after encoding
|
|
3682
3521
|
view.changes.clear();
|
|
3683
3522
|
return Buffer.concat([
|
|
3684
|
-
bytes.
|
|
3685
|
-
bytes.
|
|
3523
|
+
bytes.subarray(0, sharedOffset),
|
|
3524
|
+
bytes.subarray(viewOffset, it.offset)
|
|
3686
3525
|
]);
|
|
3687
|
-
}
|
|
3688
|
-
|
|
3689
|
-
|
|
3690
|
-
|
|
3691
|
-
for (var _i = 0, changeTreesIterator_2 = changeTreesIterator; _i < changeTreesIterator_2.length; _i++) {
|
|
3692
|
-
var _a = changeTreesIterator_2[_i], changeTree = _a[0]; _a[1];
|
|
3526
|
+
}
|
|
3527
|
+
onEndEncode(changeTrees = this.root.changes) {
|
|
3528
|
+
const changeTreesIterator = changeTrees.entries();
|
|
3529
|
+
for (const [changeTree, _] of changeTreesIterator) {
|
|
3693
3530
|
changeTree.endEncode();
|
|
3694
3531
|
}
|
|
3695
|
-
}
|
|
3696
|
-
|
|
3532
|
+
}
|
|
3533
|
+
discardChanges() {
|
|
3697
3534
|
// discard shared changes
|
|
3698
|
-
if (this
|
|
3699
|
-
this.onEndEncode(this
|
|
3700
|
-
this
|
|
3535
|
+
if (this.root.changes.size > 0) {
|
|
3536
|
+
this.onEndEncode(this.root.changes);
|
|
3537
|
+
this.root.changes.clear();
|
|
3701
3538
|
}
|
|
3702
3539
|
// discard filtered changes
|
|
3703
|
-
if (this
|
|
3704
|
-
this.onEndEncode(this
|
|
3705
|
-
this
|
|
3540
|
+
if (this.root.filteredChanges.size > 0) {
|
|
3541
|
+
this.onEndEncode(this.root.filteredChanges);
|
|
3542
|
+
this.root.filteredChanges.clear();
|
|
3706
3543
|
}
|
|
3707
|
-
}
|
|
3708
|
-
|
|
3709
|
-
|
|
3710
|
-
|
|
3544
|
+
}
|
|
3545
|
+
tryEncodeTypeId(bytes, baseType, targetType, it) {
|
|
3546
|
+
const baseTypeId = this.context.getTypeId(baseType);
|
|
3547
|
+
const targetTypeId = this.context.getTypeId(targetType);
|
|
3711
3548
|
if (baseTypeId !== targetTypeId) {
|
|
3712
3549
|
bytes[it.offset++] = TYPE_ID & 255;
|
|
3713
3550
|
number$1(bytes, targetTypeId, it);
|
|
3714
3551
|
}
|
|
3715
|
-
}
|
|
3716
|
-
|
|
3717
|
-
return Encoder;
|
|
3718
|
-
}());
|
|
3552
|
+
}
|
|
3553
|
+
}
|
|
3719
3554
|
|
|
3720
3555
|
function spliceOne(arr, index) {
|
|
3721
3556
|
// manually splice an array
|
|
3722
3557
|
if (index === -1 || index >= arr.length) {
|
|
3723
3558
|
return false;
|
|
3724
3559
|
}
|
|
3725
|
-
|
|
3726
|
-
for (
|
|
3560
|
+
const len = arr.length - 1;
|
|
3561
|
+
for (let i = index; i < len; i++) {
|
|
3727
3562
|
arr[i] = arr[i + 1];
|
|
3728
3563
|
}
|
|
3729
3564
|
arr.length = len;
|
|
3730
3565
|
return true;
|
|
3731
3566
|
}
|
|
3732
3567
|
|
|
3733
|
-
|
|
3734
|
-
|
|
3735
|
-
|
|
3736
|
-
|
|
3737
|
-
|
|
3738
|
-
|
|
3739
|
-
|
|
3740
|
-
|
|
3741
|
-
}(Error));
|
|
3742
|
-
var ReferenceTracker = /** @class */ (function () {
|
|
3743
|
-
function ReferenceTracker() {
|
|
3568
|
+
class DecodingWarning extends Error {
|
|
3569
|
+
constructor(message) {
|
|
3570
|
+
super(message);
|
|
3571
|
+
this.name = "DecodingWarning";
|
|
3572
|
+
}
|
|
3573
|
+
}
|
|
3574
|
+
class ReferenceTracker {
|
|
3575
|
+
constructor() {
|
|
3744
3576
|
//
|
|
3745
3577
|
// Relation of refId => Schema structure
|
|
3746
3578
|
// For direct access of structures during decoding time.
|
|
@@ -3752,12 +3584,11 @@
|
|
|
3752
3584
|
this.callbacks = {};
|
|
3753
3585
|
this.nextUniqueId = 0;
|
|
3754
3586
|
}
|
|
3755
|
-
|
|
3587
|
+
getNextUniqueId() {
|
|
3756
3588
|
return this.nextUniqueId++;
|
|
3757
|
-
}
|
|
3589
|
+
}
|
|
3758
3590
|
// for decoding
|
|
3759
|
-
|
|
3760
|
-
if (incrementCount === void 0) { incrementCount = true; }
|
|
3591
|
+
addRef(refId, ref, incrementCount = true) {
|
|
3761
3592
|
this.refs.set(refId, ref);
|
|
3762
3593
|
this.refIds.set(ref, refId);
|
|
3763
3594
|
if (incrementCount) {
|
|
@@ -3766,10 +3597,10 @@
|
|
|
3766
3597
|
if (this.deletedRefs.has(refId)) {
|
|
3767
3598
|
this.deletedRefs.delete(refId);
|
|
3768
3599
|
}
|
|
3769
|
-
}
|
|
3600
|
+
}
|
|
3770
3601
|
// for decoding
|
|
3771
|
-
|
|
3772
|
-
|
|
3602
|
+
removeRef(refId) {
|
|
3603
|
+
const refCount = this.refCounts[refId];
|
|
3773
3604
|
if (refCount === undefined) {
|
|
3774
3605
|
try {
|
|
3775
3606
|
throw new DecodingWarning("trying to remove refId that doesn't exist");
|
|
@@ -3781,8 +3612,8 @@
|
|
|
3781
3612
|
}
|
|
3782
3613
|
if (refCount === 0) {
|
|
3783
3614
|
try {
|
|
3784
|
-
|
|
3785
|
-
throw new DecodingWarning(
|
|
3615
|
+
const ref = this.refs.get(refId);
|
|
3616
|
+
throw new DecodingWarning(`trying to remove refId '${refId}' with 0 refCount (${ref.constructor.name}: ${JSON.stringify(ref)})`);
|
|
3786
3617
|
}
|
|
3787
3618
|
catch (e) {
|
|
3788
3619
|
console.warn(e);
|
|
@@ -3792,55 +3623,53 @@
|
|
|
3792
3623
|
if ((this.refCounts[refId] = refCount - 1) <= 0) {
|
|
3793
3624
|
this.deletedRefs.add(refId);
|
|
3794
3625
|
}
|
|
3795
|
-
}
|
|
3796
|
-
|
|
3626
|
+
}
|
|
3627
|
+
clearRefs() {
|
|
3797
3628
|
this.refs.clear();
|
|
3798
3629
|
this.deletedRefs.clear();
|
|
3799
3630
|
this.refCounts = {};
|
|
3800
|
-
}
|
|
3631
|
+
}
|
|
3801
3632
|
// for decoding
|
|
3802
|
-
|
|
3803
|
-
|
|
3804
|
-
this.deletedRefs.forEach(function (refId) {
|
|
3633
|
+
garbageCollectDeletedRefs() {
|
|
3634
|
+
this.deletedRefs.forEach((refId) => {
|
|
3805
3635
|
//
|
|
3806
3636
|
// Skip active references.
|
|
3807
3637
|
//
|
|
3808
|
-
if (
|
|
3638
|
+
if (this.refCounts[refId] > 0) {
|
|
3809
3639
|
return;
|
|
3810
3640
|
}
|
|
3811
|
-
|
|
3641
|
+
const ref = this.refs.get(refId);
|
|
3812
3642
|
//
|
|
3813
3643
|
// Ensure child schema instances have their references removed as well.
|
|
3814
3644
|
//
|
|
3815
3645
|
if (Metadata.isValidInstance(ref)) {
|
|
3816
|
-
|
|
3817
|
-
for (
|
|
3818
|
-
|
|
3646
|
+
const metadata = ref['constructor'][Symbol.metadata];
|
|
3647
|
+
for (const field in metadata) {
|
|
3648
|
+
const childRefId = typeof (ref[field]) === "object" && this.refIds.get(ref[field]);
|
|
3819
3649
|
if (childRefId) {
|
|
3820
|
-
|
|
3650
|
+
this.removeRef(childRefId);
|
|
3821
3651
|
}
|
|
3822
3652
|
}
|
|
3823
3653
|
}
|
|
3824
3654
|
else {
|
|
3825
3655
|
if (typeof (Object.values(ref[$childType])[0]) === "function") {
|
|
3826
3656
|
Array.from(ref.values())
|
|
3827
|
-
.forEach(
|
|
3657
|
+
.forEach((child) => this.removeRef(this.refIds.get(child)));
|
|
3828
3658
|
}
|
|
3829
3659
|
}
|
|
3830
|
-
|
|
3831
|
-
delete
|
|
3832
|
-
delete
|
|
3660
|
+
this.refs.delete(refId); // remove ref
|
|
3661
|
+
delete this.refCounts[refId]; // remove ref count
|
|
3662
|
+
delete this.callbacks[refId]; // remove callbacks
|
|
3833
3663
|
});
|
|
3834
3664
|
// clear deleted refs.
|
|
3835
3665
|
this.deletedRefs.clear();
|
|
3836
|
-
}
|
|
3837
|
-
|
|
3838
|
-
var _this = this;
|
|
3666
|
+
}
|
|
3667
|
+
addCallback(refId, fieldOrOperation, callback) {
|
|
3839
3668
|
if (refId === undefined) {
|
|
3840
|
-
|
|
3669
|
+
const name = (typeof (fieldOrOperation) === "number")
|
|
3841
3670
|
? exports.OPERATION[fieldOrOperation]
|
|
3842
3671
|
: fieldOrOperation;
|
|
3843
|
-
throw new Error(
|
|
3672
|
+
throw new Error(`Can't addCallback on '${name}' (refId is undefined)`);
|
|
3844
3673
|
}
|
|
3845
3674
|
if (!this.callbacks[refId]) {
|
|
3846
3675
|
this.callbacks[refId] = {};
|
|
@@ -3849,20 +3678,18 @@
|
|
|
3849
3678
|
this.callbacks[refId][fieldOrOperation] = [];
|
|
3850
3679
|
}
|
|
3851
3680
|
this.callbacks[refId][fieldOrOperation].push(callback);
|
|
3852
|
-
return
|
|
3853
|
-
}
|
|
3854
|
-
|
|
3855
|
-
|
|
3856
|
-
var index = (_c = (_b = (_a = this.callbacks) === null || _a === void 0 ? void 0 : _a[refId]) === null || _b === void 0 ? void 0 : _b[field]) === null || _c === void 0 ? void 0 : _c.indexOf(callback);
|
|
3681
|
+
return () => this.removeCallback(refId, fieldOrOperation, callback);
|
|
3682
|
+
}
|
|
3683
|
+
removeCallback(refId, field, callback) {
|
|
3684
|
+
const index = this.callbacks?.[refId]?.[field]?.indexOf(callback);
|
|
3857
3685
|
if (index !== -1) {
|
|
3858
3686
|
spliceOne(this.callbacks[refId][field], index);
|
|
3859
3687
|
}
|
|
3860
|
-
}
|
|
3861
|
-
|
|
3862
|
-
}());
|
|
3688
|
+
}
|
|
3689
|
+
}
|
|
3863
3690
|
|
|
3864
|
-
|
|
3865
|
-
|
|
3691
|
+
class Decoder {
|
|
3692
|
+
constructor(root, context) {
|
|
3866
3693
|
this.currentRefId = 0;
|
|
3867
3694
|
this.setRoot(root);
|
|
3868
3695
|
this.context = context || new TypeContext(root.constructor);
|
|
@@ -3871,19 +3698,16 @@
|
|
|
3871
3698
|
// console.log("type:", id, schema.name, Object.keys(schema[Symbol.metadata]));
|
|
3872
3699
|
// });
|
|
3873
3700
|
}
|
|
3874
|
-
|
|
3701
|
+
setRoot(root) {
|
|
3875
3702
|
this.state = root;
|
|
3876
|
-
this
|
|
3877
|
-
this
|
|
3878
|
-
}
|
|
3879
|
-
|
|
3880
|
-
|
|
3881
|
-
|
|
3882
|
-
|
|
3883
|
-
|
|
3884
|
-
var $root = this.$root;
|
|
3885
|
-
var totalBytes = bytes.byteLength;
|
|
3886
|
-
var decoder = ref['constructor'][$decoder];
|
|
3703
|
+
this.root = new ReferenceTracker();
|
|
3704
|
+
this.root.addRef(0, root);
|
|
3705
|
+
}
|
|
3706
|
+
decode(bytes, it = { offset: 0 }, ref = this.state) {
|
|
3707
|
+
const allChanges = [];
|
|
3708
|
+
const $root = this.root;
|
|
3709
|
+
const totalBytes = bytes.byteLength;
|
|
3710
|
+
let decoder = ref['constructor'][$decoder];
|
|
3887
3711
|
this.currentRefId = 0;
|
|
3888
3712
|
while (it.offset < totalBytes) {
|
|
3889
3713
|
//
|
|
@@ -3892,26 +3716,26 @@
|
|
|
3892
3716
|
if (bytes[it.offset] == SWITCH_TO_STRUCTURE) {
|
|
3893
3717
|
it.offset++;
|
|
3894
3718
|
this.currentRefId = number(bytes, it);
|
|
3895
|
-
|
|
3719
|
+
const nextRef = $root.refs.get(this.currentRefId);
|
|
3896
3720
|
//
|
|
3897
3721
|
// Trying to access a reference that haven't been decoded yet.
|
|
3898
3722
|
//
|
|
3899
3723
|
if (!nextRef) {
|
|
3900
|
-
throw new Error("
|
|
3724
|
+
throw new Error(`"refId" not found: ${this.currentRefId}`);
|
|
3901
3725
|
}
|
|
3902
|
-
|
|
3726
|
+
ref[$onDecodeEnd]?.();
|
|
3903
3727
|
ref = nextRef;
|
|
3904
3728
|
decoder = ref['constructor'][$decoder];
|
|
3905
3729
|
continue;
|
|
3906
3730
|
}
|
|
3907
|
-
|
|
3731
|
+
const result = decoder(this, bytes, it, ref, allChanges);
|
|
3908
3732
|
if (result === DEFINITION_MISMATCH) {
|
|
3909
3733
|
console.warn("@colyseus/schema: definition mismatch");
|
|
3910
3734
|
//
|
|
3911
3735
|
// keep skipping next bytes until reaches a known structure
|
|
3912
3736
|
// by local decoder.
|
|
3913
3737
|
//
|
|
3914
|
-
|
|
3738
|
+
const nextIterator = { offset: it.offset };
|
|
3915
3739
|
while (it.offset < totalBytes) {
|
|
3916
3740
|
if (switchStructureCheck(bytes, it)) {
|
|
3917
3741
|
nextIterator.offset = it.offset + 1;
|
|
@@ -3925,130 +3749,118 @@
|
|
|
3925
3749
|
}
|
|
3926
3750
|
}
|
|
3927
3751
|
// FIXME: DRY with SWITCH_TO_STRUCTURE block.
|
|
3928
|
-
|
|
3752
|
+
ref[$onDecodeEnd]?.();
|
|
3929
3753
|
// trigger changes
|
|
3930
|
-
|
|
3754
|
+
this.triggerChanges?.(allChanges);
|
|
3931
3755
|
// drop references of unused schemas
|
|
3932
3756
|
$root.garbageCollectDeletedRefs();
|
|
3933
3757
|
return allChanges;
|
|
3934
|
-
}
|
|
3935
|
-
|
|
3936
|
-
|
|
3758
|
+
}
|
|
3759
|
+
getInstanceType(bytes, it, defaultType) {
|
|
3760
|
+
let type;
|
|
3937
3761
|
if (bytes[it.offset] === TYPE_ID) {
|
|
3938
3762
|
it.offset++;
|
|
3939
|
-
|
|
3763
|
+
const type_id = number(bytes, it);
|
|
3940
3764
|
type = this.context.get(type_id);
|
|
3941
3765
|
}
|
|
3942
3766
|
return type || defaultType;
|
|
3943
|
-
}
|
|
3944
|
-
|
|
3767
|
+
}
|
|
3768
|
+
createInstanceOfType(type) {
|
|
3945
3769
|
// let instance: Schema = new (type as any)();
|
|
3946
3770
|
// // assign root on $changes
|
|
3947
3771
|
// instance[$changes].root = this.root[$changes].root;
|
|
3948
3772
|
// return instance;
|
|
3949
3773
|
return new type();
|
|
3950
|
-
}
|
|
3951
|
-
|
|
3952
|
-
|
|
3953
|
-
|
|
3954
|
-
|
|
3955
|
-
|
|
3956
|
-
ref.forEach(function (value, key) {
|
|
3774
|
+
}
|
|
3775
|
+
removeChildRefs(ref, allChanges) {
|
|
3776
|
+
const changeTree = ref[$changes];
|
|
3777
|
+
const needRemoveRef = typeof (ref[$childType]) !== "string";
|
|
3778
|
+
const refId = changeTree.refId;
|
|
3779
|
+
ref.forEach((value, key) => {
|
|
3957
3780
|
allChanges.push({
|
|
3958
3781
|
ref: value,
|
|
3959
|
-
refId
|
|
3782
|
+
refId,
|
|
3960
3783
|
op: exports.OPERATION.DELETE,
|
|
3961
3784
|
field: key,
|
|
3962
3785
|
value: undefined,
|
|
3963
3786
|
previousValue: value
|
|
3964
3787
|
});
|
|
3965
3788
|
if (needRemoveRef) {
|
|
3966
|
-
|
|
3789
|
+
this.root.removeRef(this.root.refIds.get(value));
|
|
3967
3790
|
}
|
|
3968
3791
|
});
|
|
3969
|
-
}
|
|
3970
|
-
|
|
3971
|
-
}());
|
|
3792
|
+
}
|
|
3793
|
+
}
|
|
3972
3794
|
|
|
3973
3795
|
/**
|
|
3974
3796
|
* Reflection
|
|
3975
3797
|
*/
|
|
3976
|
-
|
|
3977
|
-
|
|
3978
|
-
|
|
3979
|
-
|
|
3980
|
-
|
|
3981
|
-
|
|
3982
|
-
|
|
3983
|
-
|
|
3984
|
-
|
|
3985
|
-
|
|
3986
|
-
|
|
3987
|
-
|
|
3988
|
-
|
|
3989
|
-
|
|
3990
|
-
|
|
3991
|
-
|
|
3992
|
-
|
|
3993
|
-
|
|
3994
|
-
|
|
3995
|
-
|
|
3996
|
-
|
|
3997
|
-
|
|
3998
|
-
|
|
3999
|
-
|
|
4000
|
-
|
|
4001
|
-
|
|
4002
|
-
|
|
4003
|
-
|
|
4004
|
-
|
|
4005
|
-
|
|
4006
|
-
|
|
4007
|
-
|
|
4008
|
-
return ReflectionType;
|
|
4009
|
-
}(Schema));
|
|
4010
|
-
var Reflection = /** @class */ (function (_super) {
|
|
4011
|
-
__extends(Reflection, _super);
|
|
4012
|
-
function Reflection() {
|
|
4013
|
-
var _this = _super !== null && _super.apply(this, arguments) || this;
|
|
4014
|
-
_this.types = new ArraySchema();
|
|
4015
|
-
return _this;
|
|
4016
|
-
}
|
|
4017
|
-
Reflection.encode = function (instance, context) {
|
|
3798
|
+
class ReflectionField extends Schema {
|
|
3799
|
+
}
|
|
3800
|
+
__decorate([
|
|
3801
|
+
type("string")
|
|
3802
|
+
], ReflectionField.prototype, "name", void 0);
|
|
3803
|
+
__decorate([
|
|
3804
|
+
type("string")
|
|
3805
|
+
], ReflectionField.prototype, "type", void 0);
|
|
3806
|
+
__decorate([
|
|
3807
|
+
type("number")
|
|
3808
|
+
], ReflectionField.prototype, "referencedType", void 0);
|
|
3809
|
+
class ReflectionType extends Schema {
|
|
3810
|
+
constructor() {
|
|
3811
|
+
super(...arguments);
|
|
3812
|
+
this.fields = new ArraySchema();
|
|
3813
|
+
}
|
|
3814
|
+
}
|
|
3815
|
+
__decorate([
|
|
3816
|
+
type("number")
|
|
3817
|
+
], ReflectionType.prototype, "id", void 0);
|
|
3818
|
+
__decorate([
|
|
3819
|
+
type("number")
|
|
3820
|
+
], ReflectionType.prototype, "extendsId", void 0);
|
|
3821
|
+
__decorate([
|
|
3822
|
+
type([ReflectionField])
|
|
3823
|
+
], ReflectionType.prototype, "fields", void 0);
|
|
3824
|
+
class Reflection extends Schema {
|
|
3825
|
+
constructor() {
|
|
3826
|
+
super(...arguments);
|
|
3827
|
+
this.types = new ArraySchema();
|
|
3828
|
+
}
|
|
3829
|
+
static encode(instance, context, it = { offset: 0 }) {
|
|
4018
3830
|
if (!context) {
|
|
4019
3831
|
context = new TypeContext(instance.constructor);
|
|
4020
3832
|
}
|
|
4021
|
-
|
|
4022
|
-
|
|
4023
|
-
|
|
4024
|
-
for (
|
|
3833
|
+
const reflection = new Reflection();
|
|
3834
|
+
const encoder = new Encoder(reflection);
|
|
3835
|
+
const buildType = (currentType, metadata) => {
|
|
3836
|
+
for (const fieldName in metadata) {
|
|
4025
3837
|
// skip fields from parent classes
|
|
4026
3838
|
if (!Object.prototype.hasOwnProperty.call(metadata, fieldName)) {
|
|
4027
3839
|
continue;
|
|
4028
3840
|
}
|
|
4029
|
-
|
|
3841
|
+
const field = new ReflectionField();
|
|
4030
3842
|
field.name = fieldName;
|
|
4031
|
-
|
|
4032
|
-
|
|
4033
|
-
if (typeof (
|
|
4034
|
-
fieldType =
|
|
3843
|
+
let fieldType;
|
|
3844
|
+
const type = metadata[fieldName].type;
|
|
3845
|
+
if (typeof (type) === "string") {
|
|
3846
|
+
fieldType = type;
|
|
4035
3847
|
}
|
|
4036
3848
|
else {
|
|
4037
|
-
|
|
3849
|
+
let childTypeSchema;
|
|
4038
3850
|
//
|
|
4039
3851
|
// TODO: refactor below.
|
|
4040
3852
|
//
|
|
4041
|
-
if (Schema.is(
|
|
3853
|
+
if (Schema.is(type)) {
|
|
4042
3854
|
fieldType = "ref";
|
|
4043
|
-
childTypeSchema =
|
|
3855
|
+
childTypeSchema = type;
|
|
4044
3856
|
}
|
|
4045
3857
|
else {
|
|
4046
|
-
fieldType = Object.keys(
|
|
4047
|
-
if (typeof (
|
|
4048
|
-
fieldType += ":" +
|
|
3858
|
+
fieldType = Object.keys(type)[0];
|
|
3859
|
+
if (typeof (type[fieldType]) === "string") {
|
|
3860
|
+
fieldType += ":" + type[fieldType]; // array:string
|
|
4049
3861
|
}
|
|
4050
3862
|
else {
|
|
4051
|
-
childTypeSchema =
|
|
3863
|
+
childTypeSchema = type[fieldType];
|
|
4052
3864
|
}
|
|
4053
3865
|
}
|
|
4054
3866
|
field.referencedType = (childTypeSchema)
|
|
@@ -4060,59 +3872,52 @@
|
|
|
4060
3872
|
}
|
|
4061
3873
|
reflection.types.push(currentType);
|
|
4062
3874
|
};
|
|
4063
|
-
for (
|
|
4064
|
-
|
|
4065
|
-
|
|
4066
|
-
|
|
3875
|
+
for (let typeid in context.types) {
|
|
3876
|
+
const klass = context.types[typeid];
|
|
3877
|
+
const type = new ReflectionType();
|
|
3878
|
+
type.id = Number(typeid);
|
|
4067
3879
|
// support inheritance
|
|
4068
|
-
|
|
3880
|
+
const inheritFrom = Object.getPrototypeOf(klass);
|
|
4069
3881
|
if (inheritFrom !== Schema) {
|
|
4070
|
-
|
|
3882
|
+
type.extendsId = context.schemas.get(inheritFrom);
|
|
4071
3883
|
}
|
|
4072
|
-
buildType(
|
|
3884
|
+
buildType(type, klass[Symbol.metadata]);
|
|
4073
3885
|
}
|
|
4074
|
-
|
|
4075
|
-
var buf = encoder.encodeAll(it);
|
|
3886
|
+
const buf = encoder.encodeAll(it);
|
|
4076
3887
|
return Buffer.from(buf, 0, it.offset);
|
|
4077
|
-
}
|
|
4078
|
-
|
|
4079
|
-
|
|
4080
|
-
|
|
3888
|
+
}
|
|
3889
|
+
static decode(bytes, it) {
|
|
3890
|
+
const reflection = new Reflection();
|
|
3891
|
+
const reflectionDecoder = new Decoder(reflection);
|
|
4081
3892
|
reflectionDecoder.decode(bytes, it);
|
|
4082
|
-
|
|
4083
|
-
|
|
4084
|
-
|
|
4085
|
-
|
|
4086
|
-
|
|
4087
|
-
function _() {
|
|
4088
|
-
return _super !== null && _super.apply(this, arguments) || this;
|
|
4089
|
-
}
|
|
4090
|
-
return _;
|
|
4091
|
-
}(parentKlass));
|
|
3893
|
+
const context = new TypeContext();
|
|
3894
|
+
const schemaTypes = reflection.types.reduce((types, reflectionType) => {
|
|
3895
|
+
const parentKlass = types[reflectionType.extendsId] || Schema;
|
|
3896
|
+
const schema = class _ extends parentKlass {
|
|
3897
|
+
};
|
|
4092
3898
|
// const _metadata = Object.create(_classSuper[Symbol.metadata] ?? null);
|
|
4093
|
-
|
|
3899
|
+
const _metadata = parentKlass && parentKlass[Symbol.metadata] || Object.create(null);
|
|
4094
3900
|
Object.defineProperty(schema, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
|
|
4095
3901
|
// register for inheritance support
|
|
4096
3902
|
TypeContext.register(schema);
|
|
4097
|
-
|
|
3903
|
+
const typeid = reflectionType.id;
|
|
4098
3904
|
types[typeid] = schema;
|
|
4099
3905
|
context.add(schema, typeid);
|
|
4100
3906
|
return types;
|
|
4101
3907
|
}, {});
|
|
4102
|
-
reflection.types.forEach(
|
|
4103
|
-
|
|
4104
|
-
|
|
4105
|
-
|
|
4106
|
-
|
|
4107
|
-
reflectionType.fields.forEach(
|
|
4108
|
-
|
|
4109
|
-
var fieldIndex = parentFieldIndex + i;
|
|
3908
|
+
reflection.types.forEach((reflectionType) => {
|
|
3909
|
+
const schemaType = schemaTypes[reflectionType.id];
|
|
3910
|
+
const metadata = schemaType[Symbol.metadata];
|
|
3911
|
+
const parentKlass = reflection.types[reflectionType.extendsId];
|
|
3912
|
+
const parentFieldIndex = parentKlass && parentKlass.fields.length || 0;
|
|
3913
|
+
reflectionType.fields.forEach((field, i) => {
|
|
3914
|
+
const fieldIndex = parentFieldIndex + i;
|
|
4110
3915
|
if (field.referencedType !== undefined) {
|
|
4111
|
-
|
|
4112
|
-
|
|
3916
|
+
let fieldType = field.type;
|
|
3917
|
+
let refType = schemaTypes[field.referencedType];
|
|
4113
3918
|
// map or array of primitive type (-1)
|
|
4114
3919
|
if (!refType) {
|
|
4115
|
-
|
|
3920
|
+
const typeInfo = field.type.split(":");
|
|
4116
3921
|
fieldType = typeInfo[0];
|
|
4117
3922
|
refType = typeInfo[1];
|
|
4118
3923
|
}
|
|
@@ -4122,7 +3927,7 @@
|
|
|
4122
3927
|
}
|
|
4123
3928
|
else {
|
|
4124
3929
|
// type({ [fieldType]: refType } as DefinitionType)(schemaType.prototype, field.name);
|
|
4125
|
-
Metadata.addField(metadata, fieldIndex, field.name,
|
|
3930
|
+
Metadata.addField(metadata, fieldIndex, field.name, { [fieldType]: refType });
|
|
4126
3931
|
}
|
|
4127
3932
|
}
|
|
4128
3933
|
else {
|
|
@@ -4132,15 +3937,14 @@
|
|
|
4132
3937
|
});
|
|
4133
3938
|
});
|
|
4134
3939
|
return new (schemaTypes[0])();
|
|
4135
|
-
}
|
|
4136
|
-
|
|
4137
|
-
|
|
4138
|
-
]
|
|
4139
|
-
|
|
4140
|
-
}(Schema));
|
|
3940
|
+
}
|
|
3941
|
+
}
|
|
3942
|
+
__decorate([
|
|
3943
|
+
type([ReflectionType])
|
|
3944
|
+
], Reflection.prototype, "types", void 0);
|
|
4141
3945
|
|
|
4142
|
-
|
|
4143
|
-
|
|
3946
|
+
class StateView {
|
|
3947
|
+
constructor() {
|
|
4144
3948
|
/**
|
|
4145
3949
|
* List of ChangeTree's that are visible to this view
|
|
4146
3950
|
*/
|
|
@@ -4156,22 +3960,17 @@
|
|
|
4156
3960
|
this.changes = new Map();
|
|
4157
3961
|
}
|
|
4158
3962
|
// TODO: allow to set multiple tags at once
|
|
4159
|
-
|
|
4160
|
-
var _this = this;
|
|
4161
|
-
var _a, _b;
|
|
4162
|
-
if (tag === void 0) { tag = DEFAULT_VIEW_TAG; }
|
|
3963
|
+
add(obj, tag = DEFAULT_VIEW_TAG) {
|
|
4163
3964
|
if (!obj[$changes]) {
|
|
4164
3965
|
console.warn("StateView#add(), invalid object:", obj);
|
|
4165
3966
|
return this;
|
|
4166
3967
|
}
|
|
4167
|
-
|
|
3968
|
+
let changeTree = obj[$changes];
|
|
4168
3969
|
this.items.add(changeTree);
|
|
4169
3970
|
// Add children of this ChangeTree to this view
|
|
4170
|
-
changeTree.forEachChild(
|
|
4171
|
-
return _this.add(change.ref, tag);
|
|
4172
|
-
});
|
|
3971
|
+
changeTree.forEachChild((change, _) => this.add(change.ref, tag));
|
|
4173
3972
|
// FIXME: ArraySchema/MapSchema does not have metadata
|
|
4174
|
-
|
|
3973
|
+
const metadata = obj.constructor[Symbol.metadata];
|
|
4175
3974
|
// add parent ChangeTree's, if they are invisible to this view
|
|
4176
3975
|
// TODO: REFACTOR addParent()
|
|
4177
3976
|
this.addParent(changeTree, tag);
|
|
@@ -4179,7 +3978,7 @@
|
|
|
4179
3978
|
// TODO: when adding an item of a MapSchema, the changes may not
|
|
4180
3979
|
// be set (only the parent's changes are set)
|
|
4181
3980
|
//
|
|
4182
|
-
|
|
3981
|
+
let changes = this.changes.get(changeTree);
|
|
4183
3982
|
if (changes === undefined) {
|
|
4184
3983
|
changes = new Map();
|
|
4185
3984
|
this.changes.set(changeTree, changes);
|
|
@@ -4189,7 +3988,7 @@
|
|
|
4189
3988
|
if (!this.tags) {
|
|
4190
3989
|
this.tags = new WeakMap();
|
|
4191
3990
|
}
|
|
4192
|
-
|
|
3991
|
+
let tags;
|
|
4193
3992
|
if (!this.tags.has(changeTree)) {
|
|
4194
3993
|
tags = new Set();
|
|
4195
3994
|
this.tags.set(changeTree, tags);
|
|
@@ -4200,7 +3999,7 @@
|
|
|
4200
3999
|
tags.add(tag);
|
|
4201
4000
|
// console.log("BY TAG:", tag);
|
|
4202
4001
|
// Ref: add tagged properties
|
|
4203
|
-
|
|
4002
|
+
metadata?.[-3]?.[tag]?.forEach((index) => {
|
|
4204
4003
|
if (changeTree.getChange(index) !== exports.OPERATION.DELETE) {
|
|
4205
4004
|
changes.set(index, exports.OPERATION.ADD);
|
|
4206
4005
|
}
|
|
@@ -4214,14 +4013,13 @@
|
|
|
4214
4013
|
// changes.set(index, OPERATION.ADD);
|
|
4215
4014
|
// }
|
|
4216
4015
|
// });
|
|
4217
|
-
|
|
4016
|
+
const allChangesSet = (changeTree.isFiltered || changeTree.isPartiallyFiltered)
|
|
4218
4017
|
? changeTree.allFilteredChanges
|
|
4219
4018
|
: changeTree.allChanges;
|
|
4220
|
-
|
|
4221
|
-
|
|
4222
|
-
for (
|
|
4223
|
-
|
|
4224
|
-
if ((isInvisible || (metadata === null || metadata === void 0 ? void 0 : metadata[metadata === null || metadata === void 0 ? void 0 : metadata[index]].tag) === tag) &&
|
|
4019
|
+
const it = allChangesSet.keys();
|
|
4020
|
+
const isInvisible = this.invisible.has(changeTree);
|
|
4021
|
+
for (const index of it) {
|
|
4022
|
+
if ((isInvisible || metadata?.[metadata?.[index]].tag === tag) &&
|
|
4225
4023
|
changeTree.getChange(index) !== exports.OPERATION.DELETE) {
|
|
4226
4024
|
changes.set(index, exports.OPERATION.ADD);
|
|
4227
4025
|
}
|
|
@@ -4234,14 +4032,14 @@
|
|
|
4234
4032
|
this.items.add(changeTree);
|
|
4235
4033
|
}
|
|
4236
4034
|
return this;
|
|
4237
|
-
}
|
|
4238
|
-
|
|
4239
|
-
|
|
4035
|
+
}
|
|
4036
|
+
addParent(changeTree, tag) {
|
|
4037
|
+
const parentRef = changeTree.parent;
|
|
4240
4038
|
if (!parentRef) {
|
|
4241
4039
|
return;
|
|
4242
4040
|
}
|
|
4243
|
-
|
|
4244
|
-
|
|
4041
|
+
const parentChangeTree = parentRef[$changes];
|
|
4042
|
+
const parentIndex = changeTree.parentIndex;
|
|
4245
4043
|
if (!this.invisible.has(parentChangeTree)) {
|
|
4246
4044
|
// parent is already available, no need to add it!
|
|
4247
4045
|
return;
|
|
@@ -4249,7 +4047,7 @@
|
|
|
4249
4047
|
this.addParent(parentChangeTree, tag);
|
|
4250
4048
|
// add parent's tag properties
|
|
4251
4049
|
if (parentChangeTree.getChange(parentIndex) !== exports.OPERATION.DELETE) {
|
|
4252
|
-
|
|
4050
|
+
let parentChanges = this.changes.get(parentChangeTree);
|
|
4253
4051
|
if (parentChanges === undefined) {
|
|
4254
4052
|
parentChanges = new Map();
|
|
4255
4053
|
this.changes.set(parentChangeTree, parentChanges);
|
|
@@ -4265,7 +4063,7 @@
|
|
|
4265
4063
|
if (!this.tags) {
|
|
4266
4064
|
this.tags = new WeakMap();
|
|
4267
4065
|
}
|
|
4268
|
-
|
|
4066
|
+
let tags;
|
|
4269
4067
|
if (!this.tags.has(parentChangeTree)) {
|
|
4270
4068
|
tags = new Set();
|
|
4271
4069
|
this.tags.set(parentChangeTree, tags);
|
|
@@ -4276,51 +4074,46 @@
|
|
|
4276
4074
|
tags.add(tag);
|
|
4277
4075
|
parentChanges.set(parentIndex, exports.OPERATION.ADD);
|
|
4278
4076
|
}
|
|
4279
|
-
}
|
|
4280
|
-
|
|
4281
|
-
|
|
4282
|
-
var changeTree = obj[$changes];
|
|
4077
|
+
}
|
|
4078
|
+
remove(obj, tag = DEFAULT_VIEW_TAG) {
|
|
4079
|
+
const changeTree = obj[$changes];
|
|
4283
4080
|
if (!changeTree) {
|
|
4284
4081
|
console.warn("StateView#remove(), invalid object:", obj);
|
|
4285
4082
|
return this;
|
|
4286
4083
|
}
|
|
4287
4084
|
this.items.delete(changeTree);
|
|
4288
|
-
|
|
4289
|
-
|
|
4290
|
-
|
|
4085
|
+
const ref = changeTree.ref;
|
|
4086
|
+
const metadata = ref.constructor[Symbol.metadata];
|
|
4087
|
+
let changes = this.changes.get(changeTree);
|
|
4291
4088
|
if (changes === undefined) {
|
|
4292
4089
|
changes = new Map();
|
|
4293
4090
|
this.changes.set(changeTree, changes);
|
|
4294
4091
|
}
|
|
4295
4092
|
if (tag === DEFAULT_VIEW_TAG) {
|
|
4296
4093
|
// parent is collection (Map/Array)
|
|
4297
|
-
|
|
4094
|
+
const parent = changeTree.parent;
|
|
4298
4095
|
if (!Metadata.isValidInstance(parent)) {
|
|
4299
|
-
|
|
4300
|
-
|
|
4301
|
-
if (
|
|
4302
|
-
|
|
4303
|
-
this.changes.set(parentChangeTree,
|
|
4096
|
+
const parentChangeTree = parent[$changes];
|
|
4097
|
+
let changes = this.changes.get(parentChangeTree);
|
|
4098
|
+
if (changes === undefined) {
|
|
4099
|
+
changes = new Map();
|
|
4100
|
+
this.changes.set(parentChangeTree, changes);
|
|
4304
4101
|
}
|
|
4305
4102
|
// DELETE / DELETE BY REF ID
|
|
4306
|
-
|
|
4103
|
+
changes.set(changeTree.parentIndex, exports.OPERATION.DELETE);
|
|
4307
4104
|
}
|
|
4308
4105
|
else {
|
|
4309
4106
|
// delete all "tagged" properties.
|
|
4310
|
-
metadata[-2].forEach(
|
|
4311
|
-
return changes.set(index, exports.OPERATION.DELETE);
|
|
4312
|
-
});
|
|
4107
|
+
metadata[-2].forEach((index) => changes.set(index, exports.OPERATION.DELETE));
|
|
4313
4108
|
}
|
|
4314
4109
|
}
|
|
4315
4110
|
else {
|
|
4316
4111
|
// delete only tagged properties
|
|
4317
|
-
metadata[-3][tag].forEach(
|
|
4318
|
-
return changes.set(index, exports.OPERATION.DELETE);
|
|
4319
|
-
});
|
|
4112
|
+
metadata[-3][tag].forEach((index) => changes.set(index, exports.OPERATION.DELETE));
|
|
4320
4113
|
}
|
|
4321
4114
|
// remove tag
|
|
4322
4115
|
if (this.tags && this.tags.has(changeTree)) {
|
|
4323
|
-
|
|
4116
|
+
const tags = this.tags.get(changeTree);
|
|
4324
4117
|
if (tag === undefined) {
|
|
4325
4118
|
// delete all tags
|
|
4326
4119
|
this.tags.delete(changeTree);
|
|
@@ -4335,9 +4128,8 @@
|
|
|
4335
4128
|
}
|
|
4336
4129
|
}
|
|
4337
4130
|
return this;
|
|
4338
|
-
}
|
|
4339
|
-
|
|
4340
|
-
}());
|
|
4131
|
+
}
|
|
4132
|
+
}
|
|
4341
4133
|
|
|
4342
4134
|
registerType("map", { constructor: MapSchema });
|
|
4343
4135
|
registerType("array", { constructor: ArraySchema });
|