@colyseus/schema 3.0.0-alpha.2 → 3.0.0-alpha.22

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (99) hide show
  1. package/README.md +131 -61
  2. package/build/cjs/index.js +472 -150
  3. package/build/cjs/index.js.map +1 -1
  4. package/build/esm/index.mjs +471 -149
  5. package/build/esm/index.mjs.map +1 -1
  6. package/build/umd/index.js +472 -150
  7. package/lib/Metadata.d.ts +2 -0
  8. package/lib/Metadata.js +39 -0
  9. package/lib/Metadata.js.map +1 -1
  10. package/lib/Reflection.d.ts +1 -2
  11. package/lib/Reflection.js +28 -22
  12. package/lib/Reflection.js.map +1 -1
  13. package/lib/Schema.d.ts +1 -1
  14. package/lib/annotations.js +12 -10
  15. package/lib/annotations.js.map +1 -1
  16. package/lib/bench_encode.d.ts +1 -0
  17. package/lib/bench_encode.js +93 -0
  18. package/lib/bench_encode.js.map +1 -0
  19. package/lib/codegen/api.js +1 -2
  20. package/lib/codegen/api.js.map +1 -1
  21. package/lib/codegen/languages/cpp.js +1 -2
  22. package/lib/codegen/languages/cpp.js.map +1 -1
  23. package/lib/codegen/languages/csharp.js +1 -2
  24. package/lib/codegen/languages/csharp.js.map +1 -1
  25. package/lib/codegen/languages/haxe.js +1 -2
  26. package/lib/codegen/languages/haxe.js.map +1 -1
  27. package/lib/codegen/languages/java.js +1 -2
  28. package/lib/codegen/languages/java.js.map +1 -1
  29. package/lib/codegen/languages/js.js +1 -2
  30. package/lib/codegen/languages/js.js.map +1 -1
  31. package/lib/codegen/languages/lua.js +1 -2
  32. package/lib/codegen/languages/lua.js.map +1 -1
  33. package/lib/codegen/languages/ts.js +1 -2
  34. package/lib/codegen/languages/ts.js.map +1 -1
  35. package/lib/codegen/parser.js +2 -3
  36. package/lib/codegen/parser.js.map +1 -1
  37. package/lib/codegen/types.js +3 -3
  38. package/lib/codegen/types.js.map +1 -1
  39. package/lib/decoder/DecodeOperation.d.ts +0 -1
  40. package/lib/decoder/DecodeOperation.js +22 -7
  41. package/lib/decoder/DecodeOperation.js.map +1 -1
  42. package/lib/decoder/Decoder.d.ts +1 -2
  43. package/lib/decoder/Decoder.js +4 -4
  44. package/lib/decoder/Decoder.js.map +1 -1
  45. package/lib/decoder/strategy/RawChanges.js +1 -2
  46. package/lib/decoder/strategy/RawChanges.js.map +1 -1
  47. package/lib/decoder/strategy/StateCallbacks.d.ts +36 -7
  48. package/lib/decoder/strategy/StateCallbacks.js +39 -46
  49. package/lib/decoder/strategy/StateCallbacks.js.map +1 -1
  50. package/lib/encoder/ChangeTree.js +2 -5
  51. package/lib/encoder/ChangeTree.js.map +1 -1
  52. package/lib/encoder/EncodeOperation.d.ts +0 -1
  53. package/lib/encoder/EncodeOperation.js +29 -13
  54. package/lib/encoder/EncodeOperation.js.map +1 -1
  55. package/lib/encoder/Encoder.d.ts +5 -4
  56. package/lib/encoder/Encoder.js +56 -38
  57. package/lib/encoder/Encoder.js.map +1 -1
  58. package/lib/encoder/StateView.js +11 -6
  59. package/lib/encoder/StateView.js.map +1 -1
  60. package/lib/encoding/assert.js +3 -3
  61. package/lib/encoding/assert.js.map +1 -1
  62. package/lib/encoding/decode.d.ts +21 -19
  63. package/lib/encoding/decode.js +24 -25
  64. package/lib/encoding/decode.js.map +1 -1
  65. package/lib/encoding/encode.d.ts +2 -2
  66. package/lib/encoding/encode.js +40 -39
  67. package/lib/encoding/encode.js.map +1 -1
  68. package/lib/encoding/spec.d.ts +2 -1
  69. package/lib/encoding/spec.js +1 -0
  70. package/lib/encoding/spec.js.map +1 -1
  71. package/lib/index.d.ts +3 -0
  72. package/lib/index.js +5 -1
  73. package/lib/index.js.map +1 -1
  74. package/lib/types/custom/ArraySchema.d.ts +2 -2
  75. package/lib/types/custom/ArraySchema.js +0 -8
  76. package/lib/types/custom/ArraySchema.js.map +1 -1
  77. package/lib/types/registry.js +3 -4
  78. package/lib/types/registry.js.map +1 -1
  79. package/lib/types/utils.js +1 -2
  80. package/lib/types/utils.js.map +1 -1
  81. package/lib/utils.js +3 -4
  82. package/lib/utils.js.map +1 -1
  83. package/package.json +5 -5
  84. package/src/Metadata.ts +47 -0
  85. package/src/Reflection.ts +31 -22
  86. package/src/annotations.ts +6 -2
  87. package/src/bench_encode.ts +66 -0
  88. package/src/decoder/DecodeOperation.ts +26 -6
  89. package/src/decoder/Decoder.ts +5 -5
  90. package/src/decoder/strategy/StateCallbacks.ts +93 -53
  91. package/src/encoder/ChangeTree.ts +2 -4
  92. package/src/encoder/EncodeOperation.ts +29 -12
  93. package/src/encoder/Encoder.ts +65 -41
  94. package/src/encoder/StateView.ts +10 -7
  95. package/src/encoding/decode.ts +24 -25
  96. package/src/encoding/encode.ts +25 -22
  97. package/src/encoding/spec.ts +1 -0
  98. package/src/index.ts +5 -0
  99. package/src/types/custom/ArraySchema.ts +2 -1
@@ -29,6 +29,7 @@
29
29
  OPERATION[OPERATION["REVERSE"] = 15] = "REVERSE";
30
30
  OPERATION[OPERATION["MOVE"] = 32] = "MOVE";
31
31
  OPERATION[OPERATION["DELETE_BY_REFID"] = 33] = "DELETE_BY_REFID";
32
+ OPERATION[OPERATION["ADD_BY_REFID"] = 129] = "ADD_BY_REFID";
32
33
  })(exports.OPERATION || (exports.OPERATION = {}));
33
34
 
34
35
  Symbol.metadata ??= Symbol.for("Symbol.metadata");
@@ -145,6 +146,45 @@
145
146
  isDeprecated(metadata, field) {
146
147
  return metadata[field].deprecated === true;
147
148
  },
149
+ init(klass) {
150
+ //
151
+ // Used only to initialize an empty Schema (Encoder#constructor)
152
+ // TODO: remove/refactor this...
153
+ //
154
+ const metadata = {};
155
+ klass.constructor[Symbol.metadata] = metadata;
156
+ Object.defineProperty(metadata, -1, {
157
+ value: 0,
158
+ enumerable: false,
159
+ configurable: true,
160
+ });
161
+ },
162
+ initialize(constructor, parentMetadata) {
163
+ let metadata = constructor[Symbol.metadata] ?? Object.create(null);
164
+ // make sure inherited classes have their own metadata object.
165
+ if (constructor[Symbol.metadata] === parentMetadata) {
166
+ metadata = Object.create(null);
167
+ if (parentMetadata) {
168
+ // assign parent metadata to current
169
+ Object.assign(metadata, parentMetadata);
170
+ for (let i = 0; i <= parentMetadata[-1]; i++) {
171
+ Object.defineProperty(metadata, i, {
172
+ value: parentMetadata[i],
173
+ enumerable: false,
174
+ configurable: true,
175
+ });
176
+ }
177
+ Object.defineProperty(metadata, -1, {
178
+ value: parentMetadata[-1],
179
+ enumerable: false,
180
+ configurable: true,
181
+ writable: true,
182
+ });
183
+ }
184
+ }
185
+ constructor[Symbol.metadata] = metadata;
186
+ return metadata;
187
+ },
148
188
  isValidInstance(klass) {
149
189
  return (klass.constructor[Symbol.metadata] &&
150
190
  Object.prototype.hasOwnProperty.call(klass.constructor[Symbol.metadata], -1));
@@ -264,14 +304,12 @@
264
304
  this.checkIsFiltered(parent, parentIndex);
265
305
  if (!this.isFiltered) {
266
306
  this.root.changes.set(this, this.changes);
307
+ this.root.allChanges.set(this, this.allChanges);
267
308
  }
268
309
  if (this.isFiltered || this.isPartiallyFiltered) {
269
310
  this.root.filteredChanges.set(this, this.filteredChanges);
270
311
  this.root.allFilteredChanges.set(this, this.filteredChanges);
271
312
  }
272
- else {
273
- this.root.allChanges.set(this, this.allChanges);
274
- }
275
313
  this.ensureRefId();
276
314
  this.forEachChild((changeTree, atIndex) => {
277
315
  changeTree.setParent(this.ref, root, atIndex);
@@ -363,7 +401,6 @@
363
401
  }
364
402
  _shiftAllChangeIndexes(shiftIndex, startIndex = 0, allChangeSet) {
365
403
  Array.from(allChangeSet.entries()).forEach(([index, op]) => {
366
- // console.log('shiftAllChangeIndexes', index >= startIndex, { index, op, shiftIndex, startIndex })
367
404
  if (index >= startIndex) {
368
405
  allChangeSet.delete(index);
369
406
  allChangeSet.set(index + shiftIndex, op);
@@ -504,7 +541,7 @@
504
541
  }
505
542
  checkIsFiltered(parent, parentIndex) {
506
543
  // Detect if current structure has "filters" declared
507
- this.isPartiallyFiltered = this.ref['constructor']?.[Symbol.metadata]?.[-2];
544
+ this.isPartiallyFiltered = (this.ref['constructor']?.[Symbol.metadata]?.[-2] !== undefined);
508
545
  // TODO: support "partially filtered", where the instance is visible, but only a field is not.
509
546
  // Detect if parent has "filters" declared
510
547
  while (parent && !this.isFiltered) {
@@ -565,26 +602,29 @@
565
602
  textEncoder = new TextEncoder();
566
603
  }
567
604
  catch (e) { }
568
- function utf8Length(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;
605
+ const hasBufferByteLength = (typeof Buffer !== 'undefined' && Buffer.byteLength);
606
+ const utf8Length = (hasBufferByteLength)
607
+ ? Buffer.byteLength // node
608
+ : function (str, _) {
609
+ var c = 0, length = 0;
610
+ for (var i = 0, l = str.length; i < l; i++) {
611
+ c = str.charCodeAt(i);
612
+ if (c < 0x80) {
613
+ length += 1;
614
+ }
615
+ else if (c < 0x800) {
616
+ length += 2;
617
+ }
618
+ else if (c < 0xd800 || c >= 0xe000) {
619
+ length += 3;
620
+ }
621
+ else {
622
+ i++;
623
+ length += 4;
624
+ }
584
625
  }
585
- }
586
- return length;
587
- }
626
+ return length;
627
+ };
588
628
  function utf8Write(view, str, it) {
589
629
  var c = 0;
590
630
  for (var i = 0, l = str.length; i < l; i++) {
@@ -679,8 +719,7 @@
679
719
  if (!value) {
680
720
  value = "";
681
721
  }
682
- // let length = utf8Length(value);
683
- let length = Buffer.byteLength(value, "utf8");
722
+ let length = utf8Length(value, "utf8");
684
723
  let size = 0;
685
724
  // fixstr
686
725
  if (length < 0x20) {
@@ -791,23 +830,23 @@
791
830
 
792
831
  var encode = /*#__PURE__*/Object.freeze({
793
832
  __proto__: null,
794
- utf8Length: utf8Length,
795
- utf8Write: utf8Write,
796
- int8: int8$1,
797
- uint8: uint8$1,
833
+ boolean: boolean$1,
834
+ float32: float32$1,
835
+ float64: float64$1,
798
836
  int16: int16$1,
799
- uint16: uint16$1,
800
837
  int32: int32$1,
801
- uint32: uint32$1,
802
838
  int64: int64$1,
839
+ int8: int8$1,
840
+ number: number$1,
841
+ string: string$1,
842
+ uint16: uint16$1,
843
+ uint32: uint32$1,
803
844
  uint64: uint64$1,
804
- float32: float32$1,
805
- float64: float64$1,
845
+ uint8: uint8$1,
846
+ utf8Length: utf8Length,
847
+ utf8Write: utf8Write,
806
848
  writeFloat32: writeFloat32,
807
- writeFloat64: writeFloat64,
808
- boolean: boolean$1,
809
- string: string$1,
810
- number: number$1
849
+ writeFloat64: writeFloat64
811
850
  });
812
851
 
813
852
  class EncodeSchemaError extends Error {
@@ -949,6 +988,18 @@
949
988
  }
950
989
  const type = changeTree.getType(field);
951
990
  const value = changeTree.getValue(field);
991
+ // try { throw new Error(); } catch (e) {
992
+ // // only print if not coming from Reflection.ts
993
+ // if (!e.stack.includes("src/Reflection.ts")) {
994
+ // console.log("encodeKeyValueOperation -> ", {
995
+ // ref: changeTree.ref.constructor.name,
996
+ // field,
997
+ // operation: OPERATION[operation],
998
+ // value: value?.toJSON(),
999
+ // items: ref.toJSON(),
1000
+ // });
1001
+ // }
1002
+ // }
952
1003
  // TODO: inline this function call small performance gain
953
1004
  encodeValue(encoder, bytes, ref, type, value, field, operation, it);
954
1005
  };
@@ -958,15 +1009,19 @@
958
1009
  */
959
1010
  const encodeArray = function (encoder, bytes, changeTree, field, operation, it, isEncodeAll, hasView) {
960
1011
  const ref = changeTree.ref;
961
- if (hasView &&
962
- operation === exports.OPERATION.DELETE &&
963
- typeof (changeTree.getType(field)) !== "string") {
964
- // encode delete by refId (array of schemas)
965
- bytes[it.offset++] = exports.OPERATION.DELETE_BY_REFID;
966
- const value = ref['tmpItems'][field];
967
- const refId = value[$changes].refId;
968
- number$1(bytes, refId, it);
969
- return;
1012
+ const useOperationByRefId = hasView && changeTree.isFiltered && (typeof (changeTree.getType(field)) !== "string");
1013
+ let refOrIndex;
1014
+ if (useOperationByRefId) {
1015
+ refOrIndex = ref['tmpItems'][field][$changes].refId;
1016
+ if (operation === exports.OPERATION.DELETE) {
1017
+ operation = exports.OPERATION.DELETE_BY_REFID;
1018
+ }
1019
+ else if (operation === exports.OPERATION.ADD) {
1020
+ operation = exports.OPERATION.ADD_BY_REFID;
1021
+ }
1022
+ }
1023
+ else {
1024
+ refOrIndex = field;
970
1025
  }
971
1026
  // encode operation
972
1027
  bytes[it.offset++] = operation & 255;
@@ -975,7 +1030,7 @@
975
1030
  return;
976
1031
  }
977
1032
  // encode index
978
- number$1(bytes, field, it);
1033
+ number$1(bytes, refOrIndex, it);
979
1034
  // Do not encode value for DELETE operations
980
1035
  if (operation === exports.OPERATION.DELETE) {
981
1036
  return;
@@ -1015,9 +1070,9 @@
1015
1070
  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
1016
1071
  * SOFTWARE
1017
1072
  */
1018
- function utf8Read(bytes, offset, length) {
1073
+ function utf8Read(bytes, it, length) {
1019
1074
  var string = '', chr = 0;
1020
- for (var i = offset, end = offset + length; i < end; i++) {
1075
+ for (var i = it.offset, end = it.offset + length; i < end; i++) {
1021
1076
  var byte = bytes[i];
1022
1077
  if ((byte & 0x80) === 0x00) {
1023
1078
  string += String.fromCharCode(byte);
@@ -1052,6 +1107,7 @@
1052
1107
  // (do not throw error to avoid server/client from crashing due to hack attemps)
1053
1108
  // throw new Error('Invalid byte ' + byte.toString(16));
1054
1109
  }
1110
+ it.offset += length;
1055
1111
  return string;
1056
1112
  }
1057
1113
  function int8(bytes, it) {
@@ -1119,9 +1175,7 @@
1119
1175
  else if (prefix === 0xdb) {
1120
1176
  length = uint32(bytes, it);
1121
1177
  }
1122
- const value = utf8Read(bytes, it.offset, length);
1123
- it.offset += length;
1124
- return value;
1178
+ return utf8Read(bytes, it, length);
1125
1179
  }
1126
1180
  function stringCheck(bytes, it) {
1127
1181
  const prefix = bytes[it.offset];
@@ -1225,30 +1279,31 @@
1225
1279
 
1226
1280
  var decode = /*#__PURE__*/Object.freeze({
1227
1281
  __proto__: null,
1228
- int8: int8,
1229
- uint8: uint8,
1230
- int16: int16,
1231
- uint16: uint16,
1232
- int32: int32,
1233
- uint32: uint32,
1282
+ arrayCheck: arrayCheck,
1283
+ boolean: boolean,
1234
1284
  float32: float32,
1235
1285
  float64: float64,
1286
+ int16: int16,
1287
+ int32: int32,
1236
1288
  int64: int64,
1237
- uint64: uint64,
1289
+ int8: int8,
1290
+ number: number,
1291
+ numberCheck: numberCheck,
1238
1292
  readFloat32: readFloat32,
1239
1293
  readFloat64: readFloat64,
1240
- boolean: boolean,
1241
1294
  string: string,
1242
1295
  stringCheck: stringCheck,
1243
- number: number,
1244
- numberCheck: numberCheck,
1245
- arrayCheck: arrayCheck,
1246
- switchStructureCheck: switchStructureCheck
1296
+ switchStructureCheck: switchStructureCheck,
1297
+ uint16: uint16,
1298
+ uint32: uint32,
1299
+ uint64: uint64,
1300
+ uint8: uint8,
1301
+ utf8Read: utf8Read
1247
1302
  });
1248
1303
 
1249
1304
  const DEFINITION_MISMATCH = -1;
1250
1305
  function decodeValue(decoder, operation, ref, index, type, bytes, it, allChanges) {
1251
- const $root = decoder.$root;
1306
+ const $root = decoder.root;
1252
1307
  const previousValue = ref[$getByIndex](index);
1253
1308
  let value;
1254
1309
  if ((operation & exports.OPERATION.DELETE) === exports.OPERATION.DELETE) {
@@ -1434,7 +1489,8 @@
1434
1489
  };
1435
1490
  const decodeArray = function (decoder, bytes, it, ref, allChanges) {
1436
1491
  // "uncompressed" index + operation (array/map items)
1437
- const operation = bytes[it.offset++];
1492
+ let operation = bytes[it.offset++];
1493
+ let index;
1438
1494
  if (operation === exports.OPERATION.CLEAR) {
1439
1495
  //
1440
1496
  // When decoding:
@@ -1448,8 +1504,8 @@
1448
1504
  else if (operation === exports.OPERATION.DELETE_BY_REFID) {
1449
1505
  // TODO: refactor here, try to follow same flow as below
1450
1506
  const refId = number(bytes, it);
1451
- const previousValue = decoder.$root.refs.get(refId);
1452
- const index = ref.findIndex((value) => value === previousValue);
1507
+ const previousValue = decoder.root.refs.get(refId);
1508
+ index = ref.findIndex((value) => value === previousValue);
1453
1509
  ref[$deleteByIndex](index);
1454
1510
  allChanges.push({
1455
1511
  ref,
@@ -1462,7 +1518,18 @@
1462
1518
  });
1463
1519
  return;
1464
1520
  }
1465
- const index = number(bytes, it);
1521
+ else if (operation === exports.OPERATION.ADD_BY_REFID) {
1522
+ // operation = OPERATION.ADD;
1523
+ const refId = number(bytes, it);
1524
+ const itemByRefId = decoder.root.refs.get(refId);
1525
+ // use existing index, or push new value
1526
+ index = (itemByRefId)
1527
+ ? ref.findIndex((value) => value === itemByRefId)
1528
+ : ref.length;
1529
+ }
1530
+ else {
1531
+ index = number(bytes, it);
1532
+ }
1466
1533
  const type = ref[$childType];
1467
1534
  let dynamicIndex = index;
1468
1535
  const { value, previousValue } = decodeValue(decoder, operation, ref, index, type, bytes, it, allChanges);
@@ -1871,14 +1938,6 @@
1871
1938
  lastIndexOf(searchElement, fromIndex = this.length - 1) {
1872
1939
  return this.items.lastIndexOf(searchElement, fromIndex);
1873
1940
  }
1874
- /**
1875
- * Determines whether all the members of an array satisfy the specified test.
1876
- * @param callbackfn A function that accepts up to three arguments. The every method calls
1877
- * the callbackfn function for each element in the array until the callbackfn returns a value
1878
- * which is coercible to the Boolean value false, or until the end of the array.
1879
- * @param thisArg An object to which the this keyword can refer in the callbackfn function.
1880
- * If thisArg is omitted, undefined is used as the this value.
1881
- */
1882
1941
  every(callbackfn, thisArg) {
1883
1942
  return this.items.every(callbackfn, thisArg);
1884
1943
  }
@@ -2557,6 +2616,7 @@
2557
2616
  const constructor = target.constructor;
2558
2617
  const parentClass = Object.getPrototypeOf(constructor);
2559
2618
  const parentMetadata = parentClass[Symbol.metadata];
2619
+ // TODO: use Metadata.initialize()
2560
2620
  const metadata = (constructor[Symbol.metadata] ??= Object.assign({}, constructor[Symbol.metadata], parentMetadata ?? Object.create(null)));
2561
2621
  if (!metadata[fieldName]) {
2562
2622
  //
@@ -2581,8 +2641,8 @@
2581
2641
  // for inheritance support
2582
2642
  TypeContext.register(constructor);
2583
2643
  const parentClass = Object.getPrototypeOf(constructor);
2584
- const parentMetadata = parentClass[Symbol.metadata];
2585
- const metadata = (constructor[Symbol.metadata] ??= Object.assign({}, constructor[Symbol.metadata], parentMetadata ?? Object.create(null)));
2644
+ const parentMetadata = parentClass && parentClass[Symbol.metadata];
2645
+ const metadata = Metadata.initialize(constructor, parentMetadata);
2586
2646
  let fieldIndex;
2587
2647
  /**
2588
2648
  * skip if descriptor already exists for this field (`@deprecated()`)
@@ -3355,6 +3415,8 @@
3355
3415
  OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
3356
3416
  PERFORMANCE OF THIS SOFTWARE.
3357
3417
  ***************************************************************************** */
3418
+ /* global Reflect, Promise, SuppressedError, Symbol */
3419
+
3358
3420
 
3359
3421
  function __decorate(decorators, target, key, desc) {
3360
3422
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
@@ -3386,11 +3448,14 @@
3386
3448
  setRoot(state) {
3387
3449
  this.root = new Root();
3388
3450
  this.state = state;
3451
+ // Workaround to allow using an empty Schema.
3452
+ if (state.constructor[Symbol.metadata] === undefined) {
3453
+ Metadata.init(state);
3454
+ }
3389
3455
  state[$changes].setRoot(this.root);
3390
3456
  }
3391
- encode(it = { offset: 0 }, view, bytes = this.sharedBuffer, changeTrees = this.root.changes) {
3457
+ encode(it = { offset: 0 }, view, buffer = this.sharedBuffer, changeTrees = this.root.changes, isEncodeAll = this.root.allChanges === changeTrees) {
3392
3458
  const initialOffset = it.offset; // cache current offset in case we need to resize the buffer
3393
- const isEncodeAll = this.root.allChanges === changeTrees;
3394
3459
  const hasView = (view !== undefined);
3395
3460
  const rootChangeTree = this.state[$changes];
3396
3461
  const changeTreesIterator = changeTrees.entries();
@@ -3399,6 +3464,12 @@
3399
3464
  const ctor = ref['constructor'];
3400
3465
  const encoder = ctor[$encoder];
3401
3466
  const filter = ctor[$filter];
3467
+ // try { throw new Error(); } catch (e) {
3468
+ // // only print if not coming from Reflection.ts
3469
+ // if (!e.stack.includes("src/Reflection.ts")) {
3470
+ // console.log("ChangeTree:", { ref: ref.constructor.name, });
3471
+ // }
3472
+ // }
3402
3473
  if (hasView) {
3403
3474
  if (!view.items.has(changeTree)) {
3404
3475
  view.invisible.add(changeTree);
@@ -3410,8 +3481,8 @@
3410
3481
  }
3411
3482
  // skip root `refId` if it's the first change tree
3412
3483
  if (it.offset !== initialOffset || changeTree !== rootChangeTree) {
3413
- bytes[it.offset++] = SWITCH_TO_STRUCTURE & 255;
3414
- number$1(bytes, changeTree.refId, it);
3484
+ buffer[it.offset++] = SWITCH_TO_STRUCTURE & 255;
3485
+ number$1(buffer, changeTree.refId, it);
3415
3486
  }
3416
3487
  const changesIterator = changes.entries();
3417
3488
  for (const [fieldIndex, operation] of changesIterator) {
@@ -3428,22 +3499,31 @@
3428
3499
  // view?.invisible.add(changeTree);
3429
3500
  continue;
3430
3501
  }
3431
- // console.log("WILL ENCODE", {
3432
- // ref: changeTree.ref.constructor.name,
3433
- // fieldIndex,
3434
- // operation: OPERATION[operation],
3435
- // });
3436
- encoder(this, bytes, changeTree, fieldIndex, operation, it, isEncodeAll, hasView);
3502
+ // try { throw new Error(); } catch (e) {
3503
+ // // only print if not coming from Reflection.ts
3504
+ // if (!e.stack.includes("src/Reflection.ts")) {
3505
+ // console.log("WILL ENCODE", {
3506
+ // ref: changeTree.ref.constructor.name,
3507
+ // fieldIndex,
3508
+ // operation: OPERATION[operation],
3509
+ // });
3510
+ // }
3511
+ // }
3512
+ encoder(this, buffer, changeTree, fieldIndex, operation, it, isEncodeAll, hasView);
3437
3513
  }
3438
3514
  }
3439
- if (it.offset > bytes.byteLength) {
3440
- const newSize = getNextPowerOf2(this.sharedBuffer.byteLength * 2);
3441
- console.warn("@colyseus/schema encode buffer overflow. Current buffer size: " + bytes.byteLength + ", encoding offset: " + it.offset + ", new size: " + newSize);
3515
+ if (it.offset > buffer.byteLength) {
3516
+ const newSize = getNextPowerOf2(buffer.byteLength * 2);
3517
+ console.warn("@colyseus/schema encode buffer overflow. Current buffer size: " + buffer.byteLength + ", encoding offset: " + it.offset + ", new size: " + newSize);
3442
3518
  //
3443
3519
  // resize buffer and re-encode (TODO: can we avoid re-encoding here?)
3444
3520
  //
3445
- this.sharedBuffer = Buffer.allocUnsafeSlow(newSize);
3446
- return this.encode({ offset: initialOffset }, view);
3521
+ buffer = Buffer.allocUnsafeSlow(newSize);
3522
+ // assign resized buffer to local sharedBuffer
3523
+ if (buffer === this.sharedBuffer) {
3524
+ this.sharedBuffer = buffer;
3525
+ }
3526
+ return this.encode({ offset: initialOffset }, view, buffer, changeTrees, isEncodeAll);
3447
3527
  }
3448
3528
  else {
3449
3529
  //
@@ -3455,38 +3535,37 @@
3455
3535
  //
3456
3536
  this.onEndEncode(changeTrees);
3457
3537
  }
3458
- // return bytes;
3459
- return bytes.slice(0, it.offset);
3538
+ return buffer.subarray(0, it.offset);
3460
3539
  }
3461
3540
  }
3462
- encodeAll(it = { offset: 0 }) {
3463
- // console.log(`encodeAll(), this.$root.allChanges (${this.$root.allChanges.size})`);
3464
- // Array.from(this.$root.allChanges.entries()).map((item) => {
3465
- // console.log("->", item[0].refId, item[0].ref.toJSON());
3541
+ encodeAll(it = { offset: 0 }, buffer = this.sharedBuffer) {
3542
+ // console.log(`encodeAll(), this.root.allChanges (${this.root.allChanges.size})`);
3543
+ // Array.from(this.root.allChanges.entries()).map((item) => {
3544
+ // console.log("->", { ref: item[0].ref.constructor.name, refId: item[0].refId, changes: item[1].size });
3466
3545
  // });
3467
- return this.encode(it, undefined, this.sharedBuffer, this.root.allChanges);
3546
+ return this.encode(it, undefined, buffer, this.root.allChanges, true);
3468
3547
  }
3469
3548
  encodeAllView(view, sharedOffset, it, bytes = this.sharedBuffer) {
3470
3549
  const viewOffset = it.offset;
3471
- // console.log(`encodeAllView(), this.$root.allFilteredChanges (${this.$root.allFilteredChanges.size})`);
3550
+ // console.log(`encodeAllView(), this.root.allFilteredChanges (${this.root.allFilteredChanges.size})`);
3472
3551
  // this.debugAllFilteredChanges();
3473
3552
  // try to encode "filtered" changes
3474
- this.encode(it, view, bytes, this.root.allFilteredChanges);
3553
+ this.encode(it, view, bytes, this.root.allFilteredChanges, true);
3475
3554
  return Buffer.concat([
3476
- bytes.slice(0, sharedOffset),
3477
- bytes.slice(viewOffset, it.offset)
3555
+ bytes.subarray(0, sharedOffset),
3556
+ bytes.subarray(viewOffset, it.offset)
3478
3557
  ]);
3479
3558
  }
3480
- // debugAllFilteredChanges() {
3481
- // Array.from(this.$root.allFilteredChanges.entries()).map((item) => {
3482
- // console.log("->", { refId: item[0].refId }, item[0].ref.toJSON());
3483
- // if (Array.isArray(item[0].ref.toJSON())) {
3484
- // item[1].forEach((op, key) => {
3485
- // console.log(" ->", { key, op: OPERATION[op] });
3486
- // })
3487
- // }
3488
- // });
3489
- // }
3559
+ debugAllFilteredChanges() {
3560
+ Array.from(this.root.allFilteredChanges.entries()).map((item) => {
3561
+ console.log("->", { refId: item[0].refId, changes: item[1].size }, item[0].ref.toJSON());
3562
+ if (Array.isArray(item[0].ref.toJSON())) {
3563
+ item[1].forEach((op, key) => {
3564
+ console.log(" ->", { key, op: exports.OPERATION[op] });
3565
+ });
3566
+ }
3567
+ });
3568
+ }
3490
3569
  encodeView(view, sharedOffset, it, bytes = this.sharedBuffer) {
3491
3570
  const viewOffset = it.offset;
3492
3571
  // try to encode "filtered" changes
@@ -3518,8 +3597,8 @@
3518
3597
  // clear "view" changes after encoding
3519
3598
  view.changes.clear();
3520
3599
  return Buffer.concat([
3521
- bytes.slice(0, sharedOffset),
3522
- bytes.slice(viewOffset, it.offset)
3600
+ bytes.subarray(0, sharedOffset),
3601
+ bytes.subarray(viewOffset, it.offset)
3523
3602
  ]);
3524
3603
  }
3525
3604
  onEndEncode(changeTrees = this.root.changes) {
@@ -3698,12 +3777,12 @@
3698
3777
  }
3699
3778
  setRoot(root) {
3700
3779
  this.state = root;
3701
- this.$root = new ReferenceTracker();
3702
- this.$root.addRef(0, root);
3780
+ this.root = new ReferenceTracker();
3781
+ this.root.addRef(0, root);
3703
3782
  }
3704
3783
  decode(bytes, it = { offset: 0 }, ref = this.state) {
3705
3784
  const allChanges = [];
3706
- const $root = this.$root;
3785
+ const $root = this.root;
3707
3786
  const totalBytes = bytes.byteLength;
3708
3787
  let decoder = ref['constructor'][$decoder];
3709
3788
  this.currentRefId = 0;
@@ -3784,7 +3863,7 @@
3784
3863
  previousValue: value
3785
3864
  });
3786
3865
  if (needRemoveRef) {
3787
- this.$root.removeRef(this.$root.refIds.get(value));
3866
+ this.root.removeRef(this.root.refIds.get(value));
3788
3867
  }
3789
3868
  });
3790
3869
  }
@@ -3824,7 +3903,7 @@
3824
3903
  super(...arguments);
3825
3904
  this.types = new ArraySchema();
3826
3905
  }
3827
- static encode(instance, context) {
3906
+ static encode(instance, context, it = { offset: 0 }) {
3828
3907
  if (!context) {
3829
3908
  context = new TypeContext(instance.constructor);
3830
3909
  }
@@ -3881,7 +3960,6 @@
3881
3960
  }
3882
3961
  buildType(type, klass[Symbol.metadata]);
3883
3962
  }
3884
- const it = { offset: 0 };
3885
3963
  const buf = encoder.encodeAll(it);
3886
3964
  return Buffer.from(buf, 0, it.offset);
3887
3965
  }
@@ -3889,59 +3967,298 @@
3889
3967
  const reflection = new Reflection();
3890
3968
  const reflectionDecoder = new Decoder(reflection);
3891
3969
  reflectionDecoder.decode(bytes, it);
3892
- const context = new TypeContext();
3893
- const schemaTypes = reflection.types.reduce((types, reflectionType) => {
3894
- const parentKlass = types[reflectionType.extendsId] || Schema;
3895
- const schema = class _ extends parentKlass {
3970
+ const typeContext = new TypeContext();
3971
+ // 1st pass, initialize metadata + inheritance
3972
+ reflection.types.forEach((reflectionType) => {
3973
+ const parentClass = typeContext.get(reflectionType.extendsId) ?? Schema;
3974
+ const schema = class _ extends parentClass {
3896
3975
  };
3897
- // const _metadata = Object.create(_classSuper[Symbol.metadata] ?? null);
3898
- const _metadata = parentKlass && parentKlass[Symbol.metadata] || Object.create(null);
3899
- Object.defineProperty(schema, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
3976
+ const parentMetadata = parentClass[Symbol.metadata];
3900
3977
  // register for inheritance support
3901
3978
  TypeContext.register(schema);
3902
- const typeid = reflectionType.id;
3903
- types[typeid] = schema;
3904
- context.add(schema, typeid);
3905
- return types;
3979
+ // for inheritance support
3980
+ Metadata.initialize(schema, parentMetadata);
3981
+ typeContext.add(schema, reflectionType.id);
3906
3982
  }, {});
3983
+ // 2nd pass, set fields
3907
3984
  reflection.types.forEach((reflectionType) => {
3908
- const schemaType = schemaTypes[reflectionType.id];
3985
+ const schemaType = typeContext.get(reflectionType.id);
3909
3986
  const metadata = schemaType[Symbol.metadata];
3910
- const parentKlass = reflection.types[reflectionType.extendsId];
3911
- const parentFieldIndex = parentKlass && parentKlass.fields.length || 0;
3987
+ // FIXME: use metadata[-1] to get field count
3988
+ const parentFieldIndex = 0;
3989
+ // console.log("--------------------");
3990
+ // // console.log("reflectionType", reflectionType.toJSON());
3991
+ // console.log("reflectionType.fields", reflectionType.fields.toJSON());
3992
+ // console.log("parentFieldIndex", parentFieldIndex);
3993
+ //
3994
+ // FIXME: set fields using parentKlass as well
3995
+ // currently the fields are duplicated on inherited classes
3996
+ //
3997
+ // // const parentKlass = reflection.types[reflectionType.extendsId];
3998
+ // // parentKlass.fields
3912
3999
  reflectionType.fields.forEach((field, i) => {
3913
4000
  const fieldIndex = parentFieldIndex + i;
3914
4001
  if (field.referencedType !== undefined) {
3915
4002
  let fieldType = field.type;
3916
- let refType = schemaTypes[field.referencedType];
4003
+ let refType = typeContext.get(field.referencedType);
3917
4004
  // map or array of primitive type (-1)
3918
4005
  if (!refType) {
3919
4006
  const typeInfo = field.type.split(":");
3920
4007
  fieldType = typeInfo[0];
3921
- refType = typeInfo[1];
4008
+ refType = typeInfo[1]; // string
3922
4009
  }
3923
4010
  if (fieldType === "ref") {
3924
- // type(refType)(schemaType.prototype, field.name);
3925
4011
  Metadata.addField(metadata, fieldIndex, field.name, refType);
3926
4012
  }
3927
4013
  else {
3928
- // type({ [fieldType]: refType } as DefinitionType)(schemaType.prototype, field.name);
3929
4014
  Metadata.addField(metadata, fieldIndex, field.name, { [fieldType]: refType });
3930
4015
  }
3931
4016
  }
3932
4017
  else {
3933
- // type(field.type as PrimitiveType)(schemaType.prototype, field.name);
3934
4018
  Metadata.addField(metadata, fieldIndex, field.name, field.type);
3935
4019
  }
3936
4020
  });
3937
4021
  });
3938
- return new (schemaTypes[0])();
4022
+ // @ts-ignore
4023
+ return new (typeContext.get(0))();
3939
4024
  }
3940
4025
  }
3941
4026
  __decorate([
3942
4027
  type([ReflectionType])
3943
4028
  ], Reflection.prototype, "types", void 0);
3944
4029
 
4030
+ function getDecoderStateCallbacks(decoder) {
4031
+ const $root = decoder.root;
4032
+ const callbacks = $root.callbacks;
4033
+ let isTriggeringOnAdd = false;
4034
+ decoder.triggerChanges = function (allChanges) {
4035
+ const uniqueRefIds = new Set();
4036
+ for (let i = 0, l = allChanges.length; i < l; i++) {
4037
+ const change = allChanges[i];
4038
+ const refId = change.refId;
4039
+ const ref = change.ref;
4040
+ const $callbacks = callbacks[refId];
4041
+ if (!$callbacks) {
4042
+ continue;
4043
+ }
4044
+ //
4045
+ // trigger onRemove on child structure.
4046
+ //
4047
+ if ((change.op & exports.OPERATION.DELETE) === exports.OPERATION.DELETE &&
4048
+ change.previousValue instanceof Schema) {
4049
+ const deleteCallbacks = callbacks[$root.refIds.get(change.previousValue)]?.[exports.OPERATION.DELETE];
4050
+ for (let i = deleteCallbacks?.length - 1; i >= 0; i--) {
4051
+ deleteCallbacks[i]();
4052
+ }
4053
+ }
4054
+ if (ref instanceof Schema) {
4055
+ //
4056
+ // Handle schema instance
4057
+ //
4058
+ if (!uniqueRefIds.has(refId)) {
4059
+ // trigger onChange
4060
+ const replaceCallbacks = $callbacks?.[exports.OPERATION.REPLACE];
4061
+ for (let i = replaceCallbacks?.length - 1; i >= 0; i--) {
4062
+ replaceCallbacks[i]();
4063
+ // try {
4064
+ // } catch (e) {
4065
+ // console.error(e);
4066
+ // }
4067
+ }
4068
+ }
4069
+ if ($callbacks.hasOwnProperty(change.field)) {
4070
+ const fieldCallbacks = $callbacks[change.field];
4071
+ for (let i = fieldCallbacks?.length - 1; i >= 0; i--) {
4072
+ fieldCallbacks[i](change.value, change.previousValue);
4073
+ // try {
4074
+ // } catch (e) {
4075
+ // console.error(e);
4076
+ // }
4077
+ }
4078
+ }
4079
+ }
4080
+ else {
4081
+ //
4082
+ // Handle collection of items
4083
+ //
4084
+ if ((change.op & exports.OPERATION.DELETE) === exports.OPERATION.DELETE) {
4085
+ //
4086
+ // FIXME: `previousValue` should always be available.
4087
+ //
4088
+ if (change.previousValue !== undefined) {
4089
+ // triger onRemove
4090
+ const deleteCallbacks = $callbacks[exports.OPERATION.DELETE];
4091
+ for (let i = deleteCallbacks?.length - 1; i >= 0; i--) {
4092
+ deleteCallbacks[i](change.previousValue, change.dynamicIndex ?? change.field);
4093
+ }
4094
+ }
4095
+ // Handle DELETE_AND_ADD operations
4096
+ // FIXME: should we set "isTriggeringOnAdd" here?
4097
+ if ((change.op & exports.OPERATION.ADD) === exports.OPERATION.ADD) {
4098
+ const addCallbacks = $callbacks[exports.OPERATION.ADD];
4099
+ for (let i = addCallbacks?.length - 1; i >= 0; i--) {
4100
+ addCallbacks[i](change.value, change.dynamicIndex ?? change.field);
4101
+ }
4102
+ }
4103
+ }
4104
+ else if ((change.op & exports.OPERATION.ADD) === exports.OPERATION.ADD && change.previousValue === undefined) {
4105
+ // triger onAdd
4106
+ isTriggeringOnAdd = true;
4107
+ const addCallbacks = $callbacks[exports.OPERATION.ADD];
4108
+ for (let i = addCallbacks?.length - 1; i >= 0; i--) {
4109
+ addCallbacks[i](change.value, change.dynamicIndex ?? change.field);
4110
+ }
4111
+ isTriggeringOnAdd = false;
4112
+ }
4113
+ // trigger onChange
4114
+ if (change.value !== change.previousValue) {
4115
+ const replaceCallbacks = $callbacks[exports.OPERATION.REPLACE];
4116
+ for (let i = replaceCallbacks?.length - 1; i >= 0; i--) {
4117
+ replaceCallbacks[i](change.value, change.dynamicIndex ?? change.field);
4118
+ }
4119
+ }
4120
+ }
4121
+ uniqueRefIds.add(refId);
4122
+ }
4123
+ };
4124
+ function getProxy(metadataOrType, context) {
4125
+ let metadata = context.instance?.constructor[Symbol.metadata] || metadataOrType;
4126
+ let isCollection = ((context.instance && typeof (context.instance['forEach']) === "function") ||
4127
+ (metadataOrType && typeof (metadataOrType[Symbol.metadata]) === "undefined"));
4128
+ if (metadata && !isCollection) {
4129
+ const onAdd = function (ref, prop, callback, immediate) {
4130
+ // immediate trigger
4131
+ if (immediate &&
4132
+ context.instance[prop] !== undefined &&
4133
+ !isTriggeringOnAdd // FIXME: This is a workaround (https://github.com/colyseus/schema/issues/147)
4134
+ ) {
4135
+ callback(context.instance[prop], undefined);
4136
+ }
4137
+ return $root.addCallback($root.refIds.get(ref), prop, callback);
4138
+ };
4139
+ /**
4140
+ * Schema instances
4141
+ */
4142
+ return new Proxy({
4143
+ listen: function listen(prop, callback, immediate = true) {
4144
+ if (context.instance) {
4145
+ return onAdd(context.instance, prop, callback, immediate);
4146
+ }
4147
+ else {
4148
+ // collection instance not received yet
4149
+ context.onInstanceAvailable((ref, existing) => onAdd(ref, prop, callback, immediate && existing));
4150
+ }
4151
+ },
4152
+ onChange: function onChange(callback) {
4153
+ return $root.addCallback($root.refIds.get(context.instance), exports.OPERATION.REPLACE, callback);
4154
+ },
4155
+ bindTo: function bindTo(targetObject, properties) {
4156
+ //
4157
+ // TODO: refactor this implementation. There is room for improvement here.
4158
+ //
4159
+ if (!properties) {
4160
+ properties = Object.keys(metadata);
4161
+ }
4162
+ return $root.addCallback($root.refIds.get(context.instance), exports.OPERATION.REPLACE, () => {
4163
+ properties.forEach((prop) => targetObject[prop] = context.instance[prop]);
4164
+ });
4165
+ }
4166
+ }, {
4167
+ get(target, prop) {
4168
+ if (metadata[prop]) {
4169
+ const instance = context.instance?.[prop];
4170
+ const onInstanceAvailable = ((callback) => {
4171
+ const unbind = $(context.instance).listen(prop, (value, _) => {
4172
+ callback(value, false);
4173
+ // FIXME: by "unbinding" the callback here,
4174
+ // it will not support when the server
4175
+ // re-instantiates the instance.
4176
+ //
4177
+ unbind?.();
4178
+ }, false);
4179
+ // has existing value
4180
+ if ($root.refIds.get(instance) !== undefined) {
4181
+ callback(instance, true);
4182
+ }
4183
+ });
4184
+ return getProxy(metadata[prop].type, {
4185
+ instance,
4186
+ parentInstance: context.instance,
4187
+ onInstanceAvailable,
4188
+ });
4189
+ }
4190
+ else {
4191
+ // accessing the function
4192
+ return target[prop];
4193
+ }
4194
+ },
4195
+ has(target, prop) { return metadata[prop] !== undefined; },
4196
+ set(_, _1, _2) { throw new Error("not allowed"); },
4197
+ deleteProperty(_, _1) { throw new Error("not allowed"); },
4198
+ });
4199
+ }
4200
+ else {
4201
+ /**
4202
+ * Collection instances
4203
+ */
4204
+ const onAdd = function (ref, callback, immediate) {
4205
+ // Trigger callback on existing items
4206
+ if (immediate) {
4207
+ ref.forEach((v, k) => callback(v, k));
4208
+ }
4209
+ return $root.addCallback($root.refIds.get(ref), exports.OPERATION.ADD, callback);
4210
+ };
4211
+ const onRemove = function (ref, callback) {
4212
+ return $root.addCallback($root.refIds.get(ref), exports.OPERATION.DELETE, callback);
4213
+ };
4214
+ return new Proxy({
4215
+ onAdd: function (callback, immediate = true) {
4216
+ //
4217
+ // https://github.com/colyseus/schema/issues/147
4218
+ // If parent instance has "onAdd" registered, avoid triggering immediate callback.
4219
+ //
4220
+ // FIXME: "isTriggeringOnAdd" is a workaround. We should find a better way to handle this.
4221
+ //
4222
+ if (context.onInstanceAvailable) {
4223
+ // collection instance not received yet
4224
+ context.onInstanceAvailable((ref, existing) => onAdd(ref, callback, immediate && existing && !isTriggeringOnAdd));
4225
+ }
4226
+ else if (context.instance) {
4227
+ onAdd(context.instance, callback, immediate && !isTriggeringOnAdd);
4228
+ }
4229
+ },
4230
+ onRemove: function (callback) {
4231
+ if (context.onInstanceAvailable) {
4232
+ // collection instance not received yet
4233
+ context.onInstanceAvailable((ref) => onRemove(ref, callback));
4234
+ }
4235
+ else if (context.instance) {
4236
+ onRemove(context.instance, callback);
4237
+ }
4238
+ },
4239
+ }, {
4240
+ get(target, prop) {
4241
+ if (!target[prop]) {
4242
+ throw new Error(`Can't access '${prop}' through callback proxy. access the instance directly.`);
4243
+ }
4244
+ return target[prop];
4245
+ },
4246
+ has(target, prop) { return target[prop] !== undefined; },
4247
+ set(_, _1, _2) { throw new Error("not allowed"); },
4248
+ deleteProperty(_, _1) { throw new Error("not allowed"); },
4249
+ });
4250
+ }
4251
+ }
4252
+ function $(instance) {
4253
+ return getProxy(undefined, { instance });
4254
+ }
4255
+ return $;
4256
+ }
4257
+
4258
+ function getRawChangesCallback(decoder, callback) {
4259
+ decoder.triggerChanges = callback;
4260
+ }
4261
+
3945
4262
  class StateView {
3946
4263
  constructor() {
3947
4264
  /**
@@ -3964,12 +4281,18 @@
3964
4281
  console.warn("StateView#add(), invalid object:", obj);
3965
4282
  return this;
3966
4283
  }
4284
+ // FIXME: ArraySchema/MapSchema does not have metadata
4285
+ const metadata = obj.constructor[Symbol.metadata];
3967
4286
  let changeTree = obj[$changes];
3968
4287
  this.items.add(changeTree);
3969
4288
  // Add children of this ChangeTree to this view
3970
- changeTree.forEachChild((change, _) => this.add(change.ref, tag));
3971
- // FIXME: ArraySchema/MapSchema does not have metadata
3972
- const metadata = obj.constructor[Symbol.metadata];
4289
+ changeTree.forEachChild((change, index) => {
4290
+ // Do not ADD children that don't have the same tag
4291
+ if (metadata && metadata[metadata[index]].tag !== tag) {
4292
+ return;
4293
+ }
4294
+ this.add(change.ref, tag);
4295
+ });
3973
4296
  // add parent ChangeTree's, if they are invisible to this view
3974
4297
  // TODO: REFACTOR addParent()
3975
4298
  this.addParent(changeTree, tag);
@@ -3996,7 +4319,6 @@
3996
4319
  tags = this.tags.get(changeTree);
3997
4320
  }
3998
4321
  tags.add(tag);
3999
- // console.log("BY TAG:", tag);
4000
4322
  // Ref: add tagged properties
4001
4323
  metadata?.[-3]?.[tag]?.forEach((index) => {
4002
4324
  if (changeTree.getChange(index) !== exports.OPERATION.DELETE) {
@@ -4166,10 +4488,10 @@
4166
4488
  exports.encode = encode;
4167
4489
  exports.encodeKeyValueOperation = encodeArray;
4168
4490
  exports.encodeSchemaOperation = encodeSchemaOperation;
4491
+ exports.getDecoderStateCallbacks = getDecoderStateCallbacks;
4492
+ exports.getRawChangesCallback = getRawChangesCallback;
4169
4493
  exports.registerType = registerType;
4170
4494
  exports.type = type;
4171
4495
  exports.view = view;
4172
4496
 
4173
- Object.defineProperty(exports, '__esModule', { value: true });
4174
-
4175
4497
  }));