@colyseus/schema 3.0.75 → 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 (157) hide show
  1. package/build/cjs/index.js +780 -429
  2. package/build/cjs/index.js.map +1 -1
  3. package/build/esm/index.mjs +778 -430
  4. package/build/esm/index.mjs.map +1 -1
  5. package/build/umd/index.js +780 -429
  6. package/lib/Reflection.d.ts +50 -17
  7. package/lib/Reflection.js +151 -202
  8. package/lib/Reflection.js.map +1 -1
  9. package/lib/Schema.d.ts +13 -1
  10. package/lib/Schema.js +73 -9
  11. package/lib/Schema.js.map +1 -1
  12. package/lib/annotations.d.ts +6 -1
  13. package/lib/annotations.js +8 -34
  14. package/lib/annotations.js.map +1 -1
  15. package/lib/bench_encode.js +34 -1
  16. package/lib/bench_encode.js.map +1 -1
  17. package/lib/codegen/api.js +35 -2
  18. package/lib/codegen/api.js.map +1 -1
  19. package/lib/codegen/cli.js +4 -1
  20. package/lib/codegen/cli.js.map +1 -1
  21. package/lib/codegen/parser.js +35 -2
  22. package/lib/codegen/parser.js.map +1 -1
  23. package/lib/codegen/types.js +34 -1
  24. package/lib/codegen/types.js.map +1 -1
  25. package/lib/decoder/DecodeOperation.d.ts +2 -2
  26. package/lib/decoder/DecodeOperation.js +3 -3
  27. package/lib/decoder/DecodeOperation.js.map +1 -1
  28. package/lib/decoder/Decoder.d.ts +3 -3
  29. package/lib/decoder/Decoder.js +2 -2
  30. package/lib/decoder/Decoder.js.map +1 -1
  31. package/lib/decoder/ReferenceTracker.d.ts +0 -1
  32. package/lib/decoder/ReferenceTracker.js +9 -7
  33. package/lib/decoder/ReferenceTracker.js.map +1 -1
  34. package/lib/decoder/strategy/Callbacks.d.ts +154 -0
  35. package/lib/decoder/strategy/Callbacks.js +340 -0
  36. package/lib/decoder/strategy/Callbacks.js.map +1 -0
  37. package/lib/decoder/strategy/{StateCallbacks.d.ts → getDecoderStateCallbacks.d.ts} +6 -0
  38. package/lib/decoder/strategy/{StateCallbacks.js → getDecoderStateCallbacks.js} +17 -10
  39. package/lib/decoder/strategy/getDecoderStateCallbacks.js.map +1 -0
  40. package/lib/encoder/ChangeTree.d.ts +2 -2
  41. package/lib/encoder/ChangeTree.js.map +1 -1
  42. package/lib/encoder/EncodeOperation.d.ts +2 -2
  43. package/lib/encoder/EncodeOperation.js +3 -3
  44. package/lib/encoder/EncodeOperation.js.map +1 -1
  45. package/lib/encoder/Encoder.d.ts +6 -6
  46. package/lib/encoder/Encoder.js +19 -18
  47. package/lib/encoder/Encoder.js.map +1 -1
  48. package/lib/encoder/Root.js +17 -14
  49. package/lib/encoder/Root.js.map +1 -1
  50. package/lib/encoder/StateView.js +13 -12
  51. package/lib/encoder/StateView.js.map +1 -1
  52. package/lib/encoding/decode.d.ts +2 -2
  53. package/lib/encoding/encode.d.ts +3 -1
  54. package/lib/encoding/encode.js.map +1 -1
  55. package/lib/index.d.ts +3 -2
  56. package/lib/index.js +7 -3
  57. package/lib/index.js.map +1 -1
  58. package/lib/types/HelperTypes.d.ts +7 -14
  59. package/lib/types/HelperTypes.js.map +1 -1
  60. package/lib/types/custom/ArraySchema.d.ts +2 -1
  61. package/lib/types/custom/ArraySchema.js.map +1 -1
  62. package/lib/types/custom/CollectionSchema.d.ts +2 -1
  63. package/lib/types/custom/CollectionSchema.js.map +1 -1
  64. package/lib/types/custom/MapSchema.d.ts +3 -2
  65. package/lib/types/custom/MapSchema.js.map +1 -1
  66. package/lib/types/custom/SetSchema.d.ts +2 -1
  67. package/lib/types/custom/SetSchema.js.map +1 -1
  68. package/lib/types/symbols.d.ts +1 -0
  69. package/lib/types/symbols.js +2 -1
  70. package/lib/types/symbols.js.map +1 -1
  71. package/lib/utils.js +1 -1
  72. package/lib/utils.js.map +1 -1
  73. package/package.json +12 -16
  74. package/src/Reflection.ts +185 -174
  75. package/src/Schema.ts +81 -13
  76. package/src/annotations.ts +14 -40
  77. package/src/codegen/parser.ts +1 -1
  78. package/src/decoder/DecodeOperation.ts +9 -9
  79. package/src/decoder/Decoder.ts +6 -6
  80. package/src/decoder/ReferenceTracker.ts +10 -8
  81. package/src/decoder/strategy/Callbacks.ts +547 -0
  82. package/src/decoder/strategy/{StateCallbacks.ts → getDecoderStateCallbacks.ts} +17 -11
  83. package/src/encoder/ChangeTree.ts +4 -7
  84. package/src/encoder/EncodeOperation.ts +9 -9
  85. package/src/encoder/Encoder.ts +26 -18
  86. package/src/encoder/Root.ts +20 -15
  87. package/src/encoder/StateView.ts +15 -13
  88. package/src/encoding/encode.ts +1 -1
  89. package/src/index.ts +3 -2
  90. package/src/types/HelperTypes.ts +13 -11
  91. package/src/types/custom/ArraySchema.ts +2 -1
  92. package/src/types/custom/CollectionSchema.ts +4 -2
  93. package/src/types/custom/MapSchema.ts +4 -2
  94. package/src/types/custom/SetSchema.ts +3 -1
  95. package/src/types/symbols.ts +1 -0
  96. package/src/utils.ts +2 -2
  97. package/lib/Decoder.d.ts +0 -16
  98. package/lib/Decoder.js +0 -182
  99. package/lib/Decoder.js.map +0 -1
  100. package/lib/Encoder.d.ts +0 -13
  101. package/lib/Encoder.js +0 -79
  102. package/lib/Encoder.js.map +0 -1
  103. package/lib/changes/ChangeSet.d.ts +0 -12
  104. package/lib/changes/ChangeSet.js +0 -35
  105. package/lib/changes/ChangeSet.js.map +0 -1
  106. package/lib/changes/ChangeTree.d.ts +0 -53
  107. package/lib/changes/ChangeTree.js +0 -202
  108. package/lib/changes/ChangeTree.js.map +0 -1
  109. package/lib/changes/DecodeOperation.d.ts +0 -15
  110. package/lib/changes/DecodeOperation.js +0 -186
  111. package/lib/changes/DecodeOperation.js.map +0 -1
  112. package/lib/changes/EncodeOperation.d.ts +0 -18
  113. package/lib/changes/EncodeOperation.js +0 -130
  114. package/lib/changes/EncodeOperation.js.map +0 -1
  115. package/lib/changes/ReferenceTracker.d.ts +0 -14
  116. package/lib/changes/ReferenceTracker.js +0 -83
  117. package/lib/changes/ReferenceTracker.js.map +0 -1
  118. package/lib/changes/consts.d.ts +0 -14
  119. package/lib/changes/consts.js +0 -18
  120. package/lib/changes/consts.js.map +0 -1
  121. package/lib/decoder/strategy/StateCallbacks.js.map +0 -1
  122. package/lib/decoding/decode.d.ts +0 -48
  123. package/lib/decoding/decode.js +0 -267
  124. package/lib/decoding/decode.js.map +0 -1
  125. package/lib/ecs.d.ts +0 -11
  126. package/lib/ecs.js +0 -160
  127. package/lib/ecs.js.map +0 -1
  128. package/lib/filters/index.d.ts +0 -8
  129. package/lib/filters/index.js +0 -24
  130. package/lib/filters/index.js.map +0 -1
  131. package/lib/spec.d.ts +0 -13
  132. package/lib/spec.js +0 -42
  133. package/lib/spec.js.map +0 -1
  134. package/lib/types/ArraySchema.d.ts +0 -238
  135. package/lib/types/ArraySchema.js +0 -555
  136. package/lib/types/ArraySchema.js.map +0 -1
  137. package/lib/types/CollectionSchema.d.ts +0 -35
  138. package/lib/types/CollectionSchema.js +0 -150
  139. package/lib/types/CollectionSchema.js.map +0 -1
  140. package/lib/types/MapSchema.d.ts +0 -38
  141. package/lib/types/MapSchema.js +0 -215
  142. package/lib/types/MapSchema.js.map +0 -1
  143. package/lib/types/SetSchema.d.ts +0 -32
  144. package/lib/types/SetSchema.js +0 -162
  145. package/lib/types/SetSchema.js.map +0 -1
  146. package/lib/types/typeRegistry.d.ts +0 -5
  147. package/lib/types/typeRegistry.js +0 -13
  148. package/lib/types/typeRegistry.js.map +0 -1
  149. package/lib/usage.d.ts +0 -1
  150. package/lib/usage.js +0 -22
  151. package/lib/usage.js.map +0 -1
  152. package/lib/v3.d.ts +0 -1
  153. package/lib/v3.js +0 -427
  154. package/lib/v3.js.map +0 -1
  155. package/lib/v3_experiment.d.ts +0 -1
  156. package/lib/v3_experiment.js +0 -407
  157. package/lib/v3_experiment.js.map +0 -1
@@ -7,10 +7,16 @@ const encode_1 = require("../encoding/encode");
7
7
  const spec_1 = require("../encoding/spec");
8
8
  const Root_1 = require("./Root");
9
9
  const ChangeTree_1 = require("./ChangeTree");
10
+ function concatBytes(a, b) {
11
+ const result = new Uint8Array(a.length + b.length);
12
+ result.set(a, 0);
13
+ result.set(b, a.length);
14
+ return result;
15
+ }
10
16
  class Encoder {
11
- static { this.BUFFER_SIZE = (typeof (Buffer) !== "undefined") && Buffer.poolSize || 8 * 1024; } // 8KB
17
+ static { this.BUFFER_SIZE = 8 * 1024; } // 8KB
12
18
  constructor(state) {
13
- this.sharedBuffer = Buffer.allocUnsafe(Encoder.BUFFER_SIZE);
19
+ this.sharedBuffer = new Uint8Array(Encoder.BUFFER_SIZE);
14
20
  //
15
21
  // Use .cache() here to avoid re-creating a new context for every new room instance.
16
22
  //
@@ -38,7 +44,7 @@ class Encoder {
38
44
  const changeTree = current.changeTree;
39
45
  if (hasView) {
40
46
  if (!view.isChangeTreeVisible(changeTree)) {
41
- // console.log("MARK AS INVISIBLE:", { ref: changeTree.ref.constructor.name, refId: changeTree.refId, raw: changeTree.ref.toJSON() });
47
+ // console.log("MARK AS INVISIBLE:", { ref: changeTree.ref.constructor.name, refId: changeTree.ref[$refId], raw: changeTree.ref.toJSON() });
42
48
  view.invisible.add(changeTree);
43
49
  continue; // skip this change tree
44
50
  }
@@ -59,7 +65,7 @@ class Encoder {
59
65
  // (unless it "hasView", which will need to revisit the root)
60
66
  if (hasView || it.offset > initialOffset || changeTree !== rootChangeTree) {
61
67
  buffer[it.offset++] = spec_1.SWITCH_TO_STRUCTURE & 255;
62
- encode_1.encode.number(buffer, changeTree.refId, it);
68
+ encode_1.encode.number(buffer, ref[symbols_1.$refId], it);
63
69
  }
64
70
  for (let j = 0; j < numChanges; j++) {
65
71
  const fieldIndex = changeSet.operations[j];
@@ -88,10 +94,9 @@ class Encoder {
88
94
  }
89
95
  }
90
96
  if (it.offset > buffer.byteLength) {
91
- // we can assume that n + 1 poolSize will suffice given that we are likely done with encoding at this point
92
- // multiples of poolSize are faster to allocate than arbitrary sizes
93
- // if we are on an older platform that doesn't implement pooling use 8kb as poolSize (that's the default for node)
94
- const newSize = Math.ceil(it.offset / (Buffer.poolSize ?? 8 * 1024)) * (Buffer.poolSize ?? 8 * 1024);
97
+ // we can assume that n + 1 BUFFER_SIZE will suffice given that we are likely done with encoding at this point
98
+ // multiples of BUFFER_SIZE are faster to allocate than arbitrary sizes
99
+ const newSize = Math.ceil(it.offset / Encoder.BUFFER_SIZE) * Encoder.BUFFER_SIZE;
95
100
  console.warn(`@colyseus/schema buffer overflow. Encoded state is higher than default BUFFER_SIZE. Use the following to increase default BUFFER_SIZE:
96
101
 
97
102
  import { Encoder } from "@colyseus/schema";
@@ -101,7 +106,9 @@ class Encoder {
101
106
  // resize buffer and re-encode (TODO: can we avoid re-encoding here?)
102
107
  // -> No we probably can't unless we catch the need for resize before encoding which is likely more computationally expensive than resizing on demand
103
108
  //
104
- buffer = Buffer.alloc(newSize, buffer); // fill with buffer here to memcpy previous encoding steps beyond the initialOffset
109
+ const newBuffer = new Uint8Array(newSize);
110
+ newBuffer.set(buffer); // copy previous encoding steps beyond the initialOffset
111
+ buffer = newBuffer;
105
112
  // assign resized buffer to local sharedBuffer
106
113
  if (buffer === this.sharedBuffer) {
107
114
  this.sharedBuffer = buffer;
@@ -119,10 +126,7 @@ class Encoder {
119
126
  const viewOffset = it.offset;
120
127
  // try to encode "filtered" changes
121
128
  this.encode(it, view, bytes, "allFilteredChanges", true, viewOffset);
122
- return Buffer.concat([
123
- bytes.subarray(0, sharedOffset),
124
- bytes.subarray(viewOffset, it.offset)
125
- ]);
129
+ return concatBytes(bytes.subarray(0, sharedOffset), bytes.subarray(viewOffset, it.offset));
126
130
  }
127
131
  encodeView(view, sharedOffset, it, bytes = this.sharedBuffer) {
128
132
  const viewOffset = it.offset;
@@ -146,7 +150,7 @@ class Encoder {
146
150
  const encoder = ctor[symbols_1.$encoder];
147
151
  const metadata = ctor[Symbol.metadata];
148
152
  bytes[it.offset++] = spec_1.SWITCH_TO_STRUCTURE & 255;
149
- encode_1.encode.number(bytes, changeTree.refId, it);
153
+ encode_1.encode.number(bytes, ref[symbols_1.$refId], it);
150
154
  for (let i = 0, numChanges = keys.length; i < numChanges; i++) {
151
155
  const index = Number(keys[i]);
152
156
  // workaround when using view.add() on item that has been deleted from state (see test "adding to view item that has been removed from state")
@@ -165,10 +169,7 @@ class Encoder {
165
169
  view.changes.clear();
166
170
  // try to encode "filtered" changes
167
171
  this.encode(it, view, bytes, "filteredChanges", false, viewOffset);
168
- return Buffer.concat([
169
- bytes.subarray(0, sharedOffset),
170
- bytes.subarray(viewOffset, it.offset)
171
- ]);
172
+ return concatBytes(bytes.subarray(0, sharedOffset), bytes.subarray(viewOffset, it.offset));
172
173
  }
173
174
  discardChanges() {
174
175
  // discard shared changes
@@ -1 +1 @@
1
- {"version":3,"file":"Encoder.js","sourceRoot":"","sources":["../../src/encoder/Encoder.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Schema } from \"../Schema\";\nimport { TypeContext } from \"../types/TypeContext\";\nimport { $changes, $encoder, $filter, $getByIndex } from \"../types/symbols\";\n\nimport { encode } from \"../encoding/encode\";\nimport type { Iterator } from \"../encoding/decode\";\n\nimport { OPERATION, SWITCH_TO_STRUCTURE, TYPE_ID } from '../encoding/spec';\nimport { Root } from \"./Root\";\n\nimport type { StateView } from \"./StateView\";\nimport type { Metadata } from \"../Metadata\";\nimport type { ChangeSetName, ChangeTree, ChangeTreeList, ChangeTreeNode } from \"./ChangeTree\";\nimport { createChangeTreeList } from \"./ChangeTree\";\n\nexport class Encoder<T extends Schema = any> {\n static BUFFER_SIZE = (typeof(Buffer) !== \"undefined\") && Buffer.poolSize || 8 * 1024; // 8KB\n sharedBuffer = Buffer.allocUnsafe(Encoder.BUFFER_SIZE);\n\n context: TypeContext;\n state: T;\n\n root: Root;\n\n constructor(state: T) {\n //\n // Use .cache() here to avoid re-creating a new context for every new room instance.\n //\n // We may need to make this optional in case of dynamically created\n // schemas - which would lead to memory leaks\n //\n this.context = TypeContext.cache(state.constructor as typeof Schema);\n this.root = new Root(this.context);\n\n this.setState(state);\n\n // console.log(\">>>>>>>>>>>>>>>> Encoder 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(state: T) {\n this.state = state;\n this.state[$changes].setRoot(this.root);\n }\n\n encode(\n it: Iterator = { offset: 0 },\n view?: StateView,\n buffer = this.sharedBuffer,\n changeSetName: ChangeSetName = \"changes\",\n isEncodeAll = changeSetName === \"allChanges\",\n initialOffset = it.offset // cache current offset in case we need to resize the buffer\n ): Buffer {\n const hasView = (view !== undefined);\n const rootChangeTree = this.state[$changes];\n\n let current: ChangeTreeList | ChangeTreeNode = this.root[changeSetName];\n\n while (current = current.next) {\n const changeTree = (current as ChangeTreeNode).changeTree;\n\n if (hasView) {\n if (!view.isChangeTreeVisible(changeTree)) {\n // console.log(\"MARK AS INVISIBLE:\", { ref: changeTree.ref.constructor.name, refId: changeTree.refId, raw: changeTree.ref.toJSON() });\n view.invisible.add(changeTree);\n continue; // skip this change tree\n }\n view.invisible.delete(changeTree); // remove from invisible list\n }\n\n const changeSet = changeTree[changeSetName];\n const ref = changeTree.ref;\n\n // TODO: avoid iterating over change tree if no changes were made\n const numChanges = changeSet.operations.length;\n if (numChanges === 0) { continue; }\n\n const ctor = ref.constructor;\n const encoder = ctor[$encoder];\n const filter = ctor[$filter];\n const metadata = ctor[Symbol.metadata];\n\n // skip root `refId` if it's the first change tree\n // (unless it \"hasView\", which will need to revisit the root)\n if (hasView || it.offset > initialOffset || changeTree !== rootChangeTree) {\n buffer[it.offset++] = SWITCH_TO_STRUCTURE & 255;\n encode.number(buffer, changeTree.refId, it);\n }\n\n for (let j = 0; j < numChanges; j++) {\n const fieldIndex = changeSet.operations[j];\n\n if (fieldIndex < 0) {\n // \"pure\" operation without fieldIndex (e.g. CLEAR, REVERSE, etc.)\n // encode and continue early - no need to reach $filter check\n buffer[it.offset++] = Math.abs(fieldIndex) & 255;\n continue;\n }\n\n const operation = (isEncodeAll)\n ? OPERATION.ADD\n : changeTree.indexedOperations[fieldIndex];\n\n //\n // first pass (encodeAll), identify \"filtered\" operations without encoding them\n // they will be encoded per client, based on their view.\n //\n // TODO: how can we optimize filtering out \"encode all\" operations?\n // TODO: avoid checking if no view tags were defined\n //\n if (fieldIndex === undefined || operation === undefined || (filter && !filter(ref, fieldIndex, view))) {\n // console.log(\"ADD AS INVISIBLE:\", fieldIndex, changeTree.ref.constructor.name)\n // view?.invisible.add(changeTree);\n continue;\n }\n\n encoder(this, buffer, changeTree, fieldIndex, operation, it, isEncodeAll, hasView, metadata);\n }\n }\n\n if (it.offset > buffer.byteLength) {\n // we can assume that n + 1 poolSize will suffice given that we are likely done with encoding at this point\n // multiples of poolSize are faster to allocate than arbitrary sizes\n // if we are on an older platform that doesn't implement pooling use 8kb as poolSize (that's the default for node)\n const newSize = Math.ceil(it.offset / (Buffer.poolSize ?? 8 * 1024)) * (Buffer.poolSize ?? 8 * 1024);\n\n console.warn(`@colyseus/schema buffer overflow. Encoded state is higher than default BUFFER_SIZE. Use the following to increase default BUFFER_SIZE:\n\n import { Encoder } from \"@colyseus/schema\";\n Encoder.BUFFER_SIZE = ${Math.round(newSize / 1024)} * 1024; // ${Math.round(newSize / 1024)} KB\n`);\n\n //\n // resize buffer and re-encode (TODO: can we avoid re-encoding here?)\n // -> No we probably can't unless we catch the need for resize before encoding which is likely more computationally expensive than resizing on demand\n //\n buffer = Buffer.alloc(newSize, buffer); // fill with buffer here to memcpy previous encoding steps beyond the initialOffset\n\n // assign resized buffer to local sharedBuffer\n if (buffer === this.sharedBuffer) {\n this.sharedBuffer = buffer;\n }\n\n return this.encode({ offset: initialOffset }, view, buffer, changeSetName, isEncodeAll);\n\n } else {\n\n return buffer.subarray(0, it.offset);\n }\n }\n\n encodeAll(it: Iterator = { offset: 0 }, buffer: Buffer = this.sharedBuffer) {\n return this.encode(it, undefined, buffer, \"allChanges\", true);\n }\n\n encodeAllView(view: StateView, sharedOffset: number, it: Iterator, bytes = this.sharedBuffer) {\n const viewOffset = it.offset;\n\n // try to encode \"filtered\" changes\n this.encode(it, view, bytes, \"allFilteredChanges\", true, viewOffset);\n\n return Buffer.concat([\n bytes.subarray(0, sharedOffset),\n bytes.subarray(viewOffset, it.offset)\n ]);\n }\n\n encodeView(view: StateView, sharedOffset: number, it: Iterator, bytes = this.sharedBuffer) {\n const viewOffset = it.offset;\n\n // encode visibility changes (add/remove for this view)\n for (const [refId, changes] of view.changes) {\n const changeTree: ChangeTree = this.root.changeTrees[refId];\n\n if (changeTree === undefined) {\n // detached instance, remove from view and skip.\n // console.log(\"detached instance, remove from view and skip.\", refId);\n view.changes.delete(refId);\n continue;\n }\n\n const keys = Object.keys(changes);\n if (keys.length === 0) {\n // FIXME: avoid having empty changes if no changes were made\n // console.log(\"changes.size === 0, skip\", refId, changeTree.ref.constructor.name);\n continue;\n }\n\n const ref = changeTree.ref;\n\n const ctor = ref.constructor;\n const encoder = ctor[$encoder];\n const metadata = ctor[Symbol.metadata];\n\n bytes[it.offset++] = SWITCH_TO_STRUCTURE & 255;\n encode.number(bytes, changeTree.refId, it);\n\n for (let i = 0, numChanges = keys.length; i < numChanges; i++) {\n const index = Number(keys[i]);\n // workaround when using view.add() on item that has been deleted from state (see test \"adding to view item that has been removed from state\")\n const value = changeTree.ref[$getByIndex](index);\n const operation = (value !== undefined && changes[index]) || OPERATION.DELETE;\n\n // isEncodeAll = false\n // hasView = true\n encoder(this, bytes, changeTree, index, operation, it, false, true, metadata);\n }\n }\n\n //\n // TODO: only clear view changes after all views are encoded\n // (to allow re-using StateView's for multiple clients)\n //\n // clear \"view\" changes after encoding\n view.changes.clear();\n\n // try to encode \"filtered\" changes\n this.encode(it, view, bytes, \"filteredChanges\", false, viewOffset);\n\n return Buffer.concat([\n bytes.subarray(0, sharedOffset),\n bytes.subarray(viewOffset, it.offset)\n ]);\n }\n\n discardChanges() {\n // discard shared changes\n let current = this.root.changes.next;\n while (current) {\n current.changeTree.endEncode('changes');\n current = current.next;\n }\n this.root.changes = createChangeTreeList();\n\n // discard filtered changes\n current = this.root.filteredChanges.next;\n while (current) {\n current.changeTree.endEncode('filteredChanges');\n current = current.next;\n }\n this.root.filteredChanges = createChangeTreeList();\n }\n\n tryEncodeTypeId (bytes: Buffer, baseType: typeof Schema, targetType: typeof Schema, it: Iterator) {\n const baseTypeId = this.context.getTypeId(baseType);\n const targetTypeId = this.context.getTypeId(targetType);\n\n if (targetTypeId === undefined) {\n console.warn(`@colyseus/schema WARNING: Class \"${targetType.name}\" is not registered on TypeRegistry - Please either tag the class with @entity or define a @type() field.`);\n return;\n }\n\n if (baseTypeId !== targetTypeId) {\n bytes[it.offset++] = TYPE_ID & 255;\n encode.number(bytes, targetTypeId, it);\n }\n }\n\n get hasChanges() {\n return (\n this.root.changes.next !== undefined ||\n this.root.filteredChanges.next !== undefined\n );\n }\n}\n"]}
1
+ {"version":3,"file":"Encoder.js","sourceRoot":"","sources":["../../src/encoder/Encoder.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Schema } from \"../Schema\";\nimport { TypeContext } from \"../types/TypeContext\";\nimport { $changes, $encoder, $filter, $getByIndex, $refId } from \"../types/symbols\";\n\nimport { encode } from \"../encoding/encode\";\nimport type { Iterator } from \"../encoding/decode\";\n\nimport { OPERATION, SWITCH_TO_STRUCTURE, TYPE_ID } from '../encoding/spec';\nimport { Root } from \"./Root\";\n\nimport type { StateView } from \"./StateView\";\nimport type { Metadata } from \"../Metadata\";\nimport type { ChangeSetName, ChangeTree, ChangeTreeList, ChangeTreeNode } from \"./ChangeTree\";\nimport { createChangeTreeList } from \"./ChangeTree\";\n\nfunction concatBytes(a: Uint8Array, b: Uint8Array): Uint8Array {\n const result = new Uint8Array(a.length + b.length);\n result.set(a, 0);\n result.set(b, a.length);\n return result;\n}\n\nexport class Encoder<T extends Schema = any> {\n static BUFFER_SIZE = 8 * 1024; // 8KB\n sharedBuffer = new Uint8Array(Encoder.BUFFER_SIZE);\n\n context: TypeContext;\n state: T;\n\n root: Root;\n\n constructor(state: T) {\n //\n // Use .cache() here to avoid re-creating a new context for every new room instance.\n //\n // We may need to make this optional in case of dynamically created\n // schemas - which would lead to memory leaks\n //\n this.context = TypeContext.cache(state.constructor as typeof Schema);\n this.root = new Root(this.context);\n\n this.setState(state);\n\n // console.log(\">>>>>>>>>>>>>>>> Encoder 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(state: T) {\n this.state = state;\n this.state[$changes].setRoot(this.root);\n }\n\n encode(\n it: Iterator = { offset: 0 },\n view?: StateView,\n buffer = this.sharedBuffer,\n changeSetName: ChangeSetName = \"changes\",\n isEncodeAll = changeSetName === \"allChanges\",\n initialOffset = it.offset // cache current offset in case we need to resize the buffer\n ): Uint8Array {\n const hasView = (view !== undefined);\n const rootChangeTree = this.state[$changes];\n\n let current: ChangeTreeList | ChangeTreeNode = this.root[changeSetName];\n\n while (current = current.next) {\n const changeTree = (current as ChangeTreeNode).changeTree;\n\n if (hasView) {\n if (!view.isChangeTreeVisible(changeTree)) {\n // console.log(\"MARK AS INVISIBLE:\", { ref: changeTree.ref.constructor.name, refId: changeTree.ref[$refId], raw: changeTree.ref.toJSON() });\n view.invisible.add(changeTree);\n continue; // skip this change tree\n }\n view.invisible.delete(changeTree); // remove from invisible list\n }\n\n const changeSet = changeTree[changeSetName];\n const ref = changeTree.ref;\n\n // TODO: avoid iterating over change tree if no changes were made\n const numChanges = changeSet.operations.length;\n if (numChanges === 0) { continue; }\n\n const ctor = ref.constructor;\n const encoder = ctor[$encoder];\n const filter = ctor[$filter];\n const metadata = ctor[Symbol.metadata];\n\n // skip root `refId` if it's the first change tree\n // (unless it \"hasView\", which will need to revisit the root)\n if (hasView || it.offset > initialOffset || changeTree !== rootChangeTree) {\n buffer[it.offset++] = SWITCH_TO_STRUCTURE & 255;\n encode.number(buffer, ref[$refId], it);\n }\n\n for (let j = 0; j < numChanges; j++) {\n const fieldIndex = changeSet.operations[j];\n\n if (fieldIndex < 0) {\n // \"pure\" operation without fieldIndex (e.g. CLEAR, REVERSE, etc.)\n // encode and continue early - no need to reach $filter check\n buffer[it.offset++] = Math.abs(fieldIndex) & 255;\n continue;\n }\n\n const operation = (isEncodeAll)\n ? OPERATION.ADD\n : changeTree.indexedOperations[fieldIndex];\n\n //\n // first pass (encodeAll), identify \"filtered\" operations without encoding them\n // they will be encoded per client, based on their view.\n //\n // TODO: how can we optimize filtering out \"encode all\" operations?\n // TODO: avoid checking if no view tags were defined\n //\n if (fieldIndex === undefined || operation === undefined || (filter && !filter(ref, fieldIndex, view))) {\n // console.log(\"ADD AS INVISIBLE:\", fieldIndex, changeTree.ref.constructor.name)\n // view?.invisible.add(changeTree);\n continue;\n }\n\n encoder(this, buffer, changeTree, fieldIndex, operation, it, isEncodeAll, hasView, metadata);\n }\n }\n\n if (it.offset > buffer.byteLength) {\n // we can assume that n + 1 BUFFER_SIZE will suffice given that we are likely done with encoding at this point\n // multiples of BUFFER_SIZE are faster to allocate than arbitrary sizes\n const newSize = Math.ceil(it.offset / Encoder.BUFFER_SIZE) * Encoder.BUFFER_SIZE;\n\n console.warn(`@colyseus/schema buffer overflow. Encoded state is higher than default BUFFER_SIZE. Use the following to increase default BUFFER_SIZE:\n\n import { Encoder } from \"@colyseus/schema\";\n Encoder.BUFFER_SIZE = ${Math.round(newSize / 1024)} * 1024; // ${Math.round(newSize / 1024)} KB\n`);\n\n //\n // resize buffer and re-encode (TODO: can we avoid re-encoding here?)\n // -> No we probably can't unless we catch the need for resize before encoding which is likely more computationally expensive than resizing on demand\n //\n const newBuffer = new Uint8Array(newSize);\n newBuffer.set(buffer); // copy previous encoding steps beyond the initialOffset\n buffer = newBuffer;\n\n // assign resized buffer to local sharedBuffer\n if (buffer === this.sharedBuffer) {\n this.sharedBuffer = buffer;\n }\n\n return this.encode({ offset: initialOffset }, view, buffer, changeSetName, isEncodeAll);\n\n } else {\n\n return buffer.subarray(0, it.offset);\n }\n }\n\n encodeAll(it: Iterator = { offset: 0 }, buffer = this.sharedBuffer) {\n return this.encode(it, undefined, buffer, \"allChanges\", true);\n }\n\n encodeAllView(view: StateView, sharedOffset: number, it: Iterator, bytes = this.sharedBuffer) {\n const viewOffset = it.offset;\n\n // try to encode \"filtered\" changes\n this.encode(it, view, bytes, \"allFilteredChanges\", true, viewOffset);\n\n return concatBytes(\n bytes.subarray(0, sharedOffset),\n bytes.subarray(viewOffset, it.offset)\n );\n }\n\n encodeView(view: StateView, sharedOffset: number, it: Iterator, bytes = this.sharedBuffer) {\n const viewOffset = it.offset;\n\n // encode visibility changes (add/remove for this view)\n for (const [refId, changes] of view.changes) {\n const changeTree: ChangeTree = this.root.changeTrees[refId];\n\n if (changeTree === undefined) {\n // detached instance, remove from view and skip.\n // console.log(\"detached instance, remove from view and skip.\", refId);\n view.changes.delete(refId);\n continue;\n }\n\n const keys = Object.keys(changes);\n if (keys.length === 0) {\n // FIXME: avoid having empty changes if no changes were made\n // console.log(\"changes.size === 0, skip\", refId, changeTree.ref.constructor.name);\n continue;\n }\n\n const ref = changeTree.ref;\n\n const ctor = ref.constructor;\n const encoder = ctor[$encoder];\n const metadata = ctor[Symbol.metadata];\n\n bytes[it.offset++] = SWITCH_TO_STRUCTURE & 255;\n encode.number(bytes, ref[$refId], it);\n\n for (let i = 0, numChanges = keys.length; i < numChanges; i++) {\n const index = Number(keys[i]);\n // workaround when using view.add() on item that has been deleted from state (see test \"adding to view item that has been removed from state\")\n const value = changeTree.ref[$getByIndex](index);\n const operation = (value !== undefined && changes[index]) || OPERATION.DELETE;\n\n // isEncodeAll = false\n // hasView = true\n encoder(this, bytes, changeTree, index, operation, it, false, true, metadata);\n }\n }\n\n //\n // TODO: only clear view changes after all views are encoded\n // (to allow re-using StateView's for multiple clients)\n //\n // clear \"view\" changes after encoding\n view.changes.clear();\n\n // try to encode \"filtered\" changes\n this.encode(it, view, bytes, \"filteredChanges\", false, viewOffset);\n\n return concatBytes(\n bytes.subarray(0, sharedOffset),\n bytes.subarray(viewOffset, it.offset)\n );\n }\n\n discardChanges() {\n // discard shared changes\n let current = this.root.changes.next;\n while (current) {\n current.changeTree.endEncode('changes');\n current = current.next;\n }\n this.root.changes = createChangeTreeList();\n\n // discard filtered changes\n current = this.root.filteredChanges.next;\n while (current) {\n current.changeTree.endEncode('filteredChanges');\n current = current.next;\n }\n this.root.filteredChanges = createChangeTreeList();\n }\n\n tryEncodeTypeId (bytes: Uint8Array, baseType: typeof Schema, targetType: typeof Schema, it: Iterator) {\n const baseTypeId = this.context.getTypeId(baseType);\n const targetTypeId = this.context.getTypeId(targetType);\n\n if (targetTypeId === undefined) {\n console.warn(`@colyseus/schema WARNING: Class \"${targetType.name}\" is not registered on TypeRegistry - Please either tag the class with @entity or define a @type() field.`);\n return;\n }\n\n if (baseTypeId !== targetTypeId) {\n bytes[it.offset++] = TYPE_ID & 255;\n encode.number(bytes, targetTypeId, it);\n }\n }\n\n get hasChanges() {\n return (\n this.root.changes.next !== undefined ||\n this.root.filteredChanges.next !== undefined\n );\n }\n}\n"]}
@@ -21,15 +21,17 @@ class Root {
21
21
  return this.nextUniqueId++;
22
22
  }
23
23
  add(changeTree) {
24
- // Assign unique `refId` to changeTree if it doesn't have one yet.
25
- if (changeTree.refId === undefined) {
26
- changeTree.refId = this.getNextUniqueId();
24
+ const ref = changeTree.ref;
25
+ // Assign unique `refId` to ref if it doesn't have one yet.
26
+ if (ref[symbols_1.$refId] === undefined) {
27
+ ref[symbols_1.$refId] = this.getNextUniqueId();
27
28
  }
28
- const isNewChangeTree = (this.changeTrees[changeTree.refId] === undefined);
29
+ const refId = ref[symbols_1.$refId];
30
+ const isNewChangeTree = (this.changeTrees[refId] === undefined);
29
31
  if (isNewChangeTree) {
30
- this.changeTrees[changeTree.refId] = changeTree;
32
+ this.changeTrees[refId] = changeTree;
31
33
  }
32
- const previousRefCount = this.refCount[changeTree.refId];
34
+ const previousRefCount = this.refCount[refId];
33
35
  if (previousRefCount === 0) {
34
36
  //
35
37
  // When a ChangeTree is re-added, it means that it was previously removed.
@@ -42,30 +44,31 @@ class Root {
42
44
  (0, ChangeTree_1.setOperationAtIndex)(changeTree.changes, len);
43
45
  }
44
46
  }
45
- this.refCount[changeTree.refId] = (previousRefCount || 0) + 1;
46
- // console.log("ADD", { refId: changeTree.refId, ref: changeTree.ref.constructor.name, refCount: this.refCount[changeTree.refId], isNewChangeTree });
47
+ this.refCount[refId] = (previousRefCount || 0) + 1;
48
+ // console.log("ADD", { refId, ref: ref.constructor.name, refCount: this.refCount[refId], isNewChangeTree });
47
49
  return isNewChangeTree;
48
50
  }
49
51
  remove(changeTree) {
50
- const refCount = (this.refCount[changeTree.refId]) - 1;
51
- // console.log("REMOVE", { refId: changeTree.refId, ref: changeTree.ref.constructor.name, refCount, needRemove: refCount <= 0 });
52
+ const refId = changeTree.ref[symbols_1.$refId];
53
+ const refCount = (this.refCount[refId]) - 1;
54
+ // console.log("REMOVE", { refId, ref: changeTree.ref.constructor.name, refCount, needRemove: refCount <= 0 });
52
55
  if (refCount <= 0) {
53
56
  //
54
57
  // Only remove "root" reference if it's the last reference
55
58
  //
56
59
  changeTree.root = undefined;
57
- delete this.changeTrees[changeTree.refId];
60
+ delete this.changeTrees[refId];
58
61
  this.removeChangeFromChangeSet("allChanges", changeTree);
59
62
  this.removeChangeFromChangeSet("changes", changeTree);
60
63
  if (changeTree.filteredChanges) {
61
64
  this.removeChangeFromChangeSet("allFilteredChanges", changeTree);
62
65
  this.removeChangeFromChangeSet("filteredChanges", changeTree);
63
66
  }
64
- this.refCount[changeTree.refId] = 0;
67
+ this.refCount[refId] = 0;
65
68
  changeTree.forEachChild((child, _) => {
66
69
  if (child.removeParent(changeTree.ref)) {
67
70
  if ((child.parentChain === undefined || // no parent, remove it
68
- (child.parentChain && this.refCount[child.refId] > 0) // parent is still in use, but has more than one reference, remove it
71
+ (child.parentChain && this.refCount[child.ref[symbols_1.$refId]] > 0) // parent is still in use, but has more than one reference, remove it
69
72
  )) {
70
73
  this.remove(child);
71
74
  }
@@ -77,7 +80,7 @@ class Root {
77
80
  });
78
81
  }
79
82
  else {
80
- this.refCount[changeTree.refId] = refCount;
83
+ this.refCount[refId] = refCount;
81
84
  //
82
85
  // When losing a reference to an instance, it is best to move the
83
86
  // ChangeTree next to its parent in the encoding queue.
@@ -1 +1 @@
1
- {"version":3,"file":"Root.js","sourceRoot":"","sources":["../../src/encoder/Root.ts"],"names":[],"mappings":"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","sourcesContent":["import { OPERATION } from \"../encoding/spec\";\nimport { TypeContext } from \"../types/TypeContext\";\nimport { ChangeTree, setOperationAtIndex, ChangeTreeList, createChangeTreeList, ChangeSetName, type ChangeTreeNode } from \"./ChangeTree\";\nimport { $changes } from \"../types/symbols\";\n\nexport class Root {\n protected nextUniqueId: number = 0;\n\n refCount: {[id: number]: number} = {};\n changeTrees: {[refId: number]: ChangeTree} = {};\n\n // all changes\n allChanges: ChangeTreeList = createChangeTreeList();\n allFilteredChanges: ChangeTreeList = createChangeTreeList();// TODO: do not initialize it if filters are not used\n\n // pending changes to be encoded\n changes: ChangeTreeList = createChangeTreeList();\n filteredChanges: ChangeTreeList = createChangeTreeList();// TODO: do not initialize it if filters are not used\n\n constructor(public types: TypeContext) { }\n\n getNextUniqueId() {\n return this.nextUniqueId++;\n }\n\n add(changeTree: ChangeTree) {\n // Assign unique `refId` to changeTree if it doesn't have one yet.\n if (changeTree.refId === undefined) {\n changeTree.refId = this.getNextUniqueId();\n }\n\n const isNewChangeTree = (this.changeTrees[changeTree.refId] === undefined);\n if (isNewChangeTree) { this.changeTrees[changeTree.refId] = changeTree; }\n\n const previousRefCount = this.refCount[changeTree.refId];\n if (previousRefCount === 0) {\n //\n // When a ChangeTree is re-added, it means that it was previously removed.\n // We need to re-add all changes to the `changes` map.\n //\n const ops = changeTree.allChanges.operations;\n let len = ops.length;\n while (len--) {\n changeTree.indexedOperations[ops[len]] = OPERATION.ADD;\n setOperationAtIndex(changeTree.changes, len);\n }\n }\n\n this.refCount[changeTree.refId] = (previousRefCount || 0) + 1;\n\n // console.log(\"ADD\", { refId: changeTree.refId, ref: changeTree.ref.constructor.name, refCount: this.refCount[changeTree.refId], isNewChangeTree });\n\n return isNewChangeTree;\n }\n\n remove(changeTree: ChangeTree) {\n const refCount = (this.refCount[changeTree.refId]) - 1;\n\n // console.log(\"REMOVE\", { refId: changeTree.refId, ref: changeTree.ref.constructor.name, refCount, needRemove: refCount <= 0 });\n\n if (refCount <= 0) {\n //\n // Only remove \"root\" reference if it's the last reference\n //\n changeTree.root = undefined;\n delete this.changeTrees[changeTree.refId];\n\n this.removeChangeFromChangeSet(\"allChanges\", changeTree);\n this.removeChangeFromChangeSet(\"changes\", changeTree);\n\n if (changeTree.filteredChanges) {\n this.removeChangeFromChangeSet(\"allFilteredChanges\", changeTree);\n this.removeChangeFromChangeSet(\"filteredChanges\", changeTree);\n }\n\n this.refCount[changeTree.refId] = 0;\n\n changeTree.forEachChild((child, _) => {\n if (child.removeParent(changeTree.ref)) {\n if ((\n child.parentChain === undefined || // no parent, remove it\n (child.parentChain && this.refCount[child.refId] > 0) // parent is still in use, but has more than one reference, remove it\n )) {\n this.remove(child);\n\n } else if (child.parentChain) {\n // re-assigning a child of the same root, move it next to parent\n this.moveNextToParent(child);\n }\n }\n });\n\n } else {\n this.refCount[changeTree.refId] = refCount;\n\n //\n // When losing a reference to an instance, it is best to move the\n // ChangeTree next to its parent in the encoding queue.\n //\n // This way, at decoding time, the instance that contains the\n // ChangeTree will be available before the ChangeTree itself. If the\n // containing instance is not available, the Decoder will throw\n // \"refId not found\" error.\n //\n this.recursivelyMoveNextToParent(changeTree);\n }\n\n return refCount;\n }\n\n recursivelyMoveNextToParent(changeTree: ChangeTree) {\n this.moveNextToParent(changeTree);\n changeTree.forEachChild((child, _) => this.recursivelyMoveNextToParent(child));\n }\n\n moveNextToParent(changeTree: ChangeTree) {\n if (changeTree.filteredChanges) {\n this.moveNextToParentInChangeTreeList(\"filteredChanges\", changeTree);\n this.moveNextToParentInChangeTreeList(\"allFilteredChanges\", changeTree);\n } else {\n this.moveNextToParentInChangeTreeList(\"changes\", changeTree);\n this.moveNextToParentInChangeTreeList(\"allChanges\", changeTree);\n }\n }\n\n moveNextToParentInChangeTreeList(changeSetName: ChangeSetName, changeTree: ChangeTree): void {\n const changeSet = this[changeSetName];\n const node = changeTree[changeSetName].queueRootNode;\n if (!node) return;\n\n // Find the parent in the linked list\n const parent = changeTree.parent;\n if (!parent || !parent[$changes]) return;\n\n const parentNode = parent[$changes][changeSetName]?.queueRootNode;\n if (!parentNode || parentNode === node) return;\n\n // Use cached positions - no iteration needed!\n const parentPosition = parentNode.position;\n const childPosition = node.position;\n\n // If child is already after parent, no need to move\n if (childPosition > parentPosition) return;\n\n // Child is before parent, so we need to move it after parent\n // This maintains decoding order (parent before child)\n\n // Remove node from current position\n if (node.prev) {\n node.prev.next = node.next;\n } else {\n changeSet.next = node.next;\n }\n\n if (node.next) {\n node.next.prev = node.prev;\n } else {\n changeSet.tail = node.prev;\n }\n\n // Insert node right after parent\n node.prev = parentNode;\n node.next = parentNode.next;\n\n if (parentNode.next) {\n parentNode.next.prev = node;\n } else {\n changeSet.tail = node;\n }\n\n parentNode.next = node;\n\n // Update positions after the move\n this.updatePositionsAfterMove(changeSet, node, parentPosition + 1);\n }\n\n public enqueueChangeTree(\n changeTree: ChangeTree,\n changeSet: 'changes' | 'filteredChanges' | 'allFilteredChanges' | 'allChanges',\n queueRootNode = changeTree[changeSet].queueRootNode\n ) {\n // skip\n if (queueRootNode) { return; }\n\n // Add to linked list if not already present\n changeTree[changeSet].queueRootNode = this.addToChangeTreeList(this[changeSet], changeTree);\n }\n\n protected addToChangeTreeList(list: ChangeTreeList, changeTree: ChangeTree): ChangeTreeNode {\n const node: ChangeTreeNode = {\n changeTree,\n next: undefined,\n prev: undefined,\n position: list.tail ? list.tail.position + 1 : 0\n };\n\n if (!list.next) {\n list.next = node;\n list.tail = node;\n } else {\n node.prev = list.tail;\n list.tail!.next = node;\n list.tail = node;\n }\n\n return node;\n }\n\n protected updatePositionsAfterRemoval(list: ChangeTreeList, removedPosition: number) {\n // Update positions for all nodes after the removed position\n let current = list.next;\n let position = 0;\n\n while (current) {\n if (position >= removedPosition) {\n current.position = position;\n }\n current = current.next;\n position++;\n }\n }\n\n protected updatePositionsAfterMove(list: ChangeTreeList, node: ChangeTreeNode, newPosition: number) {\n // Recalculate all positions - this is more reliable than trying to be clever\n let current = list.next;\n let position = 0;\n\n while (current) {\n current.position = position;\n current = current.next;\n position++;\n }\n }\n\n public removeChangeFromChangeSet(changeSetName: ChangeSetName, changeTree: ChangeTree) {\n const changeSet = this[changeSetName];\n const node = changeTree[changeSetName].queueRootNode;\n\n if (node && node.changeTree === changeTree) {\n const removedPosition = node.position;\n\n // Remove the node from the linked list\n if (node.prev) {\n node.prev.next = node.next;\n } else {\n changeSet.next = node.next;\n }\n\n if (node.next) {\n node.next.prev = node.prev;\n } else {\n changeSet.tail = node.prev;\n }\n\n // Update positions for nodes that came after the removed node\n this.updatePositionsAfterRemoval(changeSet, removedPosition);\n\n // Clear ChangeTree reference\n changeTree[changeSetName].queueRootNode = undefined;\n return true;\n }\n\n return false;\n }\n}\n"]}
1
+ {"version":3,"file":"Root.js","sourceRoot":"","sources":["../../src/encoder/Root.ts"],"names":[],"mappings":"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","sourcesContent":["import { OPERATION } from \"../encoding/spec\";\nimport { TypeContext } from \"../types/TypeContext\";\nimport { ChangeTree, setOperationAtIndex, ChangeTreeList, createChangeTreeList, ChangeSetName, type ChangeTreeNode } from \"./ChangeTree\";\nimport { $changes, $refId } from \"../types/symbols\";\n\nexport class Root {\n protected nextUniqueId: number = 0;\n\n refCount: {[id: number]: number} = {};\n changeTrees: {[refId: number]: ChangeTree} = {};\n\n // all changes\n allChanges: ChangeTreeList = createChangeTreeList();\n allFilteredChanges: ChangeTreeList = createChangeTreeList();// TODO: do not initialize it if filters are not used\n\n // pending changes to be encoded\n changes: ChangeTreeList = createChangeTreeList();\n filteredChanges: ChangeTreeList = createChangeTreeList();// TODO: do not initialize it if filters are not used\n\n constructor(public types: TypeContext) { }\n\n getNextUniqueId() {\n return this.nextUniqueId++;\n }\n\n add(changeTree: ChangeTree) {\n const ref = changeTree.ref;\n\n // Assign unique `refId` to ref if it doesn't have one yet.\n if (ref[$refId] === undefined) {\n ref[$refId] = this.getNextUniqueId();\n }\n\n const refId = ref[$refId];\n\n const isNewChangeTree = (this.changeTrees[refId] === undefined);\n if (isNewChangeTree) { this.changeTrees[refId] = changeTree; }\n\n const previousRefCount = this.refCount[refId];\n if (previousRefCount === 0) {\n //\n // When a ChangeTree is re-added, it means that it was previously removed.\n // We need to re-add all changes to the `changes` map.\n //\n const ops = changeTree.allChanges.operations;\n let len = ops.length;\n while (len--) {\n changeTree.indexedOperations[ops[len]] = OPERATION.ADD;\n setOperationAtIndex(changeTree.changes, len);\n }\n }\n\n this.refCount[refId] = (previousRefCount || 0) + 1;\n\n // console.log(\"ADD\", { refId, ref: ref.constructor.name, refCount: this.refCount[refId], isNewChangeTree });\n\n return isNewChangeTree;\n }\n\n remove(changeTree: ChangeTree) {\n const refId = changeTree.ref[$refId];\n const refCount = (this.refCount[refId]) - 1;\n\n // console.log(\"REMOVE\", { refId, ref: changeTree.ref.constructor.name, refCount, needRemove: refCount <= 0 });\n\n if (refCount <= 0) {\n //\n // Only remove \"root\" reference if it's the last reference\n //\n changeTree.root = undefined;\n delete this.changeTrees[refId];\n\n this.removeChangeFromChangeSet(\"allChanges\", changeTree);\n this.removeChangeFromChangeSet(\"changes\", changeTree);\n\n if (changeTree.filteredChanges) {\n this.removeChangeFromChangeSet(\"allFilteredChanges\", changeTree);\n this.removeChangeFromChangeSet(\"filteredChanges\", changeTree);\n }\n\n this.refCount[refId] = 0;\n\n changeTree.forEachChild((child, _) => {\n if (child.removeParent(changeTree.ref)) {\n if ((\n child.parentChain === undefined || // no parent, remove it\n (child.parentChain && this.refCount[child.ref[$refId]] > 0) // parent is still in use, but has more than one reference, remove it\n )) {\n this.remove(child);\n\n } else if (child.parentChain) {\n // re-assigning a child of the same root, move it next to parent\n this.moveNextToParent(child);\n }\n }\n });\n\n } else {\n this.refCount[refId] = refCount;\n\n //\n // When losing a reference to an instance, it is best to move the\n // ChangeTree next to its parent in the encoding queue.\n //\n // This way, at decoding time, the instance that contains the\n // ChangeTree will be available before the ChangeTree itself. If the\n // containing instance is not available, the Decoder will throw\n // \"refId not found\" error.\n //\n this.recursivelyMoveNextToParent(changeTree);\n }\n\n return refCount;\n }\n\n recursivelyMoveNextToParent(changeTree: ChangeTree) {\n this.moveNextToParent(changeTree);\n changeTree.forEachChild((child, _) => this.recursivelyMoveNextToParent(child));\n }\n\n moveNextToParent(changeTree: ChangeTree) {\n if (changeTree.filteredChanges) {\n this.moveNextToParentInChangeTreeList(\"filteredChanges\", changeTree);\n this.moveNextToParentInChangeTreeList(\"allFilteredChanges\", changeTree);\n } else {\n this.moveNextToParentInChangeTreeList(\"changes\", changeTree);\n this.moveNextToParentInChangeTreeList(\"allChanges\", changeTree);\n }\n }\n\n moveNextToParentInChangeTreeList(changeSetName: ChangeSetName, changeTree: ChangeTree): void {\n const changeSet = this[changeSetName];\n const node = changeTree[changeSetName].queueRootNode;\n if (!node) return;\n\n // Find the parent in the linked list\n const parent = changeTree.parent;\n if (!parent || !parent[$changes]) return;\n\n const parentNode = parent[$changes][changeSetName]?.queueRootNode;\n if (!parentNode || parentNode === node) return;\n\n // Use cached positions - no iteration needed!\n const parentPosition = parentNode.position;\n const childPosition = node.position;\n\n // If child is already after parent, no need to move\n if (childPosition > parentPosition) return;\n\n // Child is before parent, so we need to move it after parent\n // This maintains decoding order (parent before child)\n\n // Remove node from current position\n if (node.prev) {\n node.prev.next = node.next;\n } else {\n changeSet.next = node.next;\n }\n\n if (node.next) {\n node.next.prev = node.prev;\n } else {\n changeSet.tail = node.prev;\n }\n\n // Insert node right after parent\n node.prev = parentNode;\n node.next = parentNode.next;\n\n if (parentNode.next) {\n parentNode.next.prev = node;\n } else {\n changeSet.tail = node;\n }\n\n parentNode.next = node;\n\n // Update positions after the move\n this.updatePositionsAfterMove(changeSet, node, parentPosition + 1);\n }\n\n public enqueueChangeTree(\n changeTree: ChangeTree,\n changeSet: 'changes' | 'filteredChanges' | 'allFilteredChanges' | 'allChanges',\n queueRootNode = changeTree[changeSet].queueRootNode\n ) {\n // skip\n if (queueRootNode) { return; }\n\n // Add to linked list if not already present\n changeTree[changeSet].queueRootNode = this.addToChangeTreeList(this[changeSet], changeTree);\n }\n\n protected addToChangeTreeList(list: ChangeTreeList, changeTree: ChangeTree): ChangeTreeNode {\n const node: ChangeTreeNode = {\n changeTree,\n next: undefined,\n prev: undefined,\n position: list.tail ? list.tail.position + 1 : 0\n };\n\n if (!list.next) {\n list.next = node;\n list.tail = node;\n } else {\n node.prev = list.tail;\n list.tail!.next = node;\n list.tail = node;\n }\n\n return node;\n }\n\n protected updatePositionsAfterRemoval(list: ChangeTreeList, removedPosition: number) {\n // Update positions for all nodes after the removed position\n let current = list.next;\n let position = 0;\n\n while (current) {\n if (position >= removedPosition) {\n current.position = position;\n }\n current = current.next;\n position++;\n }\n }\n\n protected updatePositionsAfterMove(list: ChangeTreeList, node: ChangeTreeNode, newPosition: number) {\n // Recalculate all positions - this is more reliable than trying to be clever\n let current = list.next;\n let position = 0;\n\n while (current) {\n current.position = position;\n current = current.next;\n position++;\n }\n }\n\n public removeChangeFromChangeSet(changeSetName: ChangeSetName, changeTree: ChangeTree) {\n const changeSet = this[changeSetName];\n const node = changeTree[changeSetName].queueRootNode;\n\n if (node && node.changeTree === changeTree) {\n const removedPosition = node.position;\n\n // Remove the node from the linked list\n if (node.prev) {\n node.prev.next = node.next;\n } else {\n changeSet.next = node.next;\n }\n\n if (node.next) {\n node.next.prev = node.prev;\n } else {\n changeSet.tail = node.prev;\n }\n\n // Update positions for nodes that came after the removed node\n this.updatePositionsAfterRemoval(changeSet, removedPosition);\n\n // Clear ChangeTree reference\n changeTree[changeSetName].queueRootNode = undefined;\n return true;\n }\n\n return false;\n }\n}\n"]}
@@ -39,7 +39,7 @@ class StateView {
39
39
  return false;
40
40
  }
41
41
  else if (!parentChangeTree &&
42
- changeTree.refId !== 0 // allow root object
42
+ obj[symbols_1.$refId] !== 0 // allow root object
43
43
  ) {
44
44
  /**
45
45
  * TODO: can we avoid this?
@@ -63,11 +63,11 @@ class StateView {
63
63
  if (checkIncludeParent && parentChangeTree) {
64
64
  this.addParentOf(changeTree, tag);
65
65
  }
66
- let changes = this.changes.get(changeTree.refId);
66
+ let changes = this.changes.get(obj[symbols_1.$refId]);
67
67
  if (changes === undefined) {
68
68
  changes = {};
69
69
  // FIXME / OPTIMIZE: do not add if no changes are needed
70
- this.changes.set(changeTree.refId, changes);
70
+ this.changes.set(obj[symbols_1.$refId], changes);
71
71
  }
72
72
  let isChildAdded = false;
73
73
  //
@@ -147,10 +147,10 @@ class StateView {
147
147
  }
148
148
  // add parent's tag properties
149
149
  if (changeTree.getChange(parentIndex) !== spec_1.OPERATION.DELETE) {
150
- let changes = this.changes.get(changeTree.refId);
150
+ let changes = this.changes.get(changeTree.ref[symbols_1.$refId]);
151
151
  if (changes === undefined) {
152
152
  changes = {};
153
- this.changes.set(changeTree.refId, changes);
153
+ this.changes.set(changeTree.ref[symbols_1.$refId], changes);
154
154
  }
155
155
  if (!this.tags) {
156
156
  this.tags = new WeakMap();
@@ -182,27 +182,28 @@ class StateView {
182
182
  }
183
183
  const ref = changeTree.ref;
184
184
  const metadata = ref.constructor[Symbol.metadata]; // ArraySchema/MapSchema do not have metadata
185
- let changes = this.changes.get(changeTree.refId);
185
+ const refId = ref[symbols_1.$refId];
186
+ let changes = this.changes.get(refId);
186
187
  if (changes === undefined) {
187
188
  changes = {};
188
- this.changes.set(changeTree.refId, changes);
189
+ this.changes.set(refId, changes);
189
190
  }
190
191
  if (tag === annotations_1.DEFAULT_VIEW_TAG) {
191
192
  // parent is collection (Map/Array)
192
193
  const parent = changeTree.parent;
193
194
  if (parent && !Metadata_1.Metadata.isValidInstance(parent) && changeTree.isFiltered) {
194
- const parentChangeTree = parent[symbols_1.$changes];
195
- let changes = this.changes.get(parentChangeTree.refId);
195
+ const parentRefId = parent[symbols_1.$refId];
196
+ let changes = this.changes.get(parentRefId);
196
197
  if (changes === undefined) {
197
198
  changes = {};
198
- this.changes.set(parentChangeTree.refId, changes);
199
+ this.changes.set(parentRefId, changes);
199
200
  }
200
201
  else if (changes[changeTree.parentIndex] === spec_1.OPERATION.ADD) {
201
202
  //
202
203
  // SAME PATCH ADD + REMOVE:
203
204
  // The 'changes' of deleted structure should be ignored.
204
205
  //
205
- this.changes.delete(changeTree.refId);
206
+ this.changes.delete(refId);
206
207
  }
207
208
  // DELETE / DELETE BY REF ID
208
209
  changes[changeTree.parentIndex] = spec_1.OPERATION.DELETE;
@@ -262,7 +263,7 @@ class StateView {
262
263
  if (!isVisible && changeTree.isVisibilitySharedWithParent) {
263
264
  // console.log("CHECK AGAINST PARENT...", {
264
265
  // ref: changeTree.ref.constructor.name,
265
- // refId: changeTree.refId,
266
+ // refId: changeTree.ref[$refId],
266
267
  // parent: changeTree.parent.constructor.name,
267
268
  // });
268
269
  if (this.visible.has(changeTree.parent[symbols_1.$changes])) {
@@ -1 +1 @@
1
- {"version":3,"file":"StateView.js","sourceRoot":"","sources":["../../src/encoder/StateView.ts"],"names":[],"mappings":"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","sourcesContent":["import { ChangeTree, IndexedOperations, Ref } from \"./ChangeTree\";\nimport { $changes, $fieldIndexesByViewTag, $viewFieldIndexes } from \"../types/symbols\";\nimport { DEFAULT_VIEW_TAG } from \"../annotations\";\nimport { OPERATION } from \"../encoding/spec\";\nimport { Metadata } from \"../Metadata\";\nimport { spliceOne } from \"../types/utils\";\nimport type { Schema } from \"../Schema\";\n\nexport function createView(iterable: boolean = false) {\n return new StateView(iterable);\n}\n\nexport class StateView {\n /**\n * Iterable list of items that are visible to this view\n * (Available only if constructed with `iterable: true`)\n */\n items: Ref[];\n\n /**\n * List of ChangeTree's that are visible to this view\n */\n visible: WeakSet<ChangeTree> = new WeakSet<ChangeTree>();\n\n /**\n * List of ChangeTree's that are invisible to this view\n */\n invisible: WeakSet<ChangeTree> = new WeakSet<ChangeTree>();\n\n tags?: WeakMap<ChangeTree, Set<number>>; // TODO: use bit manipulation instead of Set<number> ()\n\n /**\n * Manual \"ADD\" operations for changes per ChangeTree, specific to this view.\n * (This is used to force encoding a property, even if it was not changed)\n */\n changes = new Map<number, IndexedOperations>();\n\n constructor(public iterable: boolean = false) {\n if (iterable) {\n this.items = [];\n }\n }\n\n // TODO: allow to set multiple tags at once\n add(obj: Ref, tag: number = DEFAULT_VIEW_TAG, checkIncludeParent: boolean = true) {\n const changeTree: ChangeTree = obj?.[$changes];\n const parentChangeTree = changeTree.parent;\n\n if (!changeTree) {\n console.warn(\"StateView#add(), invalid object:\", obj);\n return false;\n\n } else if (\n !parentChangeTree &&\n changeTree.refId !== 0 // allow root object\n ) {\n /**\n * TODO: can we avoid this?\n *\n * When the \"parent\" structure has the @view() tag, it is currently\n * not possible to identify it has to be added to the view as well\n * (this.addParentOf() is not called).\n */\n throw new Error(\n `Cannot add a detached instance to the StateView. Make sure to assign the \"${changeTree.ref.constructor.name}\" instance to the state before calling view.add()`\n );\n }\n\n // FIXME: ArraySchema/MapSchema do not have metadata\n const metadata: Metadata = (obj.constructor as typeof Schema)[Symbol.metadata];\n this.visible.add(changeTree);\n\n // add to iterable list (only the explicitly added items)\n if (this.iterable && checkIncludeParent) {\n this.items.push(obj);\n }\n\n // add parent ChangeTree's\n // - if it was invisible to this view\n // - if it were previously filtered out\n if (checkIncludeParent && parentChangeTree) {\n this.addParentOf(changeTree, tag);\n }\n\n let changes = this.changes.get(changeTree.refId);\n if (changes === undefined) {\n changes = {};\n // FIXME / OPTIMIZE: do not add if no changes are needed\n this.changes.set(changeTree.refId, changes);\n }\n\n let isChildAdded = false;\n\n //\n // Add children of this ChangeTree first.\n // If successful, we must link the current ChangeTree to the child.\n //\n changeTree.forEachChild((change, index) => {\n // Do not ADD children that don't have the same tag\n if (\n metadata &&\n metadata[index].tag !== undefined &&\n metadata[index].tag !== tag\n ) {\n return;\n }\n\n if (this.add(change.ref, tag, false)) {\n isChildAdded = true;\n }\n });\n\n // set tag\n if (tag !== DEFAULT_VIEW_TAG) {\n if (!this.tags) {\n this.tags = new WeakMap<ChangeTree, Set<number>>();\n }\n let tags: Set<number>;\n if (!this.tags.has(changeTree)) {\n tags = new Set<number>();\n this.tags.set(changeTree, tags);\n } else {\n tags = this.tags.get(changeTree);\n }\n tags.add(tag);\n\n // Ref: add tagged properties\n metadata?.[$fieldIndexesByViewTag]?.[tag]?.forEach((index) => {\n if (changeTree.getChange(index) !== OPERATION.DELETE) {\n changes[index] = OPERATION.ADD;\n }\n });\n\n } else if (!changeTree.isNew || isChildAdded) {\n // new structures will be added as part of .encode() call, no need to force it to .encodeView()\n const changeSet = (changeTree.filteredChanges !== undefined)\n ? changeTree.allFilteredChanges\n : changeTree.allChanges;\n\n const isInvisible = this.invisible.has(changeTree);\n\n for (let i = 0, len = changeSet.operations.length; i < len; i++) {\n const index = changeSet.operations[i];\n if (index === undefined) { continue; } // skip \"undefined\" indexes\n\n const op = changeTree.indexedOperations[index] ?? OPERATION.ADD;\n const tagAtIndex = metadata?.[index].tag;\n if (\n op !== OPERATION.DELETE &&\n (\n isInvisible || // if \"invisible\", include all\n tagAtIndex === undefined || // \"all change\" with no tag\n tagAtIndex === tag // tagged property\n )\n ) {\n changes[index] = op;\n isChildAdded = true; // FIXME: assign only once\n }\n }\n }\n\n return isChildAdded;\n }\n\n protected addParentOf(childChangeTree: ChangeTree, tag: number) {\n const changeTree = childChangeTree.parent[$changes];\n const parentIndex = childChangeTree.parentIndex;\n\n if (!this.visible.has(changeTree)) {\n // view must have all \"changeTree\" parent tree\n this.visible.add(changeTree);\n\n // add parent's parent\n const parentChangeTree: ChangeTree = changeTree.parent?.[$changes];\n if (parentChangeTree && (parentChangeTree.filteredChanges !== undefined)) {\n this.addParentOf(changeTree, tag);\n }\n\n // // parent is already available, no need to add it!\n // if (!this.invisible.has(changeTree)) { return; }\n }\n\n // add parent's tag properties\n if (changeTree.getChange(parentIndex) !== OPERATION.DELETE) {\n let changes = this.changes.get(changeTree.refId);\n if (changes === undefined) {\n changes = {};\n this.changes.set(changeTree.refId, changes);\n }\n\n if (!this.tags) {\n this.tags = new WeakMap<ChangeTree, Set<number>>();\n }\n\n let tags: Set<number>;\n if (!this.tags.has(changeTree)) {\n tags = new Set<number>();\n this.tags.set(changeTree, tags);\n } else {\n tags = this.tags.get(changeTree);\n }\n tags.add(tag);\n\n changes[parentIndex] = OPERATION.ADD;\n }\n }\n\n remove(obj: Ref, tag?: number): this; // hide _isClear parameter from public API\n remove(obj: Ref, tag?: number, _isClear?: boolean): this;\n remove(obj: Ref, tag: number = DEFAULT_VIEW_TAG, _isClear: boolean = false): this {\n const changeTree: ChangeTree = obj[$changes];\n if (!changeTree) {\n console.warn(\"StateView#remove(), invalid object:\", obj);\n return this;\n }\n\n this.visible.delete(changeTree);\n\n // remove from iterable list\n if (\n this.iterable &&\n !_isClear // no need to remove during clear(), as it will be cleared entirely\n ) {\n spliceOne(this.items, this.items.indexOf(obj));\n }\n\n const ref = changeTree.ref;\n const metadata: Metadata = ref.constructor[Symbol.metadata]; // ArraySchema/MapSchema do not have metadata\n\n let changes = this.changes.get(changeTree.refId);\n if (changes === undefined) {\n changes = {};\n this.changes.set(changeTree.refId, changes);\n }\n\n if (tag === DEFAULT_VIEW_TAG) {\n // parent is collection (Map/Array)\n const parent = changeTree.parent;\n if (parent && !Metadata.isValidInstance(parent) && changeTree.isFiltered) {\n const parentChangeTree = parent[$changes];\n let changes = this.changes.get(parentChangeTree.refId);\n if (changes === undefined) {\n changes = {};\n this.changes.set(parentChangeTree.refId, changes);\n\n } else if (changes[changeTree.parentIndex] === OPERATION.ADD) {\n //\n // SAME PATCH ADD + REMOVE:\n // The 'changes' of deleted structure should be ignored.\n //\n this.changes.delete(changeTree.refId);\n }\n\n // DELETE / DELETE BY REF ID\n changes[changeTree.parentIndex] = OPERATION.DELETE;\n\n // Remove child schema from visible set\n this._recursiveDeleteVisibleChangeTree(changeTree);\n\n } else {\n // delete all \"tagged\" properties.\n metadata?.[$viewFieldIndexes]?.forEach((index) =>\n changes[index] = OPERATION.DELETE);\n }\n\n } else {\n // delete only tagged properties\n metadata?.[$fieldIndexesByViewTag][tag].forEach((index) =>\n changes[index] = OPERATION.DELETE);\n }\n\n // remove tag\n if (this.tags && this.tags.has(changeTree)) {\n const tags = this.tags.get(changeTree);\n if (tag === undefined) {\n // delete all tags\n this.tags.delete(changeTree);\n } else {\n // delete specific tag\n tags.delete(tag);\n\n // if tag set is empty, delete it entirely\n if (tags.size === 0) {\n this.tags.delete(changeTree);\n }\n }\n }\n\n return this;\n }\n\n has(obj: Ref) {\n return this.visible.has(obj[$changes]);\n }\n\n hasTag(ob: Ref, tag: number = DEFAULT_VIEW_TAG) {\n const tags = this.tags?.get(ob[$changes]);\n return tags?.has(tag) ?? false;\n }\n\n clear() {\n if (!this.iterable) {\n throw new Error(\"StateView#clear() is only available for iterable StateView's. Use StateView(iterable: true) constructor.\");\n }\n\n for (let i = 0, l = this.items.length; i < l; i++) {\n this.remove(this.items[i], DEFAULT_VIEW_TAG, true);\n }\n\n // clear items array\n this.items.length = 0;\n }\n\n isChangeTreeVisible(changeTree: ChangeTree) {\n let isVisible = this.visible.has(changeTree);\n\n //\n // TODO: avoid checking for parent visibility, most of the time it's not needed\n // See test case: 'should not be required to manually call view.add() items to child arrays without @view() tag'\n //\n if (!isVisible && changeTree.isVisibilitySharedWithParent){\n\n // console.log(\"CHECK AGAINST PARENT...\", {\n // ref: changeTree.ref.constructor.name,\n // refId: changeTree.refId,\n // parent: changeTree.parent.constructor.name,\n // });\n\n if (this.visible.has(changeTree.parent[$changes])) {\n this.visible.add(changeTree);\n isVisible = true;\n }\n }\n\n return isVisible;\n }\n\n protected _recursiveDeleteVisibleChangeTree(changeTree: ChangeTree) {\n changeTree.forEachChild((childChangeTree) => {\n this.visible.delete(childChangeTree);\n this._recursiveDeleteVisibleChangeTree(childChangeTree);\n });\n }\n}\n"]}
1
+ {"version":3,"file":"StateView.js","sourceRoot":"","sources":["../../src/encoder/StateView.ts"],"names":[],"mappings":"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","sourcesContent":["import { ChangeTree, IndexedOperations, Ref } from \"./ChangeTree\";\nimport { $changes, $fieldIndexesByViewTag, $refId, $viewFieldIndexes } from \"../types/symbols\";\nimport { DEFAULT_VIEW_TAG } from \"../annotations\";\nimport { OPERATION } from \"../encoding/spec\";\nimport { Metadata } from \"../Metadata\";\nimport { spliceOne } from \"../types/utils\";\nimport type { Schema } from \"../Schema\";\n\nexport function createView(iterable: boolean = false) {\n return new StateView(iterable);\n}\n\nexport class StateView {\n /**\n * Iterable list of items that are visible to this view\n * (Available only if constructed with `iterable: true`)\n */\n items: Ref[];\n\n /**\n * List of ChangeTree's that are visible to this view\n */\n visible: WeakSet<ChangeTree> = new WeakSet<ChangeTree>();\n\n /**\n * List of ChangeTree's that are invisible to this view\n */\n invisible: WeakSet<ChangeTree> = new WeakSet<ChangeTree>();\n\n tags?: WeakMap<ChangeTree, Set<number>>; // TODO: use bit manipulation instead of Set<number> ()\n\n /**\n * Manual \"ADD\" operations for changes per ChangeTree, specific to this view.\n * (This is used to force encoding a property, even if it was not changed)\n */\n changes = new Map<number, IndexedOperations>();\n\n constructor(public iterable: boolean = false) {\n if (iterable) {\n this.items = [];\n }\n }\n\n // TODO: allow to set multiple tags at once\n add(obj: Ref, tag: number = DEFAULT_VIEW_TAG, checkIncludeParent: boolean = true) {\n const changeTree: ChangeTree = obj?.[$changes];\n const parentChangeTree = changeTree.parent;\n\n if (!changeTree) {\n console.warn(\"StateView#add(), invalid object:\", obj);\n return false;\n\n } else if (\n !parentChangeTree &&\n obj[$refId] !== 0 // allow root object\n ) {\n /**\n * TODO: can we avoid this?\n *\n * When the \"parent\" structure has the @view() tag, it is currently\n * not possible to identify it has to be added to the view as well\n * (this.addParentOf() is not called).\n */\n throw new Error(\n `Cannot add a detached instance to the StateView. Make sure to assign the \"${changeTree.ref.constructor.name}\" instance to the state before calling view.add()`\n );\n }\n\n // FIXME: ArraySchema/MapSchema do not have metadata\n const metadata: Metadata = (obj.constructor as typeof Schema)[Symbol.metadata];\n this.visible.add(changeTree);\n\n // add to iterable list (only the explicitly added items)\n if (this.iterable && checkIncludeParent) {\n this.items.push(obj);\n }\n\n // add parent ChangeTree's\n // - if it was invisible to this view\n // - if it were previously filtered out\n if (checkIncludeParent && parentChangeTree) {\n this.addParentOf(changeTree, tag);\n }\n\n let changes = this.changes.get(obj[$refId]);\n if (changes === undefined) {\n changes = {};\n // FIXME / OPTIMIZE: do not add if no changes are needed\n this.changes.set(obj[$refId], changes);\n }\n\n let isChildAdded = false;\n\n //\n // Add children of this ChangeTree first.\n // If successful, we must link the current ChangeTree to the child.\n //\n changeTree.forEachChild((change, index) => {\n // Do not ADD children that don't have the same tag\n if (\n metadata &&\n metadata[index].tag !== undefined &&\n metadata[index].tag !== tag\n ) {\n return;\n }\n\n if (this.add(change.ref, tag, false)) {\n isChildAdded = true;\n }\n });\n\n // set tag\n if (tag !== DEFAULT_VIEW_TAG) {\n if (!this.tags) {\n this.tags = new WeakMap<ChangeTree, Set<number>>();\n }\n let tags: Set<number>;\n if (!this.tags.has(changeTree)) {\n tags = new Set<number>();\n this.tags.set(changeTree, tags);\n } else {\n tags = this.tags.get(changeTree);\n }\n tags.add(tag);\n\n // Ref: add tagged properties\n metadata?.[$fieldIndexesByViewTag]?.[tag]?.forEach((index) => {\n if (changeTree.getChange(index) !== OPERATION.DELETE) {\n changes[index] = OPERATION.ADD;\n }\n });\n\n } else if (!changeTree.isNew || isChildAdded) {\n // new structures will be added as part of .encode() call, no need to force it to .encodeView()\n const changeSet = (changeTree.filteredChanges !== undefined)\n ? changeTree.allFilteredChanges\n : changeTree.allChanges;\n\n const isInvisible = this.invisible.has(changeTree);\n\n for (let i = 0, len = changeSet.operations.length; i < len; i++) {\n const index = changeSet.operations[i];\n if (index === undefined) { continue; } // skip \"undefined\" indexes\n\n const op = changeTree.indexedOperations[index] ?? OPERATION.ADD;\n const tagAtIndex = metadata?.[index].tag;\n if (\n op !== OPERATION.DELETE &&\n (\n isInvisible || // if \"invisible\", include all\n tagAtIndex === undefined || // \"all change\" with no tag\n tagAtIndex === tag // tagged property\n )\n ) {\n changes[index] = op;\n isChildAdded = true; // FIXME: assign only once\n }\n }\n }\n\n return isChildAdded;\n }\n\n protected addParentOf(childChangeTree: ChangeTree, tag: number) {\n const changeTree = childChangeTree.parent[$changes];\n const parentIndex = childChangeTree.parentIndex;\n\n if (!this.visible.has(changeTree)) {\n // view must have all \"changeTree\" parent tree\n this.visible.add(changeTree);\n\n // add parent's parent\n const parentChangeTree: ChangeTree = changeTree.parent?.[$changes];\n if (parentChangeTree && (parentChangeTree.filteredChanges !== undefined)) {\n this.addParentOf(changeTree, tag);\n }\n\n // // parent is already available, no need to add it!\n // if (!this.invisible.has(changeTree)) { return; }\n }\n\n // add parent's tag properties\n if (changeTree.getChange(parentIndex) !== OPERATION.DELETE) {\n let changes = this.changes.get(changeTree.ref[$refId]);\n if (changes === undefined) {\n changes = {};\n this.changes.set(changeTree.ref[$refId], changes);\n }\n\n if (!this.tags) {\n this.tags = new WeakMap<ChangeTree, Set<number>>();\n }\n\n let tags: Set<number>;\n if (!this.tags.has(changeTree)) {\n tags = new Set<number>();\n this.tags.set(changeTree, tags);\n } else {\n tags = this.tags.get(changeTree);\n }\n tags.add(tag);\n\n changes[parentIndex] = OPERATION.ADD;\n }\n }\n\n remove(obj: Ref, tag?: number): this; // hide _isClear parameter from public API\n remove(obj: Ref, tag?: number, _isClear?: boolean): this;\n remove(obj: Ref, tag: number = DEFAULT_VIEW_TAG, _isClear: boolean = false): this {\n const changeTree: ChangeTree = obj[$changes];\n if (!changeTree) {\n console.warn(\"StateView#remove(), invalid object:\", obj);\n return this;\n }\n\n this.visible.delete(changeTree);\n\n // remove from iterable list\n if (\n this.iterable &&\n !_isClear // no need to remove during clear(), as it will be cleared entirely\n ) {\n spliceOne(this.items, this.items.indexOf(obj));\n }\n\n const ref = changeTree.ref;\n const metadata: Metadata = ref.constructor[Symbol.metadata]; // ArraySchema/MapSchema do not have metadata\n\n const refId = ref[$refId];\n\n let changes = this.changes.get(refId);\n if (changes === undefined) {\n changes = {};\n this.changes.set(refId, changes);\n }\n\n if (tag === DEFAULT_VIEW_TAG) {\n // parent is collection (Map/Array)\n const parent = changeTree.parent;\n if (parent && !Metadata.isValidInstance(parent) && changeTree.isFiltered) {\n const parentRefId = parent[$refId];\n let changes = this.changes.get(parentRefId);\n if (changes === undefined) {\n changes = {};\n this.changes.set(parentRefId, changes);\n\n } else if (changes[changeTree.parentIndex] === OPERATION.ADD) {\n //\n // SAME PATCH ADD + REMOVE:\n // The 'changes' of deleted structure should be ignored.\n //\n this.changes.delete(refId);\n }\n\n // DELETE / DELETE BY REF ID\n changes[changeTree.parentIndex] = OPERATION.DELETE;\n\n // Remove child schema from visible set\n this._recursiveDeleteVisibleChangeTree(changeTree);\n\n } else {\n // delete all \"tagged\" properties.\n metadata?.[$viewFieldIndexes]?.forEach((index) =>\n changes[index] = OPERATION.DELETE);\n }\n\n } else {\n // delete only tagged properties\n metadata?.[$fieldIndexesByViewTag][tag].forEach((index) =>\n changes[index] = OPERATION.DELETE);\n }\n\n // remove tag\n if (this.tags && this.tags.has(changeTree)) {\n const tags = this.tags.get(changeTree);\n if (tag === undefined) {\n // delete all tags\n this.tags.delete(changeTree);\n } else {\n // delete specific tag\n tags.delete(tag);\n\n // if tag set is empty, delete it entirely\n if (tags.size === 0) {\n this.tags.delete(changeTree);\n }\n }\n }\n\n return this;\n }\n\n has(obj: Ref) {\n return this.visible.has(obj[$changes]);\n }\n\n hasTag(ob: Ref, tag: number = DEFAULT_VIEW_TAG) {\n const tags = this.tags?.get(ob[$changes]);\n return tags?.has(tag) ?? false;\n }\n\n clear() {\n if (!this.iterable) {\n throw new Error(\"StateView#clear() is only available for iterable StateView's. Use StateView(iterable: true) constructor.\");\n }\n\n for (let i = 0, l = this.items.length; i < l; i++) {\n this.remove(this.items[i], DEFAULT_VIEW_TAG, true);\n }\n\n // clear items array\n this.items.length = 0;\n }\n\n isChangeTreeVisible(changeTree: ChangeTree) {\n let isVisible = this.visible.has(changeTree);\n\n //\n // TODO: avoid checking for parent visibility, most of the time it's not needed\n // See test case: 'should not be required to manually call view.add() items to child arrays without @view() tag'\n //\n if (!isVisible && changeTree.isVisibilitySharedWithParent){\n\n // console.log(\"CHECK AGAINST PARENT...\", {\n // ref: changeTree.ref.constructor.name,\n // refId: changeTree.ref[$refId],\n // parent: changeTree.parent.constructor.name,\n // });\n\n if (this.visible.has(changeTree.parent[$changes])) {\n this.visible.add(changeTree);\n isVisible = true;\n }\n }\n\n return isVisible;\n }\n\n protected _recursiveDeleteVisibleChangeTree(changeTree: ChangeTree) {\n changeTree.forEachChild((childChangeTree) => {\n this.visible.delete(childChangeTree);\n this._recursiveDeleteVisibleChangeTree(childChangeTree);\n });\n }\n}\n"]}
@@ -30,7 +30,7 @@ export interface Iterator {
30
30
  }
31
31
  declare function utf8Read(bytes: BufferLike, it: Iterator, length: number): string;
32
32
  declare function int8(bytes: BufferLike, it: Iterator): number;
33
- declare function uint8(bytes: BufferLike, it: Iterator): any;
33
+ declare function uint8(bytes: BufferLike, it: Iterator): number;
34
34
  declare function int16(bytes: BufferLike, it: Iterator): number;
35
35
  declare function uint16(bytes: BufferLike, it: Iterator): number;
36
36
  declare function int32(bytes: BufferLike, it: Iterator): number;
@@ -43,7 +43,7 @@ declare function bigint64(bytes: BufferLike, it: Iterator): bigint;
43
43
  declare function biguint64(bytes: BufferLike, it: Iterator): bigint;
44
44
  declare function boolean(bytes: BufferLike, it: Iterator): boolean;
45
45
  declare function string(bytes: BufferLike, it: Iterator): string;
46
- declare function number(bytes: BufferLike, it: Iterator): any;
46
+ declare function number(bytes: BufferLike, it: Iterator): number;
47
47
  export declare function stringCheck(bytes: BufferLike, it: Iterator): boolean;
48
48
  export declare const decode: {
49
49
  utf8Read: typeof utf8Read;
@@ -1,5 +1,7 @@
1
1
  import type { Iterator } from "./decode";
2
- export type BufferLike = number[] | ArrayBufferLike | Buffer;
2
+ export type BufferLike = ArrayLike<number> & {
3
+ [index: number]: number;
4
+ };
3
5
  declare function utf8Write(view: BufferLike, str: string, it: Iterator): void;
4
6
  declare function int8(bytes: BufferLike, value: number, it: Iterator): void;
5
7
  declare function uint8(bytes: BufferLike, value: number, it: Iterator): void;