@colyseus/schema 3.0.76 → 4.0.0

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 (160) hide show
  1. package/build/cjs/index.js +781 -434
  2. package/build/cjs/index.js.map +1 -1
  3. package/build/esm/index.mjs +779 -435
  4. package/build/esm/index.mjs.map +1 -1
  5. package/build/umd/index.js +781 -434
  6. package/lib/Metadata.js +1 -5
  7. package/lib/Metadata.js.map +1 -1
  8. package/lib/Reflection.d.ts +50 -17
  9. package/lib/Reflection.js +151 -202
  10. package/lib/Reflection.js.map +1 -1
  11. package/lib/Schema.d.ts +13 -1
  12. package/lib/Schema.js +73 -9
  13. package/lib/Schema.js.map +1 -1
  14. package/lib/annotations.d.ts +6 -1
  15. package/lib/annotations.js +8 -34
  16. package/lib/annotations.js.map +1 -1
  17. package/lib/bench_encode.js +34 -1
  18. package/lib/bench_encode.js.map +1 -1
  19. package/lib/codegen/api.js +35 -2
  20. package/lib/codegen/api.js.map +1 -1
  21. package/lib/codegen/cli.js +4 -1
  22. package/lib/codegen/cli.js.map +1 -1
  23. package/lib/codegen/parser.js +35 -2
  24. package/lib/codegen/parser.js.map +1 -1
  25. package/lib/codegen/types.js +34 -1
  26. package/lib/codegen/types.js.map +1 -1
  27. package/lib/decoder/DecodeOperation.d.ts +2 -2
  28. package/lib/decoder/DecodeOperation.js +3 -3
  29. package/lib/decoder/DecodeOperation.js.map +1 -1
  30. package/lib/decoder/Decoder.d.ts +3 -3
  31. package/lib/decoder/Decoder.js +2 -2
  32. package/lib/decoder/Decoder.js.map +1 -1
  33. package/lib/decoder/ReferenceTracker.d.ts +0 -1
  34. package/lib/decoder/ReferenceTracker.js +9 -7
  35. package/lib/decoder/ReferenceTracker.js.map +1 -1
  36. package/lib/decoder/strategy/Callbacks.d.ts +154 -0
  37. package/lib/decoder/strategy/Callbacks.js +340 -0
  38. package/lib/decoder/strategy/Callbacks.js.map +1 -0
  39. package/lib/decoder/strategy/{StateCallbacks.d.ts → getDecoderStateCallbacks.d.ts} +6 -0
  40. package/lib/decoder/strategy/{StateCallbacks.js → getDecoderStateCallbacks.js} +17 -10
  41. package/lib/decoder/strategy/getDecoderStateCallbacks.js.map +1 -0
  42. package/lib/encoder/ChangeTree.d.ts +2 -2
  43. package/lib/encoder/ChangeTree.js.map +1 -1
  44. package/lib/encoder/EncodeOperation.d.ts +2 -2
  45. package/lib/encoder/EncodeOperation.js +3 -3
  46. package/lib/encoder/EncodeOperation.js.map +1 -1
  47. package/lib/encoder/Encoder.d.ts +6 -6
  48. package/lib/encoder/Encoder.js +19 -18
  49. package/lib/encoder/Encoder.js.map +1 -1
  50. package/lib/encoder/Root.js +17 -14
  51. package/lib/encoder/Root.js.map +1 -1
  52. package/lib/encoder/StateView.js +13 -12
  53. package/lib/encoder/StateView.js.map +1 -1
  54. package/lib/encoding/decode.d.ts +2 -2
  55. package/lib/encoding/encode.d.ts +3 -1
  56. package/lib/encoding/encode.js.map +1 -1
  57. package/lib/index.d.ts +3 -2
  58. package/lib/index.js +7 -3
  59. package/lib/index.js.map +1 -1
  60. package/lib/types/HelperTypes.d.ts +7 -14
  61. package/lib/types/HelperTypes.js.map +1 -1
  62. package/lib/types/custom/ArraySchema.d.ts +2 -1
  63. package/lib/types/custom/ArraySchema.js.map +1 -1
  64. package/lib/types/custom/CollectionSchema.d.ts +2 -1
  65. package/lib/types/custom/CollectionSchema.js.map +1 -1
  66. package/lib/types/custom/MapSchema.d.ts +3 -2
  67. package/lib/types/custom/MapSchema.js.map +1 -1
  68. package/lib/types/custom/SetSchema.d.ts +2 -1
  69. package/lib/types/custom/SetSchema.js.map +1 -1
  70. package/lib/types/symbols.d.ts +1 -0
  71. package/lib/types/symbols.js +2 -1
  72. package/lib/types/symbols.js.map +1 -1
  73. package/lib/utils.js +1 -1
  74. package/lib/utils.js.map +1 -1
  75. package/package.json +12 -16
  76. package/src/Metadata.ts +1 -5
  77. package/src/Reflection.ts +185 -174
  78. package/src/Schema.ts +81 -13
  79. package/src/annotations.ts +14 -40
  80. package/src/codegen/parser.ts +1 -1
  81. package/src/decoder/DecodeOperation.ts +9 -9
  82. package/src/decoder/Decoder.ts +6 -6
  83. package/src/decoder/ReferenceTracker.ts +10 -8
  84. package/src/decoder/strategy/Callbacks.ts +547 -0
  85. package/src/decoder/strategy/{StateCallbacks.ts → getDecoderStateCallbacks.ts} +17 -11
  86. package/src/encoder/ChangeTree.ts +4 -7
  87. package/src/encoder/EncodeOperation.ts +9 -9
  88. package/src/encoder/Encoder.ts +26 -18
  89. package/src/encoder/Root.ts +20 -15
  90. package/src/encoder/StateView.ts +15 -13
  91. package/src/encoding/encode.ts +1 -1
  92. package/src/index.ts +3 -2
  93. package/src/types/HelperTypes.ts +13 -11
  94. package/src/types/custom/ArraySchema.ts +2 -1
  95. package/src/types/custom/CollectionSchema.ts +4 -2
  96. package/src/types/custom/MapSchema.ts +4 -2
  97. package/src/types/custom/SetSchema.ts +3 -1
  98. package/src/types/symbols.ts +1 -0
  99. package/src/utils.ts +2 -2
  100. package/lib/Decoder.d.ts +0 -16
  101. package/lib/Decoder.js +0 -182
  102. package/lib/Decoder.js.map +0 -1
  103. package/lib/Encoder.d.ts +0 -13
  104. package/lib/Encoder.js +0 -79
  105. package/lib/Encoder.js.map +0 -1
  106. package/lib/changes/ChangeSet.d.ts +0 -12
  107. package/lib/changes/ChangeSet.js +0 -35
  108. package/lib/changes/ChangeSet.js.map +0 -1
  109. package/lib/changes/ChangeTree.d.ts +0 -53
  110. package/lib/changes/ChangeTree.js +0 -202
  111. package/lib/changes/ChangeTree.js.map +0 -1
  112. package/lib/changes/DecodeOperation.d.ts +0 -15
  113. package/lib/changes/DecodeOperation.js +0 -186
  114. package/lib/changes/DecodeOperation.js.map +0 -1
  115. package/lib/changes/EncodeOperation.d.ts +0 -18
  116. package/lib/changes/EncodeOperation.js +0 -130
  117. package/lib/changes/EncodeOperation.js.map +0 -1
  118. package/lib/changes/ReferenceTracker.d.ts +0 -14
  119. package/lib/changes/ReferenceTracker.js +0 -83
  120. package/lib/changes/ReferenceTracker.js.map +0 -1
  121. package/lib/changes/consts.d.ts +0 -14
  122. package/lib/changes/consts.js +0 -18
  123. package/lib/changes/consts.js.map +0 -1
  124. package/lib/decoder/strategy/StateCallbacks.js.map +0 -1
  125. package/lib/decoding/decode.d.ts +0 -48
  126. package/lib/decoding/decode.js +0 -267
  127. package/lib/decoding/decode.js.map +0 -1
  128. package/lib/ecs.d.ts +0 -11
  129. package/lib/ecs.js +0 -160
  130. package/lib/ecs.js.map +0 -1
  131. package/lib/filters/index.d.ts +0 -8
  132. package/lib/filters/index.js +0 -24
  133. package/lib/filters/index.js.map +0 -1
  134. package/lib/spec.d.ts +0 -13
  135. package/lib/spec.js +0 -42
  136. package/lib/spec.js.map +0 -1
  137. package/lib/types/ArraySchema.d.ts +0 -238
  138. package/lib/types/ArraySchema.js +0 -555
  139. package/lib/types/ArraySchema.js.map +0 -1
  140. package/lib/types/CollectionSchema.d.ts +0 -35
  141. package/lib/types/CollectionSchema.js +0 -150
  142. package/lib/types/CollectionSchema.js.map +0 -1
  143. package/lib/types/MapSchema.d.ts +0 -38
  144. package/lib/types/MapSchema.js +0 -215
  145. package/lib/types/MapSchema.js.map +0 -1
  146. package/lib/types/SetSchema.d.ts +0 -32
  147. package/lib/types/SetSchema.js +0 -162
  148. package/lib/types/SetSchema.js.map +0 -1
  149. package/lib/types/typeRegistry.d.ts +0 -5
  150. package/lib/types/typeRegistry.js +0 -13
  151. package/lib/types/typeRegistry.js.map +0 -1
  152. package/lib/usage.d.ts +0 -1
  153. package/lib/usage.js +0 -22
  154. package/lib/usage.js.map +0 -1
  155. package/lib/v3.d.ts +0 -1
  156. package/lib/v3.js +0 -427
  157. package/lib/v3.js.map +0 -1
  158. package/lib/v3_experiment.d.ts +0 -1
  159. package/lib/v3_experiment.js +0 -407
  160. package/lib/v3_experiment.js.map +0 -1
package/src/Schema.ts CHANGED
@@ -4,7 +4,7 @@ import { DEFAULT_VIEW_TAG, type DefinitionType } from "./annotations";
4
4
  import { AssignableProps, NonFunctionPropNames, ToJSON } from './types/HelperTypes';
5
5
 
6
6
  import { ChangeSet, ChangeSetName, ChangeTree, IRef, Ref } from './encoder/ChangeTree';
7
- import { $changes, $decoder, $deleteByIndex, $descriptors, $encoder, $filter, $getByIndex, $track } from './types/symbols';
7
+ import { $changes, $decoder, $deleteByIndex, $descriptors, $encoder, $filter, $getByIndex, $refId, $track } from './types/symbols';
8
8
  import { StateView } from './encoder/StateView';
9
9
 
10
10
  import { encodeSchemaOperation } from './encoder/EncodeOperation';
@@ -22,6 +22,8 @@ export class Schema<C = any> implements IRef {
22
22
  static [$encoder] = encodeSchemaOperation;
23
23
  static [$decoder] = decodeSchemaOperation;
24
24
 
25
+ [$refId]?: number;
26
+
25
27
  /**
26
28
  * Assign the property descriptors required to track changes on this instance.
27
29
  * @param instance
@@ -95,13 +97,79 @@ export class Schema<C = any> implements IRef {
95
97
  }
96
98
  }
97
99
 
98
- public assign<T extends Partial<this>>(
99
- props: AssignableProps<T>,
100
- ): this {
100
+ /**
101
+ * Assign properties to the instance.
102
+ * @param props Properties to assign to the instance
103
+ * @returns
104
+ */
105
+ public assign<T extends Partial<this>>(props: AssignableProps<T>,): this {
101
106
  Object.assign(this, props);
102
107
  return this;
103
108
  }
104
109
 
110
+ /**
111
+ * Restore the instance from JSON data.
112
+ * @param jsonData JSON data to restore the instance from
113
+ * @returns
114
+ */
115
+ public restore(jsonData: ToJSON<this>): this {
116
+ const metadata: Metadata = (this.constructor as typeof Schema)[Symbol.metadata];
117
+
118
+ for (const fieldIndex in metadata) {
119
+ const field = metadata[fieldIndex as any as number];
120
+ const fieldName = field.name as keyof this;
121
+ const fieldType = field.type;
122
+ const value = (jsonData as any)[fieldName];
123
+
124
+ if (value === undefined || value === null) {
125
+ continue;
126
+ }
127
+
128
+ if (typeof fieldType === "string") {
129
+ // Primitive type: assign directly
130
+ this[fieldName] = value;
131
+
132
+ } else if (Schema.is(fieldType)) {
133
+ // Schema type: create instance and restore
134
+ const instance = new (fieldType as typeof Schema)();
135
+ instance.restore(value);
136
+ this[fieldName] = instance as any;
137
+
138
+ } else if (typeof fieldType === "object") {
139
+ // Collection types: { map: ... }, { array: ... }, etc.
140
+ const collectionType = Object.keys(fieldType)[0] as string;
141
+ const childType = (fieldType as any)[collectionType];
142
+
143
+ if (collectionType === "map") {
144
+ const mapSchema = this[fieldName] as any;
145
+ for (const key in value) {
146
+ if (Schema.is(childType)) {
147
+ const childInstance = new (childType as typeof Schema)();
148
+ childInstance.restore(value[key]);
149
+ mapSchema.set(key, childInstance);
150
+ } else {
151
+ mapSchema.set(key, value[key]);
152
+ }
153
+ }
154
+
155
+ } else if (collectionType === "array") {
156
+ const arraySchema = this[fieldName] as any;
157
+ for (let i = 0; i < value.length; i++) {
158
+ if (Schema.is(childType)) {
159
+ const childInstance = new (childType as typeof Schema)();
160
+ childInstance.restore(value[i]);
161
+ arraySchema.push(childInstance);
162
+ } else {
163
+ arraySchema.push(value[i]);
164
+ }
165
+ }
166
+ }
167
+ }
168
+ }
169
+
170
+ return this;
171
+ }
172
+
105
173
  /**
106
174
  * (Server-side): Flag a property to be encoded for the next patch.
107
175
  * @param instance Schema instance
@@ -190,7 +258,7 @@ export class Schema<C = any> implements IRef {
190
258
  const contents = (showContents) ? ` - ${JSON.stringify(ref.toJSON())}` : "";
191
259
  const changeTree: ChangeTree = ref[$changes];
192
260
 
193
- const refId = (decoder) ? decoder.root.refIds.get(ref) : changeTree.refId;
261
+ const refId = (ref as IRef)[$refId];
194
262
  const root = (decoder) ? decoder.root : changeTree.root;
195
263
 
196
264
  // log reference count if > 1
@@ -218,7 +286,7 @@ export class Schema<C = any> implements IRef {
218
286
  let current = ref[$changes].root[changeSet].next;
219
287
  while (current) {
220
288
  if (current.changeTree) {
221
- encodeOrder.push(current.changeTree.refId);
289
+ encodeOrder.push(current.changeTree.ref[$refId]);
222
290
  }
223
291
  current = current.next;
224
292
  }
@@ -243,7 +311,7 @@ export class Schema<C = any> implements IRef {
243
311
  const changeSet = (isEncodeAll) ? changeTree.allChanges : changeTree.changes;
244
312
  const changeSetName = (isEncodeAll) ? "allChanges" : "changes";
245
313
 
246
- let output = `${instance.constructor.name} (${changeTree.refId}) -> .${changeSetName}:\n`;
314
+ let output = `${instance.constructor.name} (${instance[$refId]}) -> .${changeSetName}:\n`;
247
315
 
248
316
  function dumpChangeSet(changeSet: ChangeSet) {
249
317
  changeSet.operations
@@ -262,7 +330,7 @@ export class Schema<C = any> implements IRef {
262
330
  changeTree.filteredChanges &&
263
331
  (changeTree.filteredChanges.operations).filter(op => op).length > 0
264
332
  ) {
265
- output += `${instance.constructor.name} (${changeTree.refId}) -> .filteredChanges:\n`;
333
+ output += `${instance.constructor.name} (${instance[$refId]}) -> .filteredChanges:\n`;
266
334
  dumpChangeSet(changeTree.filteredChanges);
267
335
  }
268
336
 
@@ -272,7 +340,7 @@ export class Schema<C = any> implements IRef {
272
340
  changeTree.allFilteredChanges &&
273
341
  (changeTree.allFilteredChanges.operations).filter(op => op).length > 0
274
342
  ) {
275
- output += `${instance.constructor.name} (${changeTree.refId}) -> .allFilteredChanges:\n`;
343
+ output += `${instance.constructor.name} (${instance[$refId]}) -> .allFilteredChanges:\n`;
276
344
  dumpChangeSet(changeTree.allFilteredChanges);
277
345
  }
278
346
 
@@ -313,14 +381,14 @@ export class Schema<C = any> implements IRef {
313
381
  }
314
382
 
315
383
  if (includeChangeTree) {
316
- instanceRefIds.push(changeTree.refId);
384
+ instanceRefIds.push(changeTree.ref[$refId]);
317
385
  totalOperations += Object.keys(changes).length;
318
386
  changeTrees.set(changeTree, parentChangeTrees.reverse());
319
387
  }
320
388
  }
321
389
 
322
390
  output += "---\n"
323
- output += `root refId: ${rootChangeTree.refId}\n`;
391
+ output += `root refId: ${rootChangeTree.ref[$refId]}\n`;
324
392
  output += `Total instances: ${instanceRefIds.length} (refIds: ${instanceRefIds.join(", ")})\n`;
325
393
  output += `Total changes: ${totalOperations}\n`;
326
394
  output += "---\n"
@@ -330,7 +398,7 @@ export class Schema<C = any> implements IRef {
330
398
  for (const [changeTree, parentChangeTrees] of changeTrees.entries()) {
331
399
  parentChangeTrees.forEach((parentChangeTree, level) => {
332
400
  if (!visitedParents.has(parentChangeTree)) {
333
- output += `${getIndent(level)}${parentChangeTree.ref.constructor.name} (refId: ${parentChangeTree.refId})\n`;
401
+ output += `${getIndent(level)}${parentChangeTree.ref.constructor.name} (refId: ${parentChangeTree.ref[$refId]})\n`;
334
402
  visitedParents.add(parentChangeTree);
335
403
  }
336
404
  });
@@ -340,7 +408,7 @@ export class Schema<C = any> implements IRef {
340
408
  const indent = getIndent(level);
341
409
 
342
410
  const parentIndex = (level > 0) ? `(${changeTree.parentIndex}) ` : "";
343
- output += `${indent}${parentIndex}${changeTree.ref.constructor.name} (refId: ${changeTree.refId}) - changes: ${Object.keys(changes).length}\n`;
411
+ output += `${indent}${parentIndex}${changeTree.ref.constructor.name} (refId: ${changeTree.ref[$refId]}) - changes: ${Object.keys(changes).length}\n`;
344
412
 
345
413
  for (const index in changes) {
346
414
  const operation = changes[index];
@@ -33,11 +33,11 @@ export type PrimitiveType = RawPrimitiveType | typeof Schema | object;
33
33
  // TODO: infer "default" value type correctly.
34
34
  export type DefinitionType<T extends PrimitiveType = PrimitiveType> = T
35
35
  | T[]
36
- | { type: T, default?: InferValueType<T>, view?: boolean | number }
37
- | { array: T, default?: ArraySchema<InferValueType<T>>, view?: boolean | number }
38
- | { map: T, default?: MapSchema<InferValueType<T>>, view?: boolean | number }
39
- | { collection: T, default?: CollectionSchema<InferValueType<T>>, view?: boolean | number }
40
- | { set: T, default?: SetSchema<InferValueType<T>>, view?: boolean | number };
36
+ | { type: T, default?: InferValueType<T>, view?: boolean | number, sync?: boolean }
37
+ | { array: T, default?: ArraySchema<InferValueType<T>>, view?: boolean | number, sync?: boolean }
38
+ | { map: T, default?: MapSchema<InferValueType<T>>, view?: boolean | number, sync?: boolean }
39
+ | { collection: T, default?: CollectionSchema<InferValueType<T>>, view?: boolean | number, sync?: boolean }
40
+ | { set: T, default?: SetSchema<InferValueType<T>>, view?: boolean | number, sync?: boolean };
41
41
 
42
42
  export type Definition = { [field: string]: DefinitionType };
43
43
 
@@ -574,7 +574,10 @@ export function schema<
574
574
  : value['view'];
575
575
  }
576
576
 
577
- fields[fieldName] = getNormalizedType(value);
577
+ // allow to define a field as not synced
578
+ if (value['sync'] !== false) {
579
+ fields[fieldName] = getNormalizedType(value);
580
+ }
578
581
 
579
582
  // If no explicit default provided, handle automatic instantiation for collection types
580
583
  if (!Object.prototype.hasOwnProperty.call(value, 'default')) {
@@ -597,12 +600,7 @@ export function schema<
597
600
 
598
601
  } else if (value['type'] !== undefined && Schema.is(value['type'])) {
599
602
  // Direct Schema type: Type → new Type()
600
- if (!value['type'].prototype.initialize || value['type'].prototype.initialize.length === 0) {
601
- // only auto-initialize Schema instances if:
602
- // - they don't have an initialize method
603
- // - or initialize method doesn't accept any parameters
604
- defaultValues[fieldName] = new value['type']();
605
- }
603
+ defaultValues[fieldName] = new value['type']();
606
604
  }
607
605
  } else {
608
606
  defaultValues[fieldName] = value['default'];
@@ -612,12 +610,7 @@ export function schema<
612
610
  } else if (typeof (value) === "function") {
613
611
  if (Schema.is(value)) {
614
612
  // Direct Schema type: Type → new Type()
615
- if (!value.prototype.initialize || value.prototype.initialize.length === 0) {
616
- // only auto-initialize Schema instances if:
617
- // - they don't have an initialize method
618
- // - or initialize method doesn't accept any parameters
619
- defaultValues[fieldName] = new value();
620
- }
613
+ defaultValues[fieldName] = new value();
621
614
  fields[fieldName] = getNormalizedType(value);
622
615
  } else {
623
616
  methods[fieldName] = value;
@@ -645,33 +638,14 @@ export function schema<
645
638
  return defaults;
646
639
  };
647
640
 
648
- const getParentProps = (props: any) => {
649
- const fieldNames = Object.keys(fields);
650
- const parentProps: any = {};
651
- for (const key in props) {
652
- if (!fieldNames.includes(key)) {
653
- parentProps[key] = props[key];
654
- }
655
- }
656
- return parentProps;
657
- }
658
-
659
641
  /** @codegen-ignore */
660
642
  const klass = Metadata.setFields<any>(class extends (inherits as any) {
661
643
  constructor(...args: any[]) {
644
+ super(Object.assign({}, getDefaultValues(), args[0] || {}));
645
+
662
646
  // call initialize method
663
647
  if (methods.initialize && typeof methods.initialize === 'function') {
664
- super(Object.assign({}, getDefaultValues(), getParentProps(args[0] || {})));
665
- /**
666
- * only call initialize() in the current class, not the parent ones.
667
- * see "should not call initialize automatically when creating an instance of inherited Schema"
668
- */
669
- if (new.target === klass) {
670
- methods.initialize.apply(this, args);
671
- }
672
-
673
- } else {
674
- super(Object.assign({}, getDefaultValues(), args[0] || {}));
648
+ methods.initialize.apply(this, args);
675
649
  }
676
650
  }
677
651
  }, fields) as SchemaWithExtendsConstructor<T, ExtractInitProps<T>, P>;
@@ -326,7 +326,7 @@ function inspectNode(node: ts.Node, context: Context, decoratorName: string) {
326
326
  break;
327
327
  }
328
328
 
329
- ts.forEachChild(node, (n) => inspectNode(n, context, decoratorName));
329
+ ts.forEachChild(node, (n: ts.Node) => inspectNode(n, context, decoratorName));
330
330
  }
331
331
 
332
332
  let parsedFiles: { [filename: string]: boolean };
@@ -4,7 +4,7 @@ import { Schema } from "../Schema";
4
4
  import type { Ref } from "../encoder/ChangeTree";
5
5
  import type { Decoder } from "./Decoder";
6
6
  import { Iterator, decode } from "../encoding/decode";
7
- import { $childType, $deleteByIndex, $getByIndex } from "../types/symbols";
7
+ import { $childType, $deleteByIndex, $getByIndex, $refId } from "../types/symbols";
8
8
 
9
9
  import type { MapSchema } from "../types/custom/MapSchema";
10
10
  import type { ArraySchema } from "../types/custom/ArraySchema";
@@ -27,7 +27,7 @@ export const DEFINITION_MISMATCH = -1;
27
27
 
28
28
  export type DecodeOperation<T extends Schema = any> = (
29
29
  decoder: Decoder<T>,
30
- bytes: Buffer,
30
+ bytes: Uint8Array,
31
31
  it: Iterator,
32
32
  ref: Ref,
33
33
  allChanges: DataChange[],
@@ -39,7 +39,7 @@ export function decodeValue<T extends Ref>(
39
39
  ref: T,
40
40
  index: number,
41
41
  type: any,
42
- bytes: Buffer,
42
+ bytes: Uint8Array,
43
43
  it: Iterator,
44
44
  allChanges: DataChange[],
45
45
  ) {
@@ -51,7 +51,7 @@ export function decodeValue<T extends Ref>(
51
51
  if ((operation & OPERATION.DELETE) === OPERATION.DELETE)
52
52
  {
53
53
  // Flag `refId` for garbage collection.
54
- const previousRefId = $root.refIds.get(previousValue);
54
+ const previousRefId = previousValue?.[$refId];
55
55
  if (previousRefId !== undefined) { $root.removeRef(previousRefId); }
56
56
 
57
57
  //
@@ -107,7 +107,7 @@ export function decodeValue<T extends Ref>(
107
107
  value[$childType] = Object.values(type)[0]; // cache childType for ArraySchema and MapSchema
108
108
 
109
109
  if (previousValue) {
110
- let previousRefId = $root.refIds.get(previousValue);
110
+ let previousRefId = previousValue[$refId];
111
111
 
112
112
  if (previousRefId !== undefined && refId !== previousRefId) {
113
113
  //
@@ -120,7 +120,7 @@ export function decodeValue<T extends Ref>(
120
120
 
121
121
  // if value is a schema, remove its reference
122
122
  if (typeof(value) === "object") {
123
- previousRefId = $root.refIds.get(value);
123
+ previousRefId = value[$refId];
124
124
  $root.removeRef(previousRefId);
125
125
  }
126
126
 
@@ -148,7 +148,7 @@ export function decodeValue<T extends Ref>(
148
148
 
149
149
  export const decodeSchemaOperation: DecodeOperation = function <T extends Schema>(
150
150
  decoder: Decoder<any>,
151
- bytes: Buffer,
151
+ bytes: Uint8Array,
152
152
  it: Iterator,
153
153
  ref: T,
154
154
  allChanges: DataChange[],
@@ -197,7 +197,7 @@ export const decodeSchemaOperation: DecodeOperation = function <T extends Schema
197
197
 
198
198
  export const decodeKeyValueOperation: DecodeOperation = function (
199
199
  decoder: Decoder<any>,
200
- bytes: Buffer,
200
+ bytes: Uint8Array,
201
201
  it: Iterator,
202
202
  ref: Ref,
203
203
  allChanges: DataChange[]
@@ -280,7 +280,7 @@ export const decodeKeyValueOperation: DecodeOperation = function (
280
280
 
281
281
  export const decodeArray: DecodeOperation = function (
282
282
  decoder: Decoder<any>,
283
- bytes: Buffer,
283
+ bytes: Uint8Array,
284
284
  it: Iterator,
285
285
  ref: ArraySchema,
286
286
  allChanges: DataChange[]
@@ -1,5 +1,5 @@
1
1
  import { TypeContext } from "../types/TypeContext";
2
- import { $changes, $childType, $decoder, $onDecodeEnd } from "../types/symbols";
2
+ import { $changes, $childType, $decoder, $onDecodeEnd, $refId } from "../types/symbols";
3
3
  import { Schema } from "../Schema";
4
4
 
5
5
  import { decode } from "../encoding/decode";
@@ -38,7 +38,7 @@ export class Decoder<T extends Schema = any> {
38
38
  }
39
39
 
40
40
  decode(
41
- bytes: Buffer,
41
+ bytes: Uint8Array,
42
42
  it: Iterator = { offset: 0 },
43
43
  ref: Ref = this.state,
44
44
  ) {
@@ -102,7 +102,7 @@ export class Decoder<T extends Schema = any> {
102
102
  return allChanges;
103
103
  }
104
104
 
105
- skipCurrentStructure(bytes: Buffer, it: Iterator, totalBytes: number) {
105
+ skipCurrentStructure(bytes: Uint8Array, it: Iterator, totalBytes: number) {
106
106
  //
107
107
  // keep skipping next bytes until reaches a known structure
108
108
  // by local decoder.
@@ -119,7 +119,7 @@ export class Decoder<T extends Schema = any> {
119
119
  }
120
120
  }
121
121
 
122
- getInstanceType(bytes: Buffer, it: Iterator, defaultType: typeof Schema): typeof Schema {
122
+ getInstanceType(bytes: Uint8Array, it: Iterator, defaultType: typeof Schema): typeof Schema {
123
123
  let type: typeof Schema;
124
124
 
125
125
  if (bytes[it.offset] === TYPE_ID) {
@@ -137,7 +137,7 @@ export class Decoder<T extends Schema = any> {
137
137
 
138
138
  removeChildRefs(ref: Collection, allChanges: DataChange[]) {
139
139
  const needRemoveRef = typeof ((ref as any)[$childType]) !== "string";
140
- const refId = this.root.refIds.get(ref as Ref);
140
+ const refId = (ref as Ref)[$refId];
141
141
 
142
142
  ref.forEach((value: any, key: any) => {
143
143
  allChanges.push({
@@ -150,7 +150,7 @@ export class Decoder<T extends Schema = any> {
150
150
  });
151
151
 
152
152
  if (needRemoveRef) {
153
- this.root.removeRef(this.root.refIds.get(value));
153
+ this.root.removeRef(value[$refId]);
154
154
  }
155
155
  });
156
156
  }
@@ -1,5 +1,5 @@
1
1
  import { Metadata } from "../Metadata";
2
- import { $childType } from "../types/symbols";
2
+ import { $childType, $refId } from "../types/symbols";
3
3
  import { Ref } from "../encoder/ChangeTree";
4
4
  import { spliceOne } from "../types/utils";
5
5
  import { OPERATION } from "../encoding/spec";
@@ -26,7 +26,6 @@ export class ReferenceTracker {
26
26
  // For direct access of structures during decoding time.
27
27
  //
28
28
  public refs = new Map<number, Ref>();
29
- public refIds = new WeakMap<Ref, number>();
30
29
 
31
30
  public refCount: { [refId: number]: number; } = {};
32
31
  public deletedRefs = new Set<number>();
@@ -41,7 +40,7 @@ export class ReferenceTracker {
41
40
  // for decoding
42
41
  addRef(refId: number, ref: Ref, incrementCount: boolean = true) {
43
42
  this.refs.set(refId, ref);
44
- this.refIds.set(ref, refId);
43
+ ref[$refId] = refId;
45
44
 
46
45
  if (incrementCount) {
47
46
  this.refCount[refId] = (this.refCount[refId] || 0) + 1;
@@ -104,9 +103,12 @@ export class ReferenceTracker {
104
103
  const metadata: Metadata = (ref.constructor as typeof Schema)[Symbol.metadata];
105
104
  for (const index in metadata) {
106
105
  const field = metadata[index as any as number].name;
107
- const childRefId = typeof(ref[field as keyof Ref]) === "object" && this.refIds.get((ref as any)[field]);
108
- if (childRefId && !this.deletedRefs.has(childRefId)) {
109
- this.removeRef(childRefId);
106
+ const child = ref[field as keyof Ref];
107
+ if (typeof(child) === "object" && child) {
108
+ const childRefId = (child as any)[$refId];
109
+ if (childRefId !== undefined && !this.deletedRefs.has(childRefId)) {
110
+ this.removeRef(childRefId);
111
+ }
110
112
  }
111
113
  }
112
114
 
@@ -114,8 +116,8 @@ export class ReferenceTracker {
114
116
  if (typeof ((ref as any)[$childType]) === "function") {
115
117
  Array.from((ref as MapSchema).values())
116
118
  .forEach((child) => {
117
- const childRefId = this.refIds.get(child);
118
- if (!this.deletedRefs.has(childRefId)) {
119
+ const childRefId = child[$refId];
120
+ if (childRefId !== undefined && !this.deletedRefs.has(childRefId)) {
119
121
  this.removeRef(childRefId);
120
122
  }
121
123
  });