@colyseus/schema 3.0.0-alpha.1 → 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 +85 -64
- 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 +85 -64
- 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 +3 -2
- 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 +26 -23
package/build/cjs/index.js
CHANGED
|
@@ -168,7 +168,6 @@ class Root {
|
|
|
168
168
|
// pending changes to be encoded
|
|
169
169
|
this.changes = new Map();
|
|
170
170
|
this.filteredChanges = new Map();
|
|
171
|
-
this.views = [];
|
|
172
171
|
}
|
|
173
172
|
getNextUniqueId() {
|
|
174
173
|
return this.nextUniqueId++;
|
|
@@ -263,14 +262,12 @@ class ChangeTree {
|
|
|
263
262
|
this.checkIsFiltered(parent, parentIndex);
|
|
264
263
|
if (!this.isFiltered) {
|
|
265
264
|
this.root.changes.set(this, this.changes);
|
|
265
|
+
this.root.allChanges.set(this, this.allChanges);
|
|
266
266
|
}
|
|
267
267
|
if (this.isFiltered || this.isPartiallyFiltered) {
|
|
268
268
|
this.root.filteredChanges.set(this, this.filteredChanges);
|
|
269
269
|
this.root.allFilteredChanges.set(this, this.filteredChanges);
|
|
270
270
|
}
|
|
271
|
-
else {
|
|
272
|
-
this.root.allChanges.set(this, this.allChanges);
|
|
273
|
-
}
|
|
274
271
|
this.ensureRefId();
|
|
275
272
|
this.forEachChild((changeTree, atIndex) => {
|
|
276
273
|
changeTree.setParent(this.ref, root, atIndex);
|
|
@@ -362,7 +359,6 @@ class ChangeTree {
|
|
|
362
359
|
}
|
|
363
360
|
_shiftAllChangeIndexes(shiftIndex, startIndex = 0, allChangeSet) {
|
|
364
361
|
Array.from(allChangeSet.entries()).forEach(([index, op]) => {
|
|
365
|
-
// console.log('shiftAllChangeIndexes', index >= startIndex, { index, op, shiftIndex, startIndex })
|
|
366
362
|
if (index >= startIndex) {
|
|
367
363
|
allChangeSet.delete(index);
|
|
368
364
|
allChangeSet.set(index + shiftIndex, op);
|
|
@@ -503,7 +499,7 @@ class ChangeTree {
|
|
|
503
499
|
}
|
|
504
500
|
checkIsFiltered(parent, parentIndex) {
|
|
505
501
|
// Detect if current structure has "filters" declared
|
|
506
|
-
this.isPartiallyFiltered = this.ref['constructor']?.[Symbol.metadata]?.[-2];
|
|
502
|
+
this.isPartiallyFiltered = (this.ref['constructor']?.[Symbol.metadata]?.[-2] !== undefined);
|
|
507
503
|
// TODO: support "partially filtered", where the instance is visible, but only a field is not.
|
|
508
504
|
// Detect if parent has "filters" declared
|
|
509
505
|
while (parent && !this.isFiltered) {
|
|
@@ -564,6 +560,29 @@ try {
|
|
|
564
560
|
textEncoder = new TextEncoder();
|
|
565
561
|
}
|
|
566
562
|
catch (e) { }
|
|
563
|
+
const hasBufferByteLength = (typeof Buffer !== 'undefined' && Buffer.byteLength);
|
|
564
|
+
const utf8Length = (hasBufferByteLength)
|
|
565
|
+
? Buffer.byteLength // node
|
|
566
|
+
: function (str, _) {
|
|
567
|
+
var c = 0, length = 0;
|
|
568
|
+
for (var i = 0, l = str.length; i < l; i++) {
|
|
569
|
+
c = str.charCodeAt(i);
|
|
570
|
+
if (c < 0x80) {
|
|
571
|
+
length += 1;
|
|
572
|
+
}
|
|
573
|
+
else if (c < 0x800) {
|
|
574
|
+
length += 2;
|
|
575
|
+
}
|
|
576
|
+
else if (c < 0xd800 || c >= 0xe000) {
|
|
577
|
+
length += 3;
|
|
578
|
+
}
|
|
579
|
+
else {
|
|
580
|
+
i++;
|
|
581
|
+
length += 4;
|
|
582
|
+
}
|
|
583
|
+
}
|
|
584
|
+
return length;
|
|
585
|
+
};
|
|
567
586
|
function utf8Write(view, str, it) {
|
|
568
587
|
var c = 0;
|
|
569
588
|
for (var i = 0, l = str.length; i < l; i++) {
|
|
@@ -658,8 +677,7 @@ function string$1(bytes, value, it) {
|
|
|
658
677
|
if (!value) {
|
|
659
678
|
value = "";
|
|
660
679
|
}
|
|
661
|
-
|
|
662
|
-
let length = Buffer.byteLength(value, "utf8");
|
|
680
|
+
let length = utf8Length(value, "utf8");
|
|
663
681
|
let size = 0;
|
|
664
682
|
// fixstr
|
|
665
683
|
if (length < 0x20) {
|
|
@@ -770,6 +788,7 @@ function number$1(bytes, value, it) {
|
|
|
770
788
|
|
|
771
789
|
var encode = /*#__PURE__*/Object.freeze({
|
|
772
790
|
__proto__: null,
|
|
791
|
+
utf8Length: utf8Length,
|
|
773
792
|
utf8Write: utf8Write,
|
|
774
793
|
int8: int8$1,
|
|
775
794
|
uint8: uint8$1,
|
|
@@ -993,9 +1012,9 @@ const encodeArray = function (encoder, bytes, changeTree, field, operation, it,
|
|
|
993
1012
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
994
1013
|
* SOFTWARE
|
|
995
1014
|
*/
|
|
996
|
-
function utf8Read(bytes,
|
|
1015
|
+
function utf8Read(bytes, it, length) {
|
|
997
1016
|
var string = '', chr = 0;
|
|
998
|
-
for (var i = offset, end = offset + length; i < end; i++) {
|
|
1017
|
+
for (var i = it.offset, end = it.offset + length; i < end; i++) {
|
|
999
1018
|
var byte = bytes[i];
|
|
1000
1019
|
if ((byte & 0x80) === 0x00) {
|
|
1001
1020
|
string += String.fromCharCode(byte);
|
|
@@ -1030,6 +1049,7 @@ function utf8Read(bytes, offset, length) {
|
|
|
1030
1049
|
// (do not throw error to avoid server/client from crashing due to hack attemps)
|
|
1031
1050
|
// throw new Error('Invalid byte ' + byte.toString(16));
|
|
1032
1051
|
}
|
|
1052
|
+
it.offset += length;
|
|
1033
1053
|
return string;
|
|
1034
1054
|
}
|
|
1035
1055
|
function int8(bytes, it) {
|
|
@@ -1097,9 +1117,7 @@ function string(bytes, it) {
|
|
|
1097
1117
|
else if (prefix === 0xdb) {
|
|
1098
1118
|
length = uint32(bytes, it);
|
|
1099
1119
|
}
|
|
1100
|
-
|
|
1101
|
-
it.offset += length;
|
|
1102
|
-
return value;
|
|
1120
|
+
return utf8Read(bytes, it, length);
|
|
1103
1121
|
}
|
|
1104
1122
|
function stringCheck(bytes, it) {
|
|
1105
1123
|
const prefix = bytes[it.offset];
|
|
@@ -1203,6 +1221,7 @@ function switchStructureCheck(bytes, it) {
|
|
|
1203
1221
|
|
|
1204
1222
|
var decode = /*#__PURE__*/Object.freeze({
|
|
1205
1223
|
__proto__: null,
|
|
1224
|
+
utf8Read: utf8Read,
|
|
1206
1225
|
int8: int8,
|
|
1207
1226
|
uint8: uint8,
|
|
1208
1227
|
int16: int16,
|
|
@@ -1226,7 +1245,7 @@ var decode = /*#__PURE__*/Object.freeze({
|
|
|
1226
1245
|
|
|
1227
1246
|
const DEFINITION_MISMATCH = -1;
|
|
1228
1247
|
function decodeValue(decoder, operation, ref, index, type, bytes, it, allChanges) {
|
|
1229
|
-
const $root = decoder
|
|
1248
|
+
const $root = decoder.root;
|
|
1230
1249
|
const previousValue = ref[$getByIndex](index);
|
|
1231
1250
|
let value;
|
|
1232
1251
|
if ((operation & exports.OPERATION.DELETE) === exports.OPERATION.DELETE) {
|
|
@@ -1426,7 +1445,7 @@ const decodeArray = function (decoder, bytes, it, ref, allChanges) {
|
|
|
1426
1445
|
else if (operation === exports.OPERATION.DELETE_BY_REFID) {
|
|
1427
1446
|
// TODO: refactor here, try to follow same flow as below
|
|
1428
1447
|
const refId = number(bytes, it);
|
|
1429
|
-
const previousValue = decoder
|
|
1448
|
+
const previousValue = decoder.root.refs.get(refId);
|
|
1430
1449
|
const index = ref.findIndex((value) => value === previousValue);
|
|
1431
1450
|
ref[$deleteByIndex](index);
|
|
1432
1451
|
allChanges.push({
|
|
@@ -3362,13 +3381,13 @@ class Encoder {
|
|
|
3362
3381
|
// });
|
|
3363
3382
|
}
|
|
3364
3383
|
setRoot(state) {
|
|
3365
|
-
this
|
|
3384
|
+
this.root = new Root();
|
|
3366
3385
|
this.state = state;
|
|
3367
|
-
state[$changes].setRoot(this
|
|
3386
|
+
state[$changes].setRoot(this.root);
|
|
3368
3387
|
}
|
|
3369
|
-
encode(it = { offset: 0 }, view,
|
|
3388
|
+
encode(it = { offset: 0 }, view, buffer = this.sharedBuffer, changeTrees = this.root.changes) {
|
|
3370
3389
|
const initialOffset = it.offset; // cache current offset in case we need to resize the buffer
|
|
3371
|
-
const isEncodeAll = this
|
|
3390
|
+
const isEncodeAll = this.root.allChanges === changeTrees;
|
|
3372
3391
|
const hasView = (view !== undefined);
|
|
3373
3392
|
const rootChangeTree = this.state[$changes];
|
|
3374
3393
|
const changeTreesIterator = changeTrees.entries();
|
|
@@ -3388,8 +3407,8 @@ class Encoder {
|
|
|
3388
3407
|
}
|
|
3389
3408
|
// skip root `refId` if it's the first change tree
|
|
3390
3409
|
if (it.offset !== initialOffset || changeTree !== rootChangeTree) {
|
|
3391
|
-
|
|
3392
|
-
number$1(
|
|
3410
|
+
buffer[it.offset++] = SWITCH_TO_STRUCTURE & 255;
|
|
3411
|
+
number$1(buffer, changeTree.refId, it);
|
|
3393
3412
|
}
|
|
3394
3413
|
const changesIterator = changes.entries();
|
|
3395
3414
|
for (const [fieldIndex, operation] of changesIterator) {
|
|
@@ -3411,17 +3430,21 @@ class Encoder {
|
|
|
3411
3430
|
// fieldIndex,
|
|
3412
3431
|
// operation: OPERATION[operation],
|
|
3413
3432
|
// });
|
|
3414
|
-
encoder(this,
|
|
3433
|
+
encoder(this, buffer, changeTree, fieldIndex, operation, it, isEncodeAll, hasView);
|
|
3415
3434
|
}
|
|
3416
3435
|
}
|
|
3417
|
-
if (it.offset >
|
|
3418
|
-
const newSize = getNextPowerOf2(
|
|
3419
|
-
console.warn("@colyseus/schema encode buffer overflow. Current buffer size: " +
|
|
3436
|
+
if (it.offset > buffer.byteLength) {
|
|
3437
|
+
const newSize = getNextPowerOf2(buffer.byteLength * 2);
|
|
3438
|
+
console.warn("@colyseus/schema encode buffer overflow. Current buffer size: " + buffer.byteLength + ", encoding offset: " + it.offset + ", new size: " + newSize);
|
|
3420
3439
|
//
|
|
3421
3440
|
// resize buffer and re-encode (TODO: can we avoid re-encoding here?)
|
|
3422
3441
|
//
|
|
3423
|
-
|
|
3424
|
-
|
|
3442
|
+
buffer = Buffer.allocUnsafeSlow(newSize);
|
|
3443
|
+
// assign resized buffer to local sharedBuffer
|
|
3444
|
+
if (buffer === this.sharedBuffer) {
|
|
3445
|
+
this.sharedBuffer = buffer;
|
|
3446
|
+
}
|
|
3447
|
+
return this.encode({ offset: initialOffset }, view, buffer);
|
|
3425
3448
|
}
|
|
3426
3449
|
else {
|
|
3427
3450
|
//
|
|
@@ -3433,42 +3456,41 @@ class Encoder {
|
|
|
3433
3456
|
//
|
|
3434
3457
|
this.onEndEncode(changeTrees);
|
|
3435
3458
|
}
|
|
3436
|
-
|
|
3437
|
-
return bytes.slice(0, it.offset);
|
|
3459
|
+
return buffer.subarray(0, it.offset);
|
|
3438
3460
|
}
|
|
3439
3461
|
}
|
|
3440
|
-
encodeAll(it = { offset: 0 }) {
|
|
3441
|
-
// console.log(`encodeAll(), this
|
|
3442
|
-
// Array.from(this
|
|
3443
|
-
// console.log("->", item[0].
|
|
3462
|
+
encodeAll(it = { offset: 0 }, buffer = this.sharedBuffer) {
|
|
3463
|
+
// console.log(`encodeAll(), this.root.allChanges (${this.root.allChanges.size})`);
|
|
3464
|
+
// Array.from(this.root.allChanges.entries()).map((item) => {
|
|
3465
|
+
// console.log("->", { ref: item[0].ref.constructor.name, refId: item[0].refId, changes: item[1].size });
|
|
3444
3466
|
// });
|
|
3445
|
-
return this.encode(it, undefined,
|
|
3467
|
+
return this.encode(it, undefined, buffer, this.root.allChanges);
|
|
3446
3468
|
}
|
|
3447
3469
|
encodeAllView(view, sharedOffset, it, bytes = this.sharedBuffer) {
|
|
3448
3470
|
const viewOffset = it.offset;
|
|
3449
|
-
// console.log(`encodeAllView(), this
|
|
3471
|
+
// console.log(`encodeAllView(), this.root.allFilteredChanges (${this.root.allFilteredChanges.size})`);
|
|
3450
3472
|
// this.debugAllFilteredChanges();
|
|
3451
3473
|
// try to encode "filtered" changes
|
|
3452
|
-
this.encode(it, view, bytes, this
|
|
3474
|
+
this.encode(it, view, bytes, this.root.allFilteredChanges);
|
|
3453
3475
|
return Buffer.concat([
|
|
3454
|
-
bytes.
|
|
3455
|
-
bytes.
|
|
3476
|
+
bytes.subarray(0, sharedOffset),
|
|
3477
|
+
bytes.subarray(viewOffset, it.offset)
|
|
3456
3478
|
]);
|
|
3457
3479
|
}
|
|
3458
|
-
|
|
3459
|
-
|
|
3460
|
-
|
|
3461
|
-
|
|
3462
|
-
|
|
3463
|
-
|
|
3464
|
-
|
|
3465
|
-
|
|
3466
|
-
|
|
3467
|
-
|
|
3480
|
+
debugAllFilteredChanges() {
|
|
3481
|
+
Array.from(this.root.allFilteredChanges.entries()).map((item) => {
|
|
3482
|
+
console.log("->", { refId: item[0].refId, changes: item[1].size }, item[0].ref.toJSON());
|
|
3483
|
+
if (Array.isArray(item[0].ref.toJSON())) {
|
|
3484
|
+
item[1].forEach((op, key) => {
|
|
3485
|
+
console.log(" ->", { key, op: exports.OPERATION[op] });
|
|
3486
|
+
});
|
|
3487
|
+
}
|
|
3488
|
+
});
|
|
3489
|
+
}
|
|
3468
3490
|
encodeView(view, sharedOffset, it, bytes = this.sharedBuffer) {
|
|
3469
3491
|
const viewOffset = it.offset;
|
|
3470
3492
|
// try to encode "filtered" changes
|
|
3471
|
-
this.encode(it, view, bytes, this
|
|
3493
|
+
this.encode(it, view, bytes, this.root.filteredChanges);
|
|
3472
3494
|
// encode visibility changes (add/remove for this view)
|
|
3473
3495
|
const viewChangesIterator = view.changes.entries();
|
|
3474
3496
|
for (const [changeTree, changes] of viewChangesIterator) {
|
|
@@ -3496,11 +3518,11 @@ class Encoder {
|
|
|
3496
3518
|
// clear "view" changes after encoding
|
|
3497
3519
|
view.changes.clear();
|
|
3498
3520
|
return Buffer.concat([
|
|
3499
|
-
bytes.
|
|
3500
|
-
bytes.
|
|
3521
|
+
bytes.subarray(0, sharedOffset),
|
|
3522
|
+
bytes.subarray(viewOffset, it.offset)
|
|
3501
3523
|
]);
|
|
3502
3524
|
}
|
|
3503
|
-
onEndEncode(changeTrees = this
|
|
3525
|
+
onEndEncode(changeTrees = this.root.changes) {
|
|
3504
3526
|
const changeTreesIterator = changeTrees.entries();
|
|
3505
3527
|
for (const [changeTree, _] of changeTreesIterator) {
|
|
3506
3528
|
changeTree.endEncode();
|
|
@@ -3508,14 +3530,14 @@ class Encoder {
|
|
|
3508
3530
|
}
|
|
3509
3531
|
discardChanges() {
|
|
3510
3532
|
// discard shared changes
|
|
3511
|
-
if (this
|
|
3512
|
-
this.onEndEncode(this
|
|
3513
|
-
this
|
|
3533
|
+
if (this.root.changes.size > 0) {
|
|
3534
|
+
this.onEndEncode(this.root.changes);
|
|
3535
|
+
this.root.changes.clear();
|
|
3514
3536
|
}
|
|
3515
3537
|
// discard filtered changes
|
|
3516
|
-
if (this
|
|
3517
|
-
this.onEndEncode(this
|
|
3518
|
-
this
|
|
3538
|
+
if (this.root.filteredChanges.size > 0) {
|
|
3539
|
+
this.onEndEncode(this.root.filteredChanges);
|
|
3540
|
+
this.root.filteredChanges.clear();
|
|
3519
3541
|
}
|
|
3520
3542
|
}
|
|
3521
3543
|
tryEncodeTypeId(bytes, baseType, targetType, it) {
|
|
@@ -3676,12 +3698,12 @@ class Decoder {
|
|
|
3676
3698
|
}
|
|
3677
3699
|
setRoot(root) {
|
|
3678
3700
|
this.state = root;
|
|
3679
|
-
this
|
|
3680
|
-
this
|
|
3701
|
+
this.root = new ReferenceTracker();
|
|
3702
|
+
this.root.addRef(0, root);
|
|
3681
3703
|
}
|
|
3682
3704
|
decode(bytes, it = { offset: 0 }, ref = this.state) {
|
|
3683
3705
|
const allChanges = [];
|
|
3684
|
-
const $root = this
|
|
3706
|
+
const $root = this.root;
|
|
3685
3707
|
const totalBytes = bytes.byteLength;
|
|
3686
3708
|
let decoder = ref['constructor'][$decoder];
|
|
3687
3709
|
this.currentRefId = 0;
|
|
@@ -3762,7 +3784,7 @@ class Decoder {
|
|
|
3762
3784
|
previousValue: value
|
|
3763
3785
|
});
|
|
3764
3786
|
if (needRemoveRef) {
|
|
3765
|
-
this
|
|
3787
|
+
this.root.removeRef(this.root.refIds.get(value));
|
|
3766
3788
|
}
|
|
3767
3789
|
});
|
|
3768
3790
|
}
|
|
@@ -3802,7 +3824,7 @@ class Reflection extends Schema {
|
|
|
3802
3824
|
super(...arguments);
|
|
3803
3825
|
this.types = new ArraySchema();
|
|
3804
3826
|
}
|
|
3805
|
-
static encode(instance, context) {
|
|
3827
|
+
static encode(instance, context, it = { offset: 0 }) {
|
|
3806
3828
|
if (!context) {
|
|
3807
3829
|
context = new TypeContext(instance.constructor);
|
|
3808
3830
|
}
|
|
@@ -3859,7 +3881,6 @@ class Reflection extends Schema {
|
|
|
3859
3881
|
}
|
|
3860
3882
|
buildType(type, klass[Symbol.metadata]);
|
|
3861
3883
|
}
|
|
3862
|
-
const it = { offset: 0 };
|
|
3863
3884
|
const buf = encoder.encodeAll(it);
|
|
3864
3885
|
return Buffer.from(buf, 0, it.offset);
|
|
3865
3886
|
}
|