@colyseus/schema 3.0.0-alpha.34 → 3.0.0-alpha.35

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 (63) hide show
  1. package/bin/schema-debug +4 -3
  2. package/build/cjs/index.js +465 -303
  3. package/build/cjs/index.js.map +1 -1
  4. package/build/esm/index.mjs +465 -303
  5. package/build/esm/index.mjs.map +1 -1
  6. package/build/umd/index.js +465 -303
  7. package/lib/Metadata.d.ts +5 -5
  8. package/lib/Metadata.js +17 -17
  9. package/lib/Metadata.js.map +1 -1
  10. package/lib/Schema.js +24 -17
  11. package/lib/Schema.js.map +1 -1
  12. package/lib/annotations.js +11 -11
  13. package/lib/annotations.js.map +1 -1
  14. package/lib/bench_encode.js +12 -5
  15. package/lib/bench_encode.js.map +1 -1
  16. package/lib/decoder/Decoder.js +1 -1
  17. package/lib/decoder/Decoder.js.map +1 -1
  18. package/lib/encoder/ChangeTree.d.ts +23 -7
  19. package/lib/encoder/ChangeTree.js +183 -106
  20. package/lib/encoder/ChangeTree.js.map +1 -1
  21. package/lib/encoder/EncodeOperation.d.ts +2 -1
  22. package/lib/encoder/EncodeOperation.js +2 -2
  23. package/lib/encoder/EncodeOperation.js.map +1 -1
  24. package/lib/encoder/Encoder.d.ts +3 -5
  25. package/lib/encoder/Encoder.js +93 -61
  26. package/lib/encoder/Encoder.js.map +1 -1
  27. package/lib/encoder/Root.d.ts +12 -7
  28. package/lib/encoder/Root.js +41 -20
  29. package/lib/encoder/Root.js.map +1 -1
  30. package/lib/encoder/StateView.d.ts +5 -5
  31. package/lib/encoder/StateView.js +29 -23
  32. package/lib/encoder/StateView.js.map +1 -1
  33. package/lib/encoding/encode.js +12 -9
  34. package/lib/encoding/encode.js.map +1 -1
  35. package/lib/types/TypeContext.js +2 -1
  36. package/lib/types/TypeContext.js.map +1 -1
  37. package/lib/types/custom/ArraySchema.js +27 -13
  38. package/lib/types/custom/ArraySchema.js.map +1 -1
  39. package/lib/types/custom/MapSchema.d.ts +3 -1
  40. package/lib/types/custom/MapSchema.js +7 -4
  41. package/lib/types/custom/MapSchema.js.map +1 -1
  42. package/lib/types/symbols.d.ts +8 -6
  43. package/lib/types/symbols.js +9 -7
  44. package/lib/types/symbols.js.map +1 -1
  45. package/lib/utils.js +6 -3
  46. package/lib/utils.js.map +1 -1
  47. package/package.json +1 -1
  48. package/src/Metadata.ts +22 -22
  49. package/src/Schema.ts +33 -25
  50. package/src/annotations.ts +12 -12
  51. package/src/bench_encode.ts +15 -6
  52. package/src/decoder/Decoder.ts +1 -1
  53. package/src/encoder/ChangeTree.ts +220 -115
  54. package/src/encoder/EncodeOperation.ts +5 -1
  55. package/src/encoder/Encoder.ts +110 -68
  56. package/src/encoder/Root.ts +41 -21
  57. package/src/encoder/StateView.ts +32 -28
  58. package/src/encoding/encode.ts +12 -9
  59. package/src/types/TypeContext.ts +2 -1
  60. package/src/types/custom/ArraySchema.ts +39 -17
  61. package/src/types/custom/MapSchema.ts +12 -5
  62. package/src/types/symbols.ts +10 -9
  63. package/src/utils.ts +7 -3
@@ -8,8 +8,6 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
8
8
  Object.defineProperty(exports, "__esModule", { value: true });
9
9
  const nanoid_1 = require("nanoid");
10
10
  const _1 = require(".");
11
- const benchmark = require("benchmark");
12
- const suite = new benchmark.Suite();
13
11
  class Attribute extends _1.Schema {
14
12
  }
15
13
  __decorate([
@@ -92,8 +90,11 @@ now = Date.now();
92
90
  // encoder.encodeAll();
93
91
  // }
94
92
  // console.log(Date.now() - now);
93
+ const total = 100;
95
94
  const allEncodes = Date.now();
96
- for (let i = 0; i < 100; i++) {
95
+ let avgTimeToEncode = 0;
96
+ let avgTimeToMakeChanges = 0;
97
+ for (let i = 0; i < total; i++) {
97
98
  now = Date.now();
98
99
  for (let j = 0; j < 50; j++) {
99
100
  const player = new Player();
@@ -112,12 +113,18 @@ for (let i = 0; i < 100; i++) {
112
113
  player.items.set(`item-${k}`, item);
113
114
  }
114
115
  }
115
- console.log("time to make changes:", Date.now() - now);
116
+ const timeToMakeChanges = Date.now() - now;
117
+ console.log("time to make changes:", timeToMakeChanges);
118
+ avgTimeToMakeChanges += timeToMakeChanges;
116
119
  now = Date.now();
117
120
  encoder.encode();
118
121
  encoder.discardChanges();
119
- console.log("time to encode:", Date.now() - now);
122
+ const timeToEncode = Date.now() - now;
123
+ console.log("time to encode:", timeToEncode);
124
+ avgTimeToEncode += timeToEncode;
120
125
  }
126
+ console.log("avg time to encode:", (avgTimeToEncode) / total);
127
+ console.log("avg time to make changes:", (avgTimeToMakeChanges) / total);
121
128
  console.log("time for all encodes:", Date.now() - allEncodes);
122
129
  console.log(Array.from(encoder.encodeAll()).length, "bytes");
123
130
  //# sourceMappingURL=bench_encode.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"bench_encode.js","sourceRoot":"","sources":["../src/bench_encode.ts"],"names":[],"mappings":"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","sourcesContent":["import { nanoid } from \"nanoid\";\nimport { Schema, type, MapSchema, ArraySchema, Encoder } from \".\";\nimport * as benchmark from \"benchmark\";\n\nconst suite = new benchmark.Suite();\n\nclass Attribute extends Schema {\n @type(\"string\") name: string;\n @type(\"number\") value: number;\n}\n\nclass Item extends Schema {\n @type(\"number\") price: number;\n @type([ Attribute ]) attributes = new ArraySchema<Attribute>();\n}\n\nclass Position extends Schema {\n @type(\"number\") x: number;\n @type(\"number\") y: number;\n}\n\nclass Player extends Schema {\n @type(Position) position = new Position();\n @type({ map: Item }) items = new MapSchema<Item>();\n}\n\nclass State extends Schema {\n @type({ map: Player }) players = new MapSchema<Player>();\n @type(\"string\") currentTurn;\n}\n\nconst state = new State();\n\nEncoder.BUFFER_SIZE = 4096 * 4096;\nconst encoder = new Encoder(state);\n\n\nlet now = Date.now();\n\n// for (let i = 0; i < 10000; i++) {\n// const player = new Player();\n// state.players.set(`p-${nanoid()}`, player);\n//\n// player.position.x = (i + 1) * 100;\n// player.position.y = (i + 1) * 100;\n// for (let j = 0; j < 10; j++) {\n// const item = new Item();\n// player.items.set(`item-${j}`, item);\n// item.price = (i + 1) * 50;\n// for (let k = 0; k < 5; k++) {\n// const attr = new Attribute();\n// attr.name = `Attribute ${k}`;\n// attr.value = k;\n// item.attributes.push(attr);\n// }\n// }\n// }\n// console.log(\"time to make changes:\", Date.now() - now);\n\n\n// measure time to .encodeAll()\n\nnow = Date.now();\n// for (let i = 0; i < 1000; i++) {\n// encoder.encodeAll();\n// }\n// console.log(Date.now() - now);\n\nconst allEncodes = Date.now();\nfor (let i = 0; i < 100; i++) {\n now = Date.now();\n for (let j = 0; j < 50; j++) {\n const player = new Player();\n state.players.set(`p-${nanoid()}`, player);\n\n player.position.x = (j + 1) * 100;\n player.position.y = (j + 1) * 100;\n for (let k = 0; k < 10; k++) {\n const item = new Item();\n item.price = (j + 1) * 50;\n for (let l = 0; l < 5; l++) {\n const attr = new Attribute();\n attr.name = `Attribute ${l}`;\n attr.value = l;\n item.attributes.push(attr);\n }\n player.items.set(`item-${k}`, item);\n }\n }\n console.log(\"time to make changes:\", Date.now() - now);\n\n now = Date.now();\n encoder.encode();\n encoder.discardChanges();\n console.log(\"time to encode:\", Date.now() - now);\n}\nconsole.log(\"time for all encodes:\", Date.now() - allEncodes);\n\nconsole.log(Array.from(encoder.encodeAll()).length, \"bytes\");\n"]}
1
+ {"version":3,"file":"bench_encode.js","sourceRoot":"","sources":["../src/bench_encode.ts"],"names":[],"mappings":"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","sourcesContent":["import { nanoid } from \"nanoid\";\nimport { Schema, type, MapSchema, ArraySchema, Encoder } from \".\";\n\nclass Attribute extends Schema {\n @type(\"string\") name: string;\n @type(\"number\") value: number;\n}\n\nclass Item extends Schema {\n @type(\"number\") price: number;\n @type([ Attribute ]) attributes = new ArraySchema<Attribute>();\n}\n\nclass Position extends Schema {\n @type(\"number\") x: number;\n @type(\"number\") y: number;\n}\n\nclass Player extends Schema {\n @type(Position) position = new Position();\n @type({ map: Item }) items = new MapSchema<Item>();\n}\n\nclass State extends Schema {\n @type({ map: Player }) players = new MapSchema<Player>();\n @type(\"string\") currentTurn;\n}\n\nconst state = new State();\n\nEncoder.BUFFER_SIZE = 4096 * 4096;\nconst encoder = new Encoder(state);\n\n\nlet now = Date.now();\n\n// for (let i = 0; i < 10000; i++) {\n// const player = new Player();\n// state.players.set(`p-${nanoid()}`, player);\n//\n// player.position.x = (i + 1) * 100;\n// player.position.y = (i + 1) * 100;\n// for (let j = 0; j < 10; j++) {\n// const item = new Item();\n// player.items.set(`item-${j}`, item);\n// item.price = (i + 1) * 50;\n// for (let k = 0; k < 5; k++) {\n// const attr = new Attribute();\n// attr.name = `Attribute ${k}`;\n// attr.value = k;\n// item.attributes.push(attr);\n// }\n// }\n// }\n// console.log(\"time to make changes:\", Date.now() - now);\n\n\n// measure time to .encodeAll()\n\nnow = Date.now();\n// for (let i = 0; i < 1000; i++) {\n// encoder.encodeAll();\n// }\n// console.log(Date.now() - now);\n\nconst total = 100;\nconst allEncodes = Date.now();\n\nlet avgTimeToEncode = 0;\nlet avgTimeToMakeChanges = 0;\n\nfor (let i = 0; i < total; i++) {\n now = Date.now();\n for (let j = 0; j < 50; j++) {\n const player = new Player();\n state.players.set(`p-${nanoid()}`, player);\n\n player.position.x = (j + 1) * 100;\n player.position.y = (j + 1) * 100;\n for (let k = 0; k < 10; k++) {\n const item = new Item();\n item.price = (j + 1) * 50;\n for (let l = 0; l < 5; l++) {\n const attr = new Attribute();\n attr.name = `Attribute ${l}`;\n attr.value = l;\n item.attributes.push(attr);\n }\n player.items.set(`item-${k}`, item);\n }\n }\n const timeToMakeChanges = Date.now() - now;\n console.log(\"time to make changes:\", timeToMakeChanges);\n avgTimeToMakeChanges += timeToMakeChanges;\n\n now = Date.now();\n encoder.encode();\n encoder.discardChanges();\n\n const timeToEncode = Date.now() - now;\n console.log(\"time to encode:\", timeToEncode);\n avgTimeToEncode += timeToEncode;\n}\nconsole.log(\"avg time to encode:\", (avgTimeToEncode) / total);\nconsole.log(\"avg time to make changes:\", (avgTimeToMakeChanges) / total);\nconsole.log(\"time for all encodes:\", Date.now() - allEncodes);\n\nconsole.log(Array.from(encoder.encodeAll()).length, \"bytes\");\n"]}
@@ -44,7 +44,7 @@ class Decoder {
44
44
  }
45
45
  ref[symbols_1.$onDecodeEnd]?.();
46
46
  ref = nextRef;
47
- decoder = ref['constructor'][symbols_1.$decoder];
47
+ decoder = ref.constructor[symbols_1.$decoder];
48
48
  continue;
49
49
  }
50
50
  const result = decoder(this, bytes, it, ref, allChanges);
@@ -1 +1 @@
1
- {"version":3,"file":"Decoder.js","sourceRoot":"","sources":["../../src/decoder/Decoder.ts"],"names":[],"mappings":"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","sourcesContent":["import { TypeContext } from \"../types/TypeContext\";\nimport { $changes, $childType, $decoder, $onDecodeEnd } from \"../types/symbols\";\nimport { Schema } from \"../Schema\";\n\nimport * as decode from \"../encoding/decode\";\nimport { OPERATION, SWITCH_TO_STRUCTURE, TYPE_ID } from '../encoding/spec';\nimport type { Ref } from \"../encoder/ChangeTree\";\nimport type { Iterator } from \"../encoding/decode\";\nimport { ReferenceTracker } from \"./ReferenceTracker\";\nimport { DEFINITION_MISMATCH, type DataChange, type DecodeOperation } from \"./DecodeOperation\";\nimport { Collection } from \"../types/HelperTypes\";\n\nexport class Decoder<T extends Schema = any> {\n context: TypeContext;\n\n state: T;\n root: ReferenceTracker;\n\n currentRefId: number = 0;\n\n triggerChanges?: (allChanges: DataChange[]) => void;\n\n constructor(root: T, context?: TypeContext) {\n this.setState(root);\n\n this.context = context || new TypeContext(root.constructor as typeof Schema);\n\n // console.log(\">>>>>>>>>>>>>>>> Decoder types\");\n // this.context.schemas.forEach((id, schema) => {\n // console.log(\"type:\", id, schema.name, Object.keys(schema[Symbol.metadata]));\n // });\n }\n\n protected setState(root: T) {\n this.state = root;\n this.root = new ReferenceTracker();\n this.root.addRef(0, root);\n }\n\n decode(\n bytes: Buffer,\n it: Iterator = { offset: 0 },\n ref: Ref = this.state,\n ) {\n const allChanges: DataChange[] = [];\n\n const $root = this.root;\n const totalBytes = bytes.byteLength;\n\n let decoder: DecodeOperation = ref['constructor'][$decoder];\n\n this.currentRefId = 0;\n\n while (it.offset < totalBytes) {\n //\n // Peek ahead, check if it's a switch to a different structure\n //\n if (bytes[it.offset] == SWITCH_TO_STRUCTURE) {\n it.offset++;\n\n this.currentRefId = decode.number(bytes, it);\n const nextRef = $root.refs.get(this.currentRefId) as Schema;\n\n //\n // Trying to access a reference that haven't been decoded yet.\n //\n if (!nextRef) { throw new Error(`\"refId\" not found: ${this.currentRefId}`); }\n ref[$onDecodeEnd]?.()\n ref = nextRef;\n\n decoder = ref['constructor'][$decoder];\n\n continue;\n }\n\n const result = decoder(this, bytes, it, ref, allChanges);\n\n if (result === DEFINITION_MISMATCH) {\n console.warn(\"@colyseus/schema: definition mismatch\");\n\n //\n // keep skipping next bytes until reaches a known structure\n // by local decoder.\n //\n const nextIterator: decode.Iterator = { offset: it.offset };\n while (it.offset < totalBytes) {\n if (decode.switchStructureCheck(bytes, it)) {\n nextIterator.offset = it.offset + 1;\n if ($root.refs.has(decode.number(bytes, nextIterator))) {\n break;\n }\n }\n\n it.offset++;\n }\n continue;\n }\n }\n\n // FIXME: DRY with SWITCH_TO_STRUCTURE block.\n ref[$onDecodeEnd]?.()\n\n // trigger changes\n this.triggerChanges?.(allChanges);\n\n // drop references of unused schemas\n $root.garbageCollectDeletedRefs();\n\n return allChanges;\n }\n\n getInstanceType(bytes: Buffer, it: Iterator, defaultType: typeof Schema): typeof Schema {\n let type: typeof Schema;\n\n if (bytes[it.offset] === TYPE_ID) {\n it.offset++;\n const type_id = decode.number(bytes, it);\n type = this.context.get(type_id);\n }\n\n return type || defaultType;\n }\n\n createInstanceOfType (type: typeof Schema): Schema {\n // let instance: Schema = new (type as any)();\n\n // // assign root on $changes\n // instance[$changes].root = this.root[$changes].root;\n\n // return instance;\n return new (type as any)();\n }\n\n removeChildRefs(ref: Collection, allChanges: DataChange[]) {\n const changeTree = ref[$changes];\n\n const needRemoveRef = typeof (ref[$childType]) !== \"string\";\n const refId = changeTree.refId;\n\n ref.forEach((value: any, key: any) => {\n allChanges.push({\n ref: value,\n refId,\n op: OPERATION.DELETE,\n field: key,\n value: undefined,\n previousValue: value\n });\n\n if (needRemoveRef) {\n this.root.removeRef(this.root.refIds.get(value));\n }\n });\n }\n\n}\n\n"]}
1
+ {"version":3,"file":"Decoder.js","sourceRoot":"","sources":["../../src/decoder/Decoder.ts"],"names":[],"mappings":"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","sourcesContent":["import { TypeContext } from \"../types/TypeContext\";\nimport { $changes, $childType, $decoder, $onDecodeEnd } from \"../types/symbols\";\nimport { Schema } from \"../Schema\";\n\nimport * as decode from \"../encoding/decode\";\nimport { OPERATION, SWITCH_TO_STRUCTURE, TYPE_ID } from '../encoding/spec';\nimport type { Ref } from \"../encoder/ChangeTree\";\nimport type { Iterator } from \"../encoding/decode\";\nimport { ReferenceTracker } from \"./ReferenceTracker\";\nimport { DEFINITION_MISMATCH, type DataChange, type DecodeOperation } from \"./DecodeOperation\";\nimport { Collection } from \"../types/HelperTypes\";\n\nexport class Decoder<T extends Schema = any> {\n context: TypeContext;\n\n state: T;\n root: ReferenceTracker;\n\n currentRefId: number = 0;\n\n triggerChanges?: (allChanges: DataChange[]) => void;\n\n constructor(root: T, context?: TypeContext) {\n this.setState(root);\n\n this.context = context || new TypeContext(root.constructor as typeof Schema);\n\n // console.log(\">>>>>>>>>>>>>>>> Decoder types\");\n // this.context.schemas.forEach((id, schema) => {\n // console.log(\"type:\", id, schema.name, Object.keys(schema[Symbol.metadata]));\n // });\n }\n\n protected setState(root: T) {\n this.state = root;\n this.root = new ReferenceTracker();\n this.root.addRef(0, root);\n }\n\n decode(\n bytes: Buffer,\n it: Iterator = { offset: 0 },\n ref: Ref = this.state,\n ) {\n const allChanges: DataChange[] = [];\n\n const $root = this.root;\n const totalBytes = bytes.byteLength;\n\n let decoder: DecodeOperation = ref['constructor'][$decoder];\n\n this.currentRefId = 0;\n\n while (it.offset < totalBytes) {\n //\n // Peek ahead, check if it's a switch to a different structure\n //\n if (bytes[it.offset] == SWITCH_TO_STRUCTURE) {\n it.offset++;\n\n this.currentRefId = decode.number(bytes, it);\n const nextRef = $root.refs.get(this.currentRefId) as Schema;\n\n //\n // Trying to access a reference that haven't been decoded yet.\n //\n if (!nextRef) { throw new Error(`\"refId\" not found: ${this.currentRefId}`); }\n ref[$onDecodeEnd]?.()\n ref = nextRef;\n\n decoder = ref.constructor[$decoder];\n\n continue;\n }\n\n const result = decoder(this, bytes, it, ref, allChanges);\n\n if (result === DEFINITION_MISMATCH) {\n console.warn(\"@colyseus/schema: definition mismatch\");\n\n //\n // keep skipping next bytes until reaches a known structure\n // by local decoder.\n //\n const nextIterator: decode.Iterator = { offset: it.offset };\n while (it.offset < totalBytes) {\n if (decode.switchStructureCheck(bytes, it)) {\n nextIterator.offset = it.offset + 1;\n if ($root.refs.has(decode.number(bytes, nextIterator))) {\n break;\n }\n }\n\n it.offset++;\n }\n continue;\n }\n }\n\n // FIXME: DRY with SWITCH_TO_STRUCTURE block.\n ref[$onDecodeEnd]?.()\n\n // trigger changes\n this.triggerChanges?.(allChanges);\n\n // drop references of unused schemas\n $root.garbageCollectDeletedRefs();\n\n return allChanges;\n }\n\n getInstanceType(bytes: Buffer, it: Iterator, defaultType: typeof Schema): typeof Schema {\n let type: typeof Schema;\n\n if (bytes[it.offset] === TYPE_ID) {\n it.offset++;\n const type_id = decode.number(bytes, it);\n type = this.context.get(type_id);\n }\n\n return type || defaultType;\n }\n\n createInstanceOfType (type: typeof Schema): Schema {\n // let instance: Schema = new (type as any)();\n\n // // assign root on $changes\n // instance[$changes].root = this.root[$changes].root;\n\n // return instance;\n return new (type as any)();\n }\n\n removeChildRefs(ref: Collection, allChanges: DataChange[]) {\n const changeTree = ref[$changes];\n\n const needRemoveRef = typeof (ref[$childType]) !== \"string\";\n const refId = changeTree.refId;\n\n ref.forEach((value: any, key: any) => {\n allChanges.push({\n ref: value,\n refId,\n op: OPERATION.DELETE,\n field: key,\n value: undefined,\n previousValue: value\n });\n\n if (needRemoveRef) {\n this.root.removeRef(this.root.refIds.get(value));\n }\n });\n }\n\n}\n\n"]}
@@ -1,6 +1,6 @@
1
1
  import { OPERATION } from "../encoding/spec";
2
2
  import { Schema } from "../Schema";
3
- import { $changes, $decoder, $encoder, $isNew } from "../types/symbols";
3
+ import { $changes, $decoder, $encoder } from "../types/symbols";
4
4
  import type { MapSchema } from "../types/custom/MapSchema";
5
5
  import type { ArraySchema } from "../types/custom/ArraySchema";
6
6
  import type { CollectionSchema } from "../types/custom/CollectionSchema";
@@ -17,6 +17,19 @@ declare global {
17
17
  }
18
18
  }
19
19
  export type Ref = Schema | ArraySchema | MapSchema | CollectionSchema | SetSchema;
20
+ export type ChangeSetName = "changes" | "allChanges" | "filteredChanges" | "allFilteredChanges";
21
+ export interface IndexedOperations {
22
+ [index: number]: OPERATION;
23
+ }
24
+ export interface ChangeSet {
25
+ indexes: {
26
+ [index: number]: number;
27
+ };
28
+ operations: OPERATION[];
29
+ queueRootIndex?: number;
30
+ }
31
+ export declare function setOperationAtIndex(changeSet: ChangeSet, index: number): void;
32
+ export declare function deleteOperationAtIndex(changeSet: ChangeSet, index: number): void;
20
33
  export declare class ChangeTree<T extends Ref = any> {
21
34
  ref: T;
22
35
  refId: number;
@@ -25,15 +38,18 @@ export declare class ChangeTree<T extends Ref = any> {
25
38
  parentIndex?: number;
26
39
  isFiltered: boolean;
27
40
  isPartiallyFiltered: boolean;
28
- currentOperationIndex: number;
29
- changes: Map<number, OPERATION>;
30
- allChanges: Map<number, OPERATION>;
31
- allFilteredChanges: Map<number, OPERATION>;
32
- filteredChanges: Map<number, OPERATION>;
41
+ indexedOperations: IndexedOperations;
42
+ changes: ChangeSet;
43
+ allChanges: ChangeSet;
44
+ filteredChanges: ChangeSet;
45
+ allFilteredChanges: ChangeSet;
33
46
  indexes: {
34
47
  [index: string]: any;
35
48
  };
36
- [$isNew]: boolean;
49
+ /**
50
+ * Is this a new instance? Used on ArraySchema to determine OPERATION.MOVE_AND_ADD operation.
51
+ */
52
+ isNew: boolean;
37
53
  constructor(ref: T);
38
54
  setRoot(root: Root): void;
39
55
  setParent(parent: Ref, root?: Root, parentIndex?: number): void;
@@ -1,31 +1,62 @@
1
1
  "use strict";
2
- var _a;
3
2
  Object.defineProperty(exports, "__esModule", { value: true });
4
3
  exports.ChangeTree = void 0;
4
+ exports.setOperationAtIndex = setOperationAtIndex;
5
+ exports.deleteOperationAtIndex = deleteOperationAtIndex;
5
6
  const spec_1 = require("../encoding/spec");
6
7
  const symbols_1 = require("../types/symbols");
7
8
  const Metadata_1 = require("../Metadata");
9
+ function setOperationAtIndex(changeSet, index) {
10
+ const operationsIndex = changeSet.indexes[index];
11
+ if (operationsIndex === undefined) {
12
+ changeSet.indexes[index] = changeSet.operations.push(index) - 1;
13
+ }
14
+ else {
15
+ changeSet.operations[operationsIndex] = index;
16
+ }
17
+ }
18
+ function deleteOperationAtIndex(changeSet, index) {
19
+ const operationsIndex = changeSet.indexes[index];
20
+ if (operationsIndex !== undefined) {
21
+ changeSet.operations[operationsIndex] = undefined;
22
+ }
23
+ delete changeSet.indexes[index];
24
+ }
25
+ function enqueueChangeTree(root, changeTree, changeSet, queueRootIndex = changeTree[changeSet].queueRootIndex) {
26
+ if (root && root[changeSet][queueRootIndex] !== changeTree) {
27
+ changeTree[changeSet].queueRootIndex = root[changeSet].push(changeTree) - 1;
28
+ }
29
+ }
8
30
  class ChangeTree {
9
- static { _a = symbols_1.$isNew; }
10
31
  constructor(ref) {
11
32
  this.isFiltered = false;
12
33
  this.isPartiallyFiltered = false;
13
- this.currentOperationIndex = 0;
14
- this.changes = new Map();
15
- this.allChanges = new Map();
16
- this[_a] = true;
34
+ this.indexedOperations = {};
35
+ //
36
+ // TODO:
37
+ // try storing the index + operation per item.
38
+ // example: 1024 & 1025 => ADD, 1026 => DELETE
39
+ //
40
+ // => https://chatgpt.com/share/67107d0c-bc20-8004-8583-83b17dd7c196
41
+ //
42
+ this.changes = { indexes: {}, operations: [] };
43
+ this.allChanges = { indexes: {}, operations: [] };
44
+ /**
45
+ * Is this a new instance? Used on ArraySchema to determine OPERATION.MOVE_AND_ADD operation.
46
+ */
47
+ this.isNew = true;
17
48
  this.ref = ref;
18
49
  //
19
50
  // Does this structure have "filters" declared?
20
51
  //
21
- if (ref.constructor[Symbol.metadata]?.[-2]) {
22
- this.allFilteredChanges = new Map();
23
- this.filteredChanges = new Map();
52
+ if (ref.constructor[Symbol.metadata]?.[symbols_1.$viewFieldIndexes]) {
53
+ this.allFilteredChanges = { indexes: {}, operations: [] };
54
+ this.filteredChanges = { indexes: {}, operations: [] };
24
55
  }
25
56
  }
26
57
  setRoot(root) {
27
58
  this.root = root;
28
- this.root.add(this);
59
+ const isNewChangeTree = this.root.add(this);
29
60
  const metadata = this.ref.constructor[Symbol.metadata];
30
61
  if (this.root.types.hasFilters) {
31
62
  //
@@ -36,22 +67,24 @@ class ChangeTree {
36
67
  //
37
68
  this.checkIsFiltered(metadata, this.parent, this.parentIndex);
38
69
  if (this.isFiltered || this.isPartiallyFiltered) {
39
- this.root.allFilteredChanges.set(this, this.allFilteredChanges);
40
- this.root.filteredChanges.set(this, this.filteredChanges);
70
+ enqueueChangeTree(root, this, 'filteredChanges');
71
+ if (isNewChangeTree) {
72
+ this.root.allFilteredChanges.push(this);
73
+ }
41
74
  }
42
75
  }
43
76
  if (!this.isFiltered) {
44
- this.root.changes.set(this, this.changes);
45
- this.root.allChanges.set(this, this.allChanges);
77
+ enqueueChangeTree(root, this, 'changes');
78
+ if (isNewChangeTree) {
79
+ this.root.allChanges.push(this);
80
+ }
46
81
  }
47
- this.ensureRefId();
82
+ // Recursively set root on child structures
48
83
  if (metadata) {
49
- metadata[-4]?.forEach((index) => {
84
+ metadata[symbols_1.$refTypeFieldIndexes]?.forEach((index) => {
50
85
  const field = metadata[index];
51
86
  const value = this.ref[field.name];
52
- if (value) {
53
- value[symbols_1.$changes].setRoot(root);
54
- }
87
+ value?.[symbols_1.$changes].setRoot(root);
55
88
  });
56
89
  }
57
90
  else if (this.ref[symbols_1.$childType] && typeof (this.ref[symbols_1.$childType]) !== "string") {
@@ -68,31 +101,36 @@ class ChangeTree {
68
101
  if (!root) {
69
102
  return;
70
103
  }
71
- root.add(this);
72
104
  const metadata = this.ref.constructor[Symbol.metadata];
73
105
  // skip if parent is already set
74
106
  if (root !== this.root) {
75
107
  this.root = root;
108
+ const isNewChangeTree = root.add(this);
76
109
  if (root.types.hasFilters) {
77
110
  this.checkIsFiltered(metadata, parent, parentIndex);
78
111
  if (this.isFiltered || this.isPartiallyFiltered) {
79
- this.root.filteredChanges.set(this, this.filteredChanges);
80
- this.root.allFilteredChanges.set(this, this.filteredChanges);
112
+ enqueueChangeTree(root, this, 'filteredChanges');
113
+ if (isNewChangeTree) {
114
+ this.root.allFilteredChanges.push(this);
115
+ }
81
116
  }
82
117
  }
83
118
  if (!this.isFiltered) {
84
- this.root.changes.set(this, this.changes);
85
- this.root.allChanges.set(this, this.allChanges);
119
+ enqueueChangeTree(root, this, 'changes');
120
+ if (isNewChangeTree) {
121
+ this.root.allChanges.push(this);
122
+ }
86
123
  }
87
- this.ensureRefId();
124
+ }
125
+ else {
126
+ root.add(this);
88
127
  }
89
128
  // assign same parent on child structures
90
129
  if (metadata) {
91
- metadata[-4]?.forEach((index) => {
130
+ metadata[symbols_1.$refTypeFieldIndexes]?.forEach((index) => {
92
131
  const field = metadata[index];
93
132
  const value = this.ref[field.name];
94
133
  value?.[symbols_1.$changes].setParent(this.ref, root, index);
95
- // console.log(this.ref.constructor.name, field.name, value);
96
134
  // try { throw new Error(); } catch (e) {
97
135
  // console.log(e.stack);
98
136
  // }
@@ -111,7 +149,7 @@ class ChangeTree {
111
149
  //
112
150
  const metadata = this.ref.constructor[Symbol.metadata];
113
151
  if (metadata) {
114
- metadata[-4]?.forEach((index) => {
152
+ metadata[symbols_1.$refTypeFieldIndexes]?.forEach((index) => {
115
153
  const field = metadata[index];
116
154
  const value = this.ref[field.name];
117
155
  if (value) {
@@ -127,8 +165,10 @@ class ChangeTree {
127
165
  }
128
166
  }
129
167
  operation(op) {
130
- this.changes.set(--this.currentOperationIndex, op);
131
- this.root?.changes.set(this, this.changes);
168
+ // operations without index use negative values to represent them
169
+ // this is checked during .encode() time.
170
+ this.changes.operations.push(-op);
171
+ enqueueChangeTree(this.root, this, 'changes');
132
172
  }
133
173
  change(index, operation = spec_1.OPERATION.ADD) {
134
174
  const metadata = this.ref.constructor[Symbol.metadata];
@@ -136,7 +176,7 @@ class ChangeTree {
136
176
  const changeSet = (isFiltered)
137
177
  ? this.filteredChanges
138
178
  : this.changes;
139
- const previousOperation = changeSet.get(index);
179
+ const previousOperation = this.indexedOperations[index];
140
180
  if (!previousOperation || previousOperation === spec_1.OPERATION.DELETE) {
141
181
  const op = (!previousOperation)
142
182
  ? operation
@@ -146,16 +186,19 @@ class ChangeTree {
146
186
  //
147
187
  // TODO: are DELETE operations being encoded as ADD here ??
148
188
  //
149
- changeSet.set(index, op);
189
+ this.indexedOperations[index] = op;
150
190
  }
191
+ setOperationAtIndex(changeSet, index);
151
192
  if (isFiltered) {
152
- this.allFilteredChanges.set(index, spec_1.OPERATION.ADD);
153
- this.root?.filteredChanges.set(this, this.filteredChanges);
154
- this.root?.allFilteredChanges.set(this, this.allFilteredChanges);
193
+ setOperationAtIndex(this.allFilteredChanges, index);
194
+ if (this.root) {
195
+ enqueueChangeTree(this.root, this, 'filteredChanges');
196
+ enqueueChangeTree(this.root, this, 'allFilteredChanges');
197
+ }
155
198
  }
156
199
  else {
157
- this.allChanges.set(index, spec_1.OPERATION.ADD);
158
- this.root?.changes.set(this, this.changes);
200
+ setOperationAtIndex(this.allChanges, index);
201
+ enqueueChangeTree(this.root, this, 'changes');
159
202
  }
160
203
  }
161
204
  shiftChangeIndexes(shiftIndex) {
@@ -167,12 +210,15 @@ class ChangeTree {
167
210
  const changeSet = (this.isFiltered)
168
211
  ? this.filteredChanges
169
212
  : this.changes;
170
- const changeSetEntries = Array.from(changeSet.entries());
171
- changeSet.clear();
172
- // Re-insert each entry with the shifted index
173
- for (const [index, op] of changeSetEntries) {
174
- changeSet.set(index + shiftIndex, op);
213
+ const newIndexedOperations = {};
214
+ const newIndexes = {};
215
+ for (const index in this.indexedOperations) {
216
+ newIndexedOperations[Number(index) + shiftIndex] = this.indexedOperations[index];
217
+ newIndexes[Number(index) + shiftIndex] = changeSet[index];
175
218
  }
219
+ this.indexedOperations = newIndexedOperations;
220
+ changeSet.indexes = newIndexes;
221
+ changeSet.operations = changeSet.operations.map((index) => index + shiftIndex);
176
222
  }
177
223
  shiftAllChangeIndexes(shiftIndex, startIndex = 0) {
178
224
  //
@@ -188,24 +234,36 @@ class ChangeTree {
188
234
  this._shiftAllChangeIndexes(shiftIndex, startIndex, this.allChanges);
189
235
  }
190
236
  }
191
- _shiftAllChangeIndexes(shiftIndex, startIndex = 0, allChangeSet) {
192
- Array.from(allChangeSet.entries()).forEach(([index, op]) => {
193
- if (index >= startIndex) {
194
- allChangeSet.delete(index);
195
- allChangeSet.set(index + shiftIndex, op);
237
+ _shiftAllChangeIndexes(shiftIndex, startIndex = 0, changeSet) {
238
+ const newIndexes = {};
239
+ for (const key in changeSet.indexes) {
240
+ const index = changeSet.indexes[key];
241
+ if (index > startIndex) {
242
+ newIndexes[Number(key) + shiftIndex] = index;
243
+ }
244
+ else {
245
+ newIndexes[key] = index;
246
+ }
247
+ }
248
+ changeSet.indexes = newIndexes;
249
+ for (let i = 0; i < changeSet.operations.length; i++) {
250
+ const index = changeSet.operations[i];
251
+ if (index > startIndex) {
252
+ changeSet.operations[i] = index + shiftIndex;
196
253
  }
197
- });
254
+ }
198
255
  }
199
256
  indexedOperation(index, operation, allChangesIndex = index) {
200
- if (this.filteredChanges !== undefined) {
201
- this.allFilteredChanges.set(allChangesIndex, spec_1.OPERATION.ADD);
202
- this.filteredChanges.set(index, operation);
203
- this.root?.filteredChanges.set(this, this.filteredChanges);
257
+ this.indexedOperations[index] = operation;
258
+ if (this.filteredChanges) {
259
+ setOperationAtIndex(this.allFilteredChanges, allChangesIndex);
260
+ setOperationAtIndex(this.filteredChanges, index);
261
+ enqueueChangeTree(this.root, this, 'filteredChanges');
204
262
  }
205
263
  else {
206
- this.allChanges.set(allChangesIndex, spec_1.OPERATION.ADD);
207
- this.changes.set(index, operation);
208
- this.root?.changes.set(this, this.changes);
264
+ setOperationAtIndex(this.allChanges, allChangesIndex);
265
+ setOperationAtIndex(this.changes, index);
266
+ enqueueChangeTree(this.root, this, 'changes');
209
267
  }
210
268
  }
211
269
  getType(index) {
@@ -224,8 +282,7 @@ class ChangeTree {
224
282
  }
225
283
  }
226
284
  getChange(index) {
227
- // TODO: optimize this. avoid checking against multiple instances
228
- return this.changes.get(index) ?? this.filteredChanges?.get(index);
285
+ return this.indexedOperations[index];
229
286
  }
230
287
  //
231
288
  // used during `.encode()`
@@ -249,8 +306,9 @@ class ChangeTree {
249
306
  const changeSet = (this.filteredChanges)
250
307
  ? this.filteredChanges
251
308
  : this.changes;
309
+ this.indexedOperations[index] = operation ?? spec_1.OPERATION.DELETE;
310
+ setOperationAtIndex(changeSet, index);
252
311
  const previousValue = this.getValue(index);
253
- changeSet.set(index, operation ?? spec_1.OPERATION.DELETE);
254
312
  // remove `root` reference
255
313
  if (previousValue && previousValue[symbols_1.$changes]) {
256
314
  //
@@ -266,23 +324,26 @@ class ChangeTree {
266
324
  this.root?.remove(previousValue[symbols_1.$changes]);
267
325
  }
268
326
  //
269
- // FIXME: this is looking a bit ugly (and repeated from `.change()`)
327
+ // FIXME: this is looking a ugly and repeated
270
328
  //
271
329
  if (this.filteredChanges) {
272
- this.root?.filteredChanges.set(this, this.filteredChanges);
273
- this.allFilteredChanges.delete(allChangesIndex);
330
+ deleteOperationAtIndex(this.allFilteredChanges, allChangesIndex);
331
+ enqueueChangeTree(this.root, this, 'filteredChanges');
274
332
  }
275
333
  else {
276
- this.root?.changes.set(this, this.changes);
277
- this.allChanges.delete(allChangesIndex);
334
+ deleteOperationAtIndex(this.allChanges, allChangesIndex);
335
+ enqueueChangeTree(this.root, this, 'changes');
278
336
  }
279
337
  }
280
338
  endEncode() {
281
- this.changes.clear();
339
+ this.indexedOperations = {};
340
+ // // clear changes
341
+ // this.changes.indexes = {};
342
+ // this.changes.operations.length = 0;
282
343
  // ArraySchema and MapSchema have a custom "encode end" method
283
344
  this.ref[symbols_1.$onEncodeEnd]?.();
284
345
  // Not a new instance anymore
285
- delete this[symbols_1.$isNew];
346
+ this.isNew = false;
286
347
  }
287
348
  discard(discardAll = false) {
288
349
  //
@@ -291,13 +352,22 @@ class ChangeTree {
291
352
  // REPLACE in case same key is used on next patches.
292
353
  //
293
354
  this.ref[symbols_1.$onEncodeEnd]?.();
294
- this.changes.clear();
295
- this.filteredChanges?.clear();
296
- // reset operation index
297
- this.currentOperationIndex = 0;
355
+ this.indexedOperations = {};
356
+ this.changes.indexes = {};
357
+ this.changes.operations.length = 0;
358
+ this.changes.queueRootIndex = undefined;
359
+ if (this.filteredChanges !== undefined) {
360
+ this.filteredChanges.indexes = {};
361
+ this.filteredChanges.operations.length = 0;
362
+ this.filteredChanges.queueRootIndex = undefined;
363
+ }
298
364
  if (discardAll) {
299
- this.allChanges.clear();
300
- this.allFilteredChanges?.clear();
365
+ this.allChanges.indexes = {};
366
+ this.allChanges.operations.length = 0;
367
+ if (this.allFilteredChanges !== undefined) {
368
+ this.allFilteredChanges.indexes = {};
369
+ this.allFilteredChanges.operations.length = 0;
370
+ }
301
371
  // remove children references
302
372
  this.forEachChild((changeTree, _) => this.root?.remove(changeTree));
303
373
  }
@@ -306,12 +376,13 @@ class ChangeTree {
306
376
  * Recursively discard all changes from this, and child structures.
307
377
  */
308
378
  discardAll() {
309
- this.changes.forEach((_, fieldIndex) => {
310
- const value = this.getValue(fieldIndex);
379
+ const keys = Object.keys(this.indexedOperations);
380
+ for (let i = 0, len = keys.length; i < len; i++) {
381
+ const value = this.getValue(Number(keys[i]));
311
382
  if (value && value[symbols_1.$changes]) {
312
383
  value[symbols_1.$changes].discardAll();
313
384
  }
314
- });
385
+ }
315
386
  this.discard();
316
387
  }
317
388
  ensureRefId() {
@@ -322,42 +393,48 @@ class ChangeTree {
322
393
  this.refId = this.root.getNextUniqueId();
323
394
  }
324
395
  get changed() {
325
- return this.changes.size > 0;
396
+ return (Object.entries(this.indexedOperations).length > 0);
326
397
  }
327
398
  checkIsFiltered(metadata, parent, parentIndex) {
328
399
  // Detect if current structure has "filters" declared
329
- this.isPartiallyFiltered = metadata?.[-2] !== undefined;
400
+ this.isPartiallyFiltered = metadata?.[symbols_1.$viewFieldIndexes] !== undefined;
330
401
  if (this.isPartiallyFiltered) {
331
- this.filteredChanges = this.filteredChanges || new Map();
332
- this.allFilteredChanges = this.allFilteredChanges || new Map();
333
- }
334
- if (parent) {
335
- if (!Metadata_1.Metadata.isValidInstance(parent)) {
336
- const parentChangeTree = parent[symbols_1.$changes];
337
- parent = parentChangeTree.parent;
338
- parentIndex = parentChangeTree.parentIndex;
339
- }
340
- const parentMetadata = parent?.constructor?.[Symbol.metadata];
341
- this.isFiltered = (parent && parentMetadata?.[-2]?.includes(parentIndex));
342
- //
343
- // TODO: refactor this!
344
- //
345
- // swapping `changes` and `filteredChanges` is required here
346
- // because "isFiltered" may not be imedialely available on `change()`
347
- //
348
- if (this.isFiltered) {
349
- this.filteredChanges = new Map();
350
- this.allFilteredChanges = new Map();
351
- if (this.changes.size > 0) {
352
- // swap changes reference
353
- const changes = this.changes;
354
- this.changes = this.filteredChanges;
355
- this.filteredChanges = changes;
356
- // swap "all changes" reference
357
- const allFilteredChanges = this.allFilteredChanges;
358
- this.allFilteredChanges = this.allChanges;
359
- this.allChanges = allFilteredChanges;
360
- }
402
+ this.filteredChanges = this.filteredChanges || { indexes: {}, operations: [] };
403
+ this.allFilteredChanges = this.allFilteredChanges || { indexes: {}, operations: [] };
404
+ }
405
+ // skip if parent is not set
406
+ if (!parent) {
407
+ return;
408
+ }
409
+ if (!Metadata_1.Metadata.isValidInstance(parent)) {
410
+ const parentChangeTree = parent[symbols_1.$changes];
411
+ parent = parentChangeTree.parent;
412
+ parentIndex = parentChangeTree.parentIndex;
413
+ }
414
+ const parentMetadata = parent.constructor?.[Symbol.metadata];
415
+ this.isFiltered = parentMetadata?.[symbols_1.$viewFieldIndexes]?.includes(parentIndex);
416
+ //
417
+ // TODO: refactor this!
418
+ //
419
+ // swapping `changes` and `filteredChanges` is required here
420
+ // because "isFiltered" may not be imedialely available on `change()`
421
+ //
422
+ if (this.isFiltered) {
423
+ this.filteredChanges = { indexes: {}, operations: [] };
424
+ this.allFilteredChanges = { indexes: {}, operations: [] };
425
+ if (this.changes.operations.length > 0) {
426
+ // swap changes reference
427
+ const changes = this.changes;
428
+ this.changes = this.filteredChanges;
429
+ this.filteredChanges = changes;
430
+ // swap "all changes" reference
431
+ const allFilteredChanges = this.allFilteredChanges;
432
+ this.allFilteredChanges = this.allChanges;
433
+ this.allChanges = allFilteredChanges;
434
+ // console.log("SWAP =>", {
435
+ // "this.allFilteredChanges": this.allFilteredChanges,
436
+ // "this.allChanges": this.allChanges
437
+ // })
361
438
  }
362
439
  }
363
440
  }