@colyseus/schema 3.0.76 → 4.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build/cjs/index.js +781 -434
- package/build/cjs/index.js.map +1 -1
- package/build/esm/index.mjs +779 -435
- package/build/esm/index.mjs.map +1 -1
- package/build/umd/index.js +781 -434
- package/lib/Metadata.js +1 -5
- package/lib/Metadata.js.map +1 -1
- package/lib/Reflection.d.ts +50 -17
- package/lib/Reflection.js +151 -202
- package/lib/Reflection.js.map +1 -1
- package/lib/Schema.d.ts +13 -1
- package/lib/Schema.js +73 -9
- package/lib/Schema.js.map +1 -1
- package/lib/annotations.d.ts +6 -1
- package/lib/annotations.js +8 -34
- package/lib/annotations.js.map +1 -1
- package/lib/bench_encode.js +34 -1
- package/lib/bench_encode.js.map +1 -1
- package/lib/codegen/api.js +35 -2
- package/lib/codegen/api.js.map +1 -1
- package/lib/codegen/cli.js +4 -1
- package/lib/codegen/cli.js.map +1 -1
- package/lib/codegen/parser.js +35 -2
- package/lib/codegen/parser.js.map +1 -1
- package/lib/codegen/types.js +34 -1
- package/lib/codegen/types.js.map +1 -1
- package/lib/decoder/DecodeOperation.d.ts +2 -2
- package/lib/decoder/DecodeOperation.js +3 -3
- package/lib/decoder/DecodeOperation.js.map +1 -1
- package/lib/decoder/Decoder.d.ts +3 -3
- package/lib/decoder/Decoder.js +2 -2
- package/lib/decoder/Decoder.js.map +1 -1
- package/lib/decoder/ReferenceTracker.d.ts +0 -1
- package/lib/decoder/ReferenceTracker.js +9 -7
- package/lib/decoder/ReferenceTracker.js.map +1 -1
- package/lib/decoder/strategy/Callbacks.d.ts +154 -0
- package/lib/decoder/strategy/Callbacks.js +340 -0
- package/lib/decoder/strategy/Callbacks.js.map +1 -0
- package/lib/decoder/strategy/{StateCallbacks.d.ts → getDecoderStateCallbacks.d.ts} +6 -0
- package/lib/decoder/strategy/{StateCallbacks.js → getDecoderStateCallbacks.js} +17 -10
- package/lib/decoder/strategy/getDecoderStateCallbacks.js.map +1 -0
- package/lib/encoder/ChangeTree.d.ts +2 -2
- package/lib/encoder/ChangeTree.js.map +1 -1
- package/lib/encoder/EncodeOperation.d.ts +2 -2
- package/lib/encoder/EncodeOperation.js +3 -3
- package/lib/encoder/EncodeOperation.js.map +1 -1
- package/lib/encoder/Encoder.d.ts +6 -6
- package/lib/encoder/Encoder.js +19 -18
- package/lib/encoder/Encoder.js.map +1 -1
- package/lib/encoder/Root.js +17 -14
- package/lib/encoder/Root.js.map +1 -1
- package/lib/encoder/StateView.js +13 -12
- package/lib/encoder/StateView.js.map +1 -1
- package/lib/encoding/decode.d.ts +2 -2
- package/lib/encoding/encode.d.ts +3 -1
- package/lib/encoding/encode.js.map +1 -1
- package/lib/index.d.ts +3 -2
- package/lib/index.js +7 -3
- package/lib/index.js.map +1 -1
- package/lib/types/HelperTypes.d.ts +7 -14
- package/lib/types/HelperTypes.js.map +1 -1
- package/lib/types/custom/ArraySchema.d.ts +2 -1
- package/lib/types/custom/ArraySchema.js.map +1 -1
- package/lib/types/custom/CollectionSchema.d.ts +2 -1
- package/lib/types/custom/CollectionSchema.js.map +1 -1
- package/lib/types/custom/MapSchema.d.ts +3 -2
- package/lib/types/custom/MapSchema.js.map +1 -1
- package/lib/types/custom/SetSchema.d.ts +2 -1
- package/lib/types/custom/SetSchema.js.map +1 -1
- package/lib/types/symbols.d.ts +1 -0
- package/lib/types/symbols.js +2 -1
- package/lib/types/symbols.js.map +1 -1
- package/lib/utils.js +1 -1
- package/lib/utils.js.map +1 -1
- package/package.json +12 -16
- package/src/Metadata.ts +1 -5
- package/src/Reflection.ts +185 -174
- package/src/Schema.ts +81 -13
- package/src/annotations.ts +14 -40
- package/src/codegen/parser.ts +1 -1
- package/src/decoder/DecodeOperation.ts +9 -9
- package/src/decoder/Decoder.ts +6 -6
- package/src/decoder/ReferenceTracker.ts +10 -8
- package/src/decoder/strategy/Callbacks.ts +547 -0
- package/src/decoder/strategy/{StateCallbacks.ts → getDecoderStateCallbacks.ts} +17 -11
- package/src/encoder/ChangeTree.ts +4 -7
- package/src/encoder/EncodeOperation.ts +9 -9
- package/src/encoder/Encoder.ts +26 -18
- package/src/encoder/Root.ts +20 -15
- package/src/encoder/StateView.ts +15 -13
- package/src/encoding/encode.ts +1 -1
- package/src/index.ts +3 -2
- package/src/types/HelperTypes.ts +13 -11
- package/src/types/custom/ArraySchema.ts +2 -1
- package/src/types/custom/CollectionSchema.ts +4 -2
- package/src/types/custom/MapSchema.ts +4 -2
- package/src/types/custom/SetSchema.ts +3 -1
- package/src/types/symbols.ts +1 -0
- package/src/utils.ts +2 -2
- package/lib/Decoder.d.ts +0 -16
- package/lib/Decoder.js +0 -182
- package/lib/Decoder.js.map +0 -1
- package/lib/Encoder.d.ts +0 -13
- package/lib/Encoder.js +0 -79
- package/lib/Encoder.js.map +0 -1
- package/lib/changes/ChangeSet.d.ts +0 -12
- package/lib/changes/ChangeSet.js +0 -35
- package/lib/changes/ChangeSet.js.map +0 -1
- package/lib/changes/ChangeTree.d.ts +0 -53
- package/lib/changes/ChangeTree.js +0 -202
- package/lib/changes/ChangeTree.js.map +0 -1
- package/lib/changes/DecodeOperation.d.ts +0 -15
- package/lib/changes/DecodeOperation.js +0 -186
- package/lib/changes/DecodeOperation.js.map +0 -1
- package/lib/changes/EncodeOperation.d.ts +0 -18
- package/lib/changes/EncodeOperation.js +0 -130
- package/lib/changes/EncodeOperation.js.map +0 -1
- package/lib/changes/ReferenceTracker.d.ts +0 -14
- package/lib/changes/ReferenceTracker.js +0 -83
- package/lib/changes/ReferenceTracker.js.map +0 -1
- package/lib/changes/consts.d.ts +0 -14
- package/lib/changes/consts.js +0 -18
- package/lib/changes/consts.js.map +0 -1
- package/lib/decoder/strategy/StateCallbacks.js.map +0 -1
- package/lib/decoding/decode.d.ts +0 -48
- package/lib/decoding/decode.js +0 -267
- package/lib/decoding/decode.js.map +0 -1
- package/lib/ecs.d.ts +0 -11
- package/lib/ecs.js +0 -160
- package/lib/ecs.js.map +0 -1
- package/lib/filters/index.d.ts +0 -8
- package/lib/filters/index.js +0 -24
- package/lib/filters/index.js.map +0 -1
- package/lib/spec.d.ts +0 -13
- package/lib/spec.js +0 -42
- package/lib/spec.js.map +0 -1
- package/lib/types/ArraySchema.d.ts +0 -238
- package/lib/types/ArraySchema.js +0 -555
- package/lib/types/ArraySchema.js.map +0 -1
- package/lib/types/CollectionSchema.d.ts +0 -35
- package/lib/types/CollectionSchema.js +0 -150
- package/lib/types/CollectionSchema.js.map +0 -1
- package/lib/types/MapSchema.d.ts +0 -38
- package/lib/types/MapSchema.js +0 -215
- package/lib/types/MapSchema.js.map +0 -1
- package/lib/types/SetSchema.d.ts +0 -32
- package/lib/types/SetSchema.js +0 -162
- package/lib/types/SetSchema.js.map +0 -1
- package/lib/types/typeRegistry.d.ts +0 -5
- package/lib/types/typeRegistry.js +0 -13
- package/lib/types/typeRegistry.js.map +0 -1
- package/lib/usage.d.ts +0 -1
- package/lib/usage.js +0 -22
- package/lib/usage.js.map +0 -1
- package/lib/v3.d.ts +0 -1
- package/lib/v3.js +0 -427
- package/lib/v3.js.map +0 -1
- package/lib/v3_experiment.d.ts +0 -1
- package/lib/v3_experiment.js +0 -407
- package/lib/v3_experiment.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ChangeTree.js","sourceRoot":"","sources":["../../src/encoder/ChangeTree.ts"],"names":[],"mappings":"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","sourcesContent":["import { OPERATION } from \"../encoding/spec\";\nimport { Schema } from \"../Schema\";\nimport { $changes, $childType, $decoder, $onEncodeEnd, $encoder, $getByIndex, $refTypeFieldIndexes, $viewFieldIndexes, type $deleteByIndex } from \"../types/symbols\";\n\nimport type { MapSchema } from \"../types/custom/MapSchema\";\nimport type { ArraySchema } from \"../types/custom/ArraySchema\";\nimport type { CollectionSchema } from \"../types/custom/CollectionSchema\";\nimport type { SetSchema } from \"../types/custom/SetSchema\";\n\nimport { Root } from \"./Root\";\nimport { Metadata } from \"../Metadata\";\nimport type { EncodeOperation } from \"./EncodeOperation\";\nimport type { DecodeOperation } from \"../decoder/DecodeOperation\";\n\ndeclare global {\n interface Object {\n // FIXME: not a good practice to extend globals here\n [$changes]?: ChangeTree;\n [$encoder]?: EncodeOperation,\n [$decoder]?: DecodeOperation,\n }\n}\n\nexport interface IRef {\n [$changes]?: ChangeTree;\n [$getByIndex]?: (index: number, isEncodeAll?: boolean) => any;\n [$deleteByIndex]?: (index: number) => void;\n}\n\nexport type Ref = Schema\n | ArraySchema\n | MapSchema\n | CollectionSchema\n | SetSchema;\n\nexport type ChangeSetName = \"changes\"\n | \"allChanges\"\n | \"filteredChanges\"\n | \"allFilteredChanges\";\n\nexport interface IndexedOperations {\n [index: number]: OPERATION;\n}\n\n// Linked list node for change trees\nexport interface ChangeTreeNode {\n changeTree: ChangeTree;\n next?: ChangeTreeNode;\n prev?: ChangeTreeNode;\n position: number; // Cached position in the linked list for O(1) lookup\n}\n\n// Linked list for change trees\nexport interface ChangeTreeList {\n next?: ChangeTreeNode;\n tail?: ChangeTreeNode;\n}\n\nexport interface ChangeSet {\n // field index -> operation index\n indexes: { [index: number]: number };\n operations: number[];\n queueRootNode?: ChangeTreeNode; // direct reference to ChangeTreeNode in the linked list\n}\n\nfunction createChangeSet(queueRootNode?: ChangeTreeNode): ChangeSet {\n return { indexes: {}, operations: [], queueRootNode };\n}\n\n// Linked list helper functions\nexport function createChangeTreeList(): ChangeTreeList {\n return { next: undefined, tail: undefined };\n}\n\nexport function setOperationAtIndex(changeSet: ChangeSet, index: number) {\n const operationsIndex = changeSet.indexes[index];\n if (operationsIndex === undefined) {\n changeSet.indexes[index] = changeSet.operations.push(index) - 1;\n } else {\n changeSet.operations[operationsIndex] = index;\n }\n}\n\nexport function deleteOperationAtIndex(changeSet: ChangeSet, index: number | string) {\n let operationsIndex = changeSet.indexes[index as any as number];\n if (operationsIndex === undefined) {\n //\n // if index is not found, we need to find the last operation\n // FIXME: this is not very efficient\n //\n // > See \"should allow consecutive splices (same place)\" tests\n //\n operationsIndex = Object.values(changeSet.indexes).at(-1);\n index = Object.entries(changeSet.indexes).find(([_, value]) => value === operationsIndex)?.[0];\n }\n changeSet.operations[operationsIndex] = undefined;\n delete changeSet.indexes[index as any as number];\n}\n\nexport function debugChangeSet(label: string, changeSet: ChangeSet) {\n let indexes: string[] = [];\n let operations: string[] = [];\n\n for (const index in changeSet.indexes) {\n indexes.push(`\\t${index} => [${changeSet.indexes[index]}]`);\n }\n\n for (let i = 0; i < changeSet.operations.length; i++) {\n const index = changeSet.operations[i];\n if (index !== undefined) {\n operations.push(`\\t[${i}] => ${index}`);\n }\n }\n\n console.log(`${label} =>\\nindexes (${Object.keys(changeSet.indexes).length}) {`);\n console.log(indexes.join(\"\\n\"), \"\\n}\");\n console.log(`operations (${changeSet.operations.filter(op => op !== undefined).length}) {`);\n console.log(operations.join(\"\\n\"), \"\\n}\");\n}\n\nexport interface ParentChain {\n ref: Ref;\n index: number;\n next?: ParentChain;\n}\n\nexport class ChangeTree<T extends Ref = any> {\n ref: T;\n refId: number;\n metadata: Metadata;\n\n root?: Root;\n parentChain?: ParentChain; // Linked list for tracking parents\n\n /**\n * Whether this structure is parent of a filtered structure.\n */\n isFiltered: boolean = false;\n isVisibilitySharedWithParent?: boolean; // See test case: 'should not be required to manually call view.add() items to child arrays without @view() tag'\n\n indexedOperations: IndexedOperations = {};\n\n //\n // TODO:\n // try storing the index + operation per item.\n // example: 1024 & 1025 => ADD, 1026 => DELETE\n //\n // => https://chatgpt.com/share/67107d0c-bc20-8004-8583-83b17dd7c196\n //\n changes: ChangeSet = { indexes: {}, operations: [] };\n allChanges: ChangeSet = { indexes: {}, operations: [] };\n filteredChanges: ChangeSet;\n allFilteredChanges: ChangeSet;\n\n indexes: { [index: string]: any }; // TODO: remove this, only used by MapSchema/SetSchema/CollectionSchema (`encodeKeyValueOperation`)\n\n /**\n * Is this a new instance? Used on ArraySchema to determine OPERATION.MOVE_AND_ADD operation.\n */\n isNew = true;\n\n constructor(ref: T) {\n this.ref = ref;\n this.metadata = (ref.constructor as typeof Schema)[Symbol.metadata];\n\n //\n // Does this structure have \"filters\" declared?\n //\n if (this.metadata?.[$viewFieldIndexes]) {\n this.allFilteredChanges = { indexes: {}, operations: [] };\n this.filteredChanges = { indexes: {}, operations: [] };\n }\n }\n\n setRoot(root: Root) {\n this.root = root;\n\n const isNewChangeTree = this.root.add(this);\n\n this.checkIsFiltered(this.parent, this.parentIndex, isNewChangeTree);\n\n // Recursively set root on child structures\n if (isNewChangeTree) {\n this.forEachChild((child, _) => {\n if (child.root !== root) {\n child.setRoot(root);\n } else {\n root.add(child); // increment refCount\n }\n });\n }\n }\n\n setParent(\n parent: Ref,\n root?: Root,\n parentIndex?: number,\n ) {\n this.addParent(parent, parentIndex);\n\n // avoid setting parents with empty `root`\n if (!root) { return; }\n\n const isNewChangeTree = root.add(this);\n\n // skip if parent is already set\n if (root !== this.root) {\n this.root = root;\n this.checkIsFiltered(parent, parentIndex, isNewChangeTree);\n }\n\n // assign same parent on child structures\n if (isNewChangeTree) {\n //\n // assign same parent on child structures\n //\n this.forEachChild((child, index) => {\n if (child.root === root) {\n //\n // re-assigning a child of the same root, move it next to parent\n // so encoding order is preserved\n //\n root.add(child);\n root.moveNextToParent(child);\n return;\n }\n child.setParent(this.ref, root, index);\n });\n }\n }\n\n forEachChild(callback: (change: ChangeTree, at: any) => void) {\n //\n // assign same parent on child structures\n //\n if ((this.ref as any)[$childType]) {\n if (typeof ((this.ref as any)[$childType]) !== \"string\") {\n // MapSchema / ArraySchema, etc.\n for (const [key, value] of (this.ref as MapSchema).entries()) {\n if (!value) { continue; } // sparse arrays can have undefined values\n callback(value[$changes], this.indexes?.[key] ?? key);\n };\n }\n\n } else {\n for (const index of this.metadata?.[$refTypeFieldIndexes] ?? []) {\n const field = this.metadata[index as any as number];\n const value = this.ref[field.name as keyof Ref];\n if (!value) { continue; }\n callback(value[$changes], index);\n }\n }\n }\n\n operation(op: OPERATION) {\n // operations without index use negative values to represent them\n // this is checked during .encode() time.\n if (this.filteredChanges !== undefined) {\n this.filteredChanges.operations.push(-op);\n this.root?.enqueueChangeTree(this, 'filteredChanges');\n\n } else {\n this.changes.operations.push(-op);\n this.root?.enqueueChangeTree(this, 'changes');\n }\n }\n\n change(index: number, operation: OPERATION = OPERATION.ADD) {\n const isFiltered = this.isFiltered || (this.metadata?.[index]?.tag !== undefined);\n const changeSet = (isFiltered)\n ? this.filteredChanges\n : this.changes;\n\n const previousOperation = this.indexedOperations[index];\n if (!previousOperation || previousOperation === OPERATION.DELETE) {\n const op = (!previousOperation)\n ? operation\n : (previousOperation === OPERATION.DELETE)\n ? OPERATION.DELETE_AND_ADD\n : operation\n //\n // TODO: are DELETE operations being encoded as ADD here ??\n //\n this.indexedOperations[index] = op;\n }\n\n setOperationAtIndex(changeSet, index);\n\n if (isFiltered) {\n setOperationAtIndex(this.allFilteredChanges, index);\n\n if (this.root) {\n this.root.enqueueChangeTree(this, 'filteredChanges');\n this.root.enqueueChangeTree(this, 'allFilteredChanges');\n }\n\n } else {\n setOperationAtIndex(this.allChanges, index);\n this.root?.enqueueChangeTree(this, 'changes');\n }\n }\n\n shiftChangeIndexes(shiftIndex: number) {\n //\n // Used only during:\n //\n // - ArraySchema#unshift()\n //\n const changeSet = (this.isFiltered)\n ? this.filteredChanges\n : this.changes;\n\n const newIndexedOperations: any = {};\n const newIndexes: { [index: number]: number } = {};\n for (const index in this.indexedOperations) {\n newIndexedOperations[Number(index) + shiftIndex] = this.indexedOperations[index];\n newIndexes[Number(index) + shiftIndex] = changeSet.indexes[index];\n }\n this.indexedOperations = newIndexedOperations;\n changeSet.indexes = newIndexes;\n\n changeSet.operations = changeSet.operations.map((index) => index + shiftIndex);\n }\n\n shiftAllChangeIndexes(shiftIndex: number, startIndex: number = 0) {\n //\n // Used only during:\n //\n // - ArraySchema#splice()\n //\n if (this.filteredChanges !== undefined) {\n this._shiftAllChangeIndexes(shiftIndex, startIndex, this.allFilteredChanges);\n this._shiftAllChangeIndexes(shiftIndex, startIndex, this.allChanges);\n\n } else {\n this._shiftAllChangeIndexes(shiftIndex, startIndex, this.allChanges);\n }\n }\n\n private _shiftAllChangeIndexes(shiftIndex: number, startIndex: number = 0, changeSet: ChangeSet) {\n const newIndexes: { [index: number]: number } = {};\n let newKey = 0;\n for (const key in changeSet.indexes) {\n newIndexes[newKey++] = changeSet.indexes[key];\n }\n changeSet.indexes = newIndexes;\n\n for (let i = 0; i < changeSet.operations.length; i++) {\n const index = changeSet.operations[i];\n if (index > startIndex) {\n changeSet.operations[i] = index + shiftIndex;\n }\n }\n }\n\n indexedOperation(index: number, operation: OPERATION, allChangesIndex: number = index) {\n this.indexedOperations[index] = operation;\n\n if (this.filteredChanges !== undefined) {\n setOperationAtIndex(this.allFilteredChanges, allChangesIndex);\n setOperationAtIndex(this.filteredChanges, index);\n this.root?.enqueueChangeTree(this, 'filteredChanges');\n\n } else {\n setOperationAtIndex(this.allChanges, allChangesIndex);\n setOperationAtIndex(this.changes, index);\n this.root?.enqueueChangeTree(this, 'changes');\n }\n }\n\n getType(index?: number) {\n return (\n //\n // Get the child type from parent structure.\n // - [\"string\"] => \"string\"\n // - { map: \"string\" } => \"string\"\n // - { set: \"string\" } => \"string\"\n //\n (this.ref as any)[$childType] || // ArraySchema | MapSchema | SetSchema | CollectionSchema\n this.metadata[index].type // Schema\n );\n }\n\n getChange(index: number) {\n return this.indexedOperations[index];\n }\n\n //\n // used during `.encode()`\n //\n getValue(index: number, isEncodeAll: boolean = false) {\n //\n // `isEncodeAll` param is only used by ArraySchema\n //\n return (this.ref as any)[$getByIndex](index, isEncodeAll);\n }\n\n delete(index: number, operation?: OPERATION, allChangesIndex = index) {\n if (index === undefined) {\n try {\n throw new Error(`@colyseus/schema ${this.ref.constructor.name}: trying to delete non-existing index '${index}'`);\n } catch (e) {\n console.warn(e);\n }\n return;\n }\n\n const changeSet = (this.filteredChanges !== undefined)\n ? this.filteredChanges\n : this.changes;\n\n this.indexedOperations[index] = operation ?? OPERATION.DELETE;\n setOperationAtIndex(changeSet, index);\n deleteOperationAtIndex(this.allChanges, allChangesIndex);\n\n const previousValue = this.getValue(index);\n\n // remove `root` reference\n if (previousValue && previousValue[$changes]) {\n //\n // FIXME: this.root is \"undefined\"\n //\n // This method is being called at decoding time when a DELETE operation is found.\n //\n // - This is due to using the concrete Schema class at decoding time.\n // - \"Reflected\" structures do not have this problem.\n //\n // (The property descriptors should NOT be used at decoding time. only at encoding time.)\n //\n this.root?.remove(previousValue[$changes]);\n }\n\n //\n // FIXME: this is looking a ugly and repeated\n //\n if (this.filteredChanges !== undefined) {\n deleteOperationAtIndex(this.allFilteredChanges, allChangesIndex);\n this.root?.enqueueChangeTree(this, 'filteredChanges');\n\n } else {\n this.root?.enqueueChangeTree(this, 'changes');\n }\n\n return previousValue;\n }\n\n endEncode(changeSetName: ChangeSetName) {\n this.indexedOperations = {};\n\n // clear changeset\n this[changeSetName] = createChangeSet();\n\n // ArraySchema and MapSchema have a custom \"encode end\" method\n (this.ref as any)[$onEncodeEnd]?.();\n\n // Not a new instance anymore\n this.isNew = false;\n }\n\n discard(discardAll: boolean = false) {\n //\n // > MapSchema:\n // Remove cached key to ensure ADD operations is unsed instead of\n // REPLACE in case same key is used on next patches.\n //\n (this.ref as any)[$onEncodeEnd]?.();\n\n this.indexedOperations = {};\n this.changes = createChangeSet(this.changes.queueRootNode);\n\n if (this.filteredChanges !== undefined) {\n this.filteredChanges = createChangeSet(this.filteredChanges.queueRootNode);\n }\n\n if (discardAll) {\n // preserve queueRootNode references\n this.allChanges = createChangeSet(this.allChanges.queueRootNode);\n\n if (this.allFilteredChanges !== undefined) {\n this.allFilteredChanges = createChangeSet(this.allFilteredChanges.queueRootNode);\n }\n }\n }\n\n /**\n * Recursively discard all changes from this, and child structures.\n * (Used in tests only)\n */\n discardAll() {\n const keys = Object.keys(this.indexedOperations);\n for (let i = 0, len = keys.length; i < len; i++) {\n const value = this.getValue(Number(keys[i]));\n\n if (value && value[$changes]) {\n value[$changes].discardAll();\n }\n }\n\n this.discard();\n }\n\n get changed() {\n return (Object.entries(this.indexedOperations).length > 0);\n }\n\n protected checkIsFiltered(parent: Ref, parentIndex: number, isNewChangeTree: boolean) {\n if (this.root.types.hasFilters) {\n //\n // At Schema initialization, the \"root\" structure might not be available\n // yet, as it only does once the \"Encoder\" has been set up.\n //\n // So the \"parent\" may be already set without a \"root\".\n //\n this._checkFilteredByParent(parent, parentIndex);\n\n if (this.filteredChanges !== undefined) {\n this.root?.enqueueChangeTree(this, 'filteredChanges');\n\n if (isNewChangeTree) {\n this.root?.enqueueChangeTree(this, 'allFilteredChanges');\n }\n }\n }\n\n if (!this.isFiltered) {\n this.root?.enqueueChangeTree(this, 'changes');\n\n if (isNewChangeTree) {\n this.root?.enqueueChangeTree(this, 'allChanges');\n }\n }\n }\n\n protected _checkFilteredByParent(parent: Ref, parentIndex: number) {\n // skip if parent is not set\n if (!parent) { return; }\n\n //\n // ArraySchema | MapSchema - get the child type\n // (if refType is typeof string, the parentFiltered[key] below will always be invalid)\n //\n const refType = Metadata.isValidInstance(this.ref)\n ? this.ref.constructor\n : (this.ref as any)[$childType];\n\n let parentChangeTree: ChangeTree;\n\n let parentIsCollection = !Metadata.isValidInstance(parent);\n if (parentIsCollection) {\n parentChangeTree = parent[$changes];\n parent = parentChangeTree.parent;\n parentIndex = parentChangeTree.parentIndex;\n\n } else {\n parentChangeTree = parent[$changes]\n }\n\n const parentConstructor = parent.constructor as typeof Schema;\n\n let key = `${this.root.types.getTypeId(refType as typeof Schema)}`;\n if (parentConstructor) {\n key += `-${this.root.types.schemas.get(parentConstructor)}`;\n }\n key += `-${parentIndex}`;\n\n const fieldHasViewTag = Metadata.hasViewTagAtIndex(parentConstructor?.[Symbol.metadata], parentIndex);\n\n this.isFiltered = parent[$changes].isFiltered // in case parent is already filtered\n || this.root.types.parentFiltered[key]\n || fieldHasViewTag;\n\n //\n // \"isFiltered\" may not be imedialely available during `change()` due to the instance not being attached to the root yet.\n // when it's available, we need to enqueue the \"changes\" changeset into the \"filteredChanges\" changeset.\n //\n if (this.isFiltered) {\n\n this.isVisibilitySharedWithParent = (\n parentChangeTree.isFiltered &&\n typeof (refType) !== \"string\" &&\n !fieldHasViewTag &&\n parentIsCollection\n );\n\n if (!this.filteredChanges) {\n this.filteredChanges = createChangeSet();\n this.allFilteredChanges = createChangeSet();\n }\n\n if (this.changes.operations.length > 0) {\n this.changes.operations.forEach((index) =>\n setOperationAtIndex(this.filteredChanges, index));\n\n this.allChanges.operations.forEach((index) =>\n setOperationAtIndex(this.allFilteredChanges, index));\n\n this.changes = createChangeSet();\n this.allChanges = createChangeSet();\n }\n }\n }\n\n /**\n * Get the immediate parent\n */\n get parent(): Ref | undefined {\n return this.parentChain?.ref;\n }\n\n /**\n * Get the immediate parent index\n */\n get parentIndex(): number | undefined {\n return this.parentChain?.index;\n }\n\n /**\n * Add a parent to the chain\n */\n addParent(parent: Ref, index: number) {\n // Check if this parent already exists in the chain\n if (this.hasParent((p, _) => p[$changes] === parent[$changes])) {\n // if (this.hasParent((p, i) => p[$changes] === parent[$changes] && i === index)) {\n this.parentChain.index = index;\n return;\n }\n\n this.parentChain = {\n ref: parent,\n index,\n next: this.parentChain\n };\n }\n\n /**\n * Remove a parent from the chain\n * @param parent - The parent to remove\n * @returns true if parent was removed\n */\n removeParent(parent: Ref = this.parent): boolean {\n let current = this.parentChain;\n let previous = null;\n while (current) {\n //\n // FIXME: it is required to check against `$changes` here because\n // ArraySchema is instance of Proxy\n //\n if (current.ref[$changes] === parent[$changes]) {\n if (previous) {\n previous.next = current.next;\n } else {\n this.parentChain = current.next;\n }\n return true;\n }\n previous = current;\n current = current.next;\n }\n return this.parentChain === undefined;\n }\n\n /**\n * Find a specific parent in the chain\n */\n findParent(predicate: (parent: Ref, index: number) => boolean): ParentChain | undefined {\n let current = this.parentChain;\n while (current) {\n if (predicate(current.ref, current.index)) {\n return current;\n }\n current = current.next;\n }\n return undefined;\n }\n\n /**\n * Check if this ChangeTree has a specific parent\n */\n hasParent(predicate: (parent: Ref, index: number) => boolean): boolean {\n return this.findParent(predicate) !== undefined;\n }\n\n /**\n * Get all parents as an array (for debugging/testing)\n */\n getAllParents(): Array<{ ref: Ref, index: number }> {\n const parents: Array<{ ref: Ref, index: number }> = [];\n let current = this.parentChain;\n while (current) {\n parents.push({ ref: current.ref, index: current.index });\n current = current.next;\n }\n return parents;\n }\n\n}\n"]}
|
|
1
|
+
{"version":3,"file":"ChangeTree.js","sourceRoot":"","sources":["../../src/encoder/ChangeTree.ts"],"names":[],"mappings":"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","sourcesContent":["import { OPERATION } from \"../encoding/spec\";\nimport { Schema } from \"../Schema\";\nimport { $changes, $childType, $decoder, $onEncodeEnd, $encoder, $getByIndex, $refId, $refTypeFieldIndexes, $viewFieldIndexes, type $deleteByIndex } from \"../types/symbols\";\n\nimport type { MapSchema } from \"../types/custom/MapSchema\";\nimport type { ArraySchema } from \"../types/custom/ArraySchema\";\nimport type { CollectionSchema } from \"../types/custom/CollectionSchema\";\nimport type { SetSchema } from \"../types/custom/SetSchema\";\n\nimport { Root } from \"./Root\";\nimport { Metadata } from \"../Metadata\";\nimport type { EncodeOperation } from \"./EncodeOperation\";\nimport type { DecodeOperation } from \"../decoder/DecodeOperation\";\n\ndeclare global {\n interface Object {\n // FIXME: not a good practice to extend globals here\n [$changes]?: ChangeTree;\n // [$refId]?: number;\n [$encoder]?: EncodeOperation,\n [$decoder]?: DecodeOperation,\n }\n}\n\nexport interface IRef {\n [$changes]?: ChangeTree;\n [$refId]?: number;\n [$getByIndex]?: (index: number, isEncodeAll?: boolean) => any;\n [$deleteByIndex]?: (index: number) => void;\n}\n\nexport type Ref = Schema | ArraySchema | MapSchema | CollectionSchema | SetSchema;\n\nexport type ChangeSetName = \"changes\"\n | \"allChanges\"\n | \"filteredChanges\"\n | \"allFilteredChanges\";\n\nexport interface IndexedOperations {\n [index: number]: OPERATION;\n}\n\n// Linked list node for change trees\nexport interface ChangeTreeNode {\n changeTree: ChangeTree;\n next?: ChangeTreeNode;\n prev?: ChangeTreeNode;\n position: number; // Cached position in the linked list for O(1) lookup\n}\n\n// Linked list for change trees\nexport interface ChangeTreeList {\n next?: ChangeTreeNode;\n tail?: ChangeTreeNode;\n}\n\nexport interface ChangeSet {\n // field index -> operation index\n indexes: { [index: number]: number };\n operations: number[];\n queueRootNode?: ChangeTreeNode; // direct reference to ChangeTreeNode in the linked list\n}\n\nfunction createChangeSet(queueRootNode?: ChangeTreeNode): ChangeSet {\n return { indexes: {}, operations: [], queueRootNode };\n}\n\n// Linked list helper functions\nexport function createChangeTreeList(): ChangeTreeList {\n return { next: undefined, tail: undefined };\n}\n\nexport function setOperationAtIndex(changeSet: ChangeSet, index: number) {\n const operationsIndex = changeSet.indexes[index];\n if (operationsIndex === undefined) {\n changeSet.indexes[index] = changeSet.operations.push(index) - 1;\n } else {\n changeSet.operations[operationsIndex] = index;\n }\n}\n\nexport function deleteOperationAtIndex(changeSet: ChangeSet, index: number | string) {\n let operationsIndex = changeSet.indexes[index as any as number];\n if (operationsIndex === undefined) {\n //\n // if index is not found, we need to find the last operation\n // FIXME: this is not very efficient\n //\n // > See \"should allow consecutive splices (same place)\" tests\n //\n operationsIndex = Object.values(changeSet.indexes).at(-1);\n index = Object.entries(changeSet.indexes).find(([_, value]) => value === operationsIndex)?.[0];\n }\n changeSet.operations[operationsIndex] = undefined;\n delete changeSet.indexes[index as any as number];\n}\n\nexport function debugChangeSet(label: string, changeSet: ChangeSet) {\n let indexes: string[] = [];\n let operations: string[] = [];\n\n for (const index in changeSet.indexes) {\n indexes.push(`\\t${index} => [${changeSet.indexes[index]}]`);\n }\n\n for (let i = 0; i < changeSet.operations.length; i++) {\n const index = changeSet.operations[i];\n if (index !== undefined) {\n operations.push(`\\t[${i}] => ${index}`);\n }\n }\n\n console.log(`${label} =>\\nindexes (${Object.keys(changeSet.indexes).length}) {`);\n console.log(indexes.join(\"\\n\"), \"\\n}\");\n console.log(`operations (${changeSet.operations.filter(op => op !== undefined).length}) {`);\n console.log(operations.join(\"\\n\"), \"\\n}\");\n}\n\nexport interface ParentChain {\n ref: Ref;\n index: number;\n next?: ParentChain;\n}\n\nexport class ChangeTree<T extends Ref = any> {\n ref: T;\n metadata: Metadata;\n\n root?: Root;\n parentChain?: ParentChain; // Linked list for tracking parents\n\n /**\n * Whether this structure is parent of a filtered structure.\n */\n isFiltered: boolean = false;\n isVisibilitySharedWithParent?: boolean; // See test case: 'should not be required to manually call view.add() items to child arrays without @view() tag'\n\n indexedOperations: IndexedOperations = {};\n\n //\n // TODO:\n // try storing the index + operation per item.\n // example: 1024 & 1025 => ADD, 1026 => DELETE\n //\n // => https://chatgpt.com/share/67107d0c-bc20-8004-8583-83b17dd7c196\n //\n changes: ChangeSet = { indexes: {}, operations: [] };\n allChanges: ChangeSet = { indexes: {}, operations: [] };\n filteredChanges: ChangeSet;\n allFilteredChanges: ChangeSet;\n\n indexes: { [index: string]: any }; // TODO: remove this, only used by MapSchema/SetSchema/CollectionSchema (`encodeKeyValueOperation`)\n\n /**\n * Is this a new instance? Used on ArraySchema to determine OPERATION.MOVE_AND_ADD operation.\n */\n isNew = true;\n\n constructor(ref: T) {\n this.ref = ref;\n this.metadata = (ref.constructor as typeof Schema)[Symbol.metadata];\n\n //\n // Does this structure have \"filters\" declared?\n //\n if (this.metadata?.[$viewFieldIndexes]) {\n this.allFilteredChanges = { indexes: {}, operations: [] };\n this.filteredChanges = { indexes: {}, operations: [] };\n }\n }\n\n setRoot(root: Root) {\n this.root = root;\n\n const isNewChangeTree = this.root.add(this);\n\n this.checkIsFiltered(this.parent, this.parentIndex, isNewChangeTree);\n\n // Recursively set root on child structures\n if (isNewChangeTree) {\n this.forEachChild((child, _) => {\n if (child.root !== root) {\n child.setRoot(root);\n } else {\n root.add(child); // increment refCount\n }\n });\n }\n }\n\n setParent(\n parent: Ref,\n root?: Root,\n parentIndex?: number,\n ) {\n this.addParent(parent, parentIndex);\n\n // avoid setting parents with empty `root`\n if (!root) { return; }\n\n const isNewChangeTree = root.add(this);\n\n // skip if parent is already set\n if (root !== this.root) {\n this.root = root;\n this.checkIsFiltered(parent, parentIndex, isNewChangeTree);\n }\n\n // assign same parent on child structures\n if (isNewChangeTree) {\n //\n // assign same parent on child structures\n //\n this.forEachChild((child, index) => {\n if (child.root === root) {\n //\n // re-assigning a child of the same root, move it next to parent\n // so encoding order is preserved\n //\n root.add(child);\n root.moveNextToParent(child);\n return;\n }\n child.setParent(this.ref, root, index);\n });\n }\n }\n\n forEachChild(callback: (change: ChangeTree, at: any) => void) {\n //\n // assign same parent on child structures\n //\n if ((this.ref as any)[$childType]) {\n if (typeof ((this.ref as any)[$childType]) !== \"string\") {\n // MapSchema / ArraySchema, etc.\n for (const [key, value] of (this.ref as MapSchema).entries()) {\n if (!value) { continue; } // sparse arrays can have undefined values\n callback(value[$changes], this.indexes?.[key] ?? key);\n };\n }\n\n } else {\n for (const index of this.metadata?.[$refTypeFieldIndexes] ?? []) {\n const field = this.metadata[index as any as number];\n const value = this.ref[field.name as keyof Ref];\n if (!value) { continue; }\n callback(value[$changes], index);\n }\n }\n }\n\n operation(op: OPERATION) {\n // operations without index use negative values to represent them\n // this is checked during .encode() time.\n if (this.filteredChanges !== undefined) {\n this.filteredChanges.operations.push(-op);\n this.root?.enqueueChangeTree(this, 'filteredChanges');\n\n } else {\n this.changes.operations.push(-op);\n this.root?.enqueueChangeTree(this, 'changes');\n }\n }\n\n change(index: number, operation: OPERATION = OPERATION.ADD) {\n const isFiltered = this.isFiltered || (this.metadata?.[index]?.tag !== undefined);\n const changeSet = (isFiltered)\n ? this.filteredChanges\n : this.changes;\n\n const previousOperation = this.indexedOperations[index];\n if (!previousOperation || previousOperation === OPERATION.DELETE) {\n const op = (!previousOperation)\n ? operation\n : (previousOperation === OPERATION.DELETE)\n ? OPERATION.DELETE_AND_ADD\n : operation\n //\n // TODO: are DELETE operations being encoded as ADD here ??\n //\n this.indexedOperations[index] = op;\n }\n\n setOperationAtIndex(changeSet, index);\n\n if (isFiltered) {\n setOperationAtIndex(this.allFilteredChanges, index);\n\n if (this.root) {\n this.root.enqueueChangeTree(this, 'filteredChanges');\n this.root.enqueueChangeTree(this, 'allFilteredChanges');\n }\n\n } else {\n setOperationAtIndex(this.allChanges, index);\n this.root?.enqueueChangeTree(this, 'changes');\n }\n }\n\n shiftChangeIndexes(shiftIndex: number) {\n //\n // Used only during:\n //\n // - ArraySchema#unshift()\n //\n const changeSet = (this.isFiltered)\n ? this.filteredChanges\n : this.changes;\n\n const newIndexedOperations: any = {};\n const newIndexes: { [index: number]: number } = {};\n for (const index in this.indexedOperations) {\n newIndexedOperations[Number(index) + shiftIndex] = this.indexedOperations[index];\n newIndexes[Number(index) + shiftIndex] = changeSet.indexes[index];\n }\n this.indexedOperations = newIndexedOperations;\n changeSet.indexes = newIndexes;\n\n changeSet.operations = changeSet.operations.map((index) => index + shiftIndex);\n }\n\n shiftAllChangeIndexes(shiftIndex: number, startIndex: number = 0) {\n //\n // Used only during:\n //\n // - ArraySchema#splice()\n //\n if (this.filteredChanges !== undefined) {\n this._shiftAllChangeIndexes(shiftIndex, startIndex, this.allFilteredChanges);\n this._shiftAllChangeIndexes(shiftIndex, startIndex, this.allChanges);\n\n } else {\n this._shiftAllChangeIndexes(shiftIndex, startIndex, this.allChanges);\n }\n }\n\n private _shiftAllChangeIndexes(shiftIndex: number, startIndex: number = 0, changeSet: ChangeSet) {\n const newIndexes: { [index: number]: number } = {};\n let newKey = 0;\n for (const key in changeSet.indexes) {\n newIndexes[newKey++] = changeSet.indexes[key];\n }\n changeSet.indexes = newIndexes;\n\n for (let i = 0; i < changeSet.operations.length; i++) {\n const index = changeSet.operations[i];\n if (index > startIndex) {\n changeSet.operations[i] = index + shiftIndex;\n }\n }\n }\n\n indexedOperation(index: number, operation: OPERATION, allChangesIndex: number = index) {\n this.indexedOperations[index] = operation;\n\n if (this.filteredChanges !== undefined) {\n setOperationAtIndex(this.allFilteredChanges, allChangesIndex);\n setOperationAtIndex(this.filteredChanges, index);\n this.root?.enqueueChangeTree(this, 'filteredChanges');\n\n } else {\n setOperationAtIndex(this.allChanges, allChangesIndex);\n setOperationAtIndex(this.changes, index);\n this.root?.enqueueChangeTree(this, 'changes');\n }\n }\n\n getType(index?: number) {\n return (\n //\n // Get the child type from parent structure.\n // - [\"string\"] => \"string\"\n // - { map: \"string\" } => \"string\"\n // - { set: \"string\" } => \"string\"\n //\n (this.ref as any)[$childType] || // ArraySchema | MapSchema | SetSchema | CollectionSchema\n this.metadata[index].type // Schema\n );\n }\n\n getChange(index: number) {\n return this.indexedOperations[index];\n }\n\n //\n // used during `.encode()`\n //\n getValue(index: number, isEncodeAll: boolean = false) {\n //\n // `isEncodeAll` param is only used by ArraySchema\n //\n return (this.ref as any)[$getByIndex](index, isEncodeAll);\n }\n\n delete(index: number, operation?: OPERATION, allChangesIndex = index) {\n if (index === undefined) {\n try {\n throw new Error(`@colyseus/schema ${this.ref.constructor.name}: trying to delete non-existing index '${index}'`);\n } catch (e) {\n console.warn(e);\n }\n return;\n }\n\n const changeSet = (this.filteredChanges !== undefined)\n ? this.filteredChanges\n : this.changes;\n\n this.indexedOperations[index] = operation ?? OPERATION.DELETE;\n setOperationAtIndex(changeSet, index);\n deleteOperationAtIndex(this.allChanges, allChangesIndex);\n\n const previousValue = this.getValue(index);\n\n // remove `root` reference\n if (previousValue && previousValue[$changes]) {\n //\n // FIXME: this.root is \"undefined\"\n //\n // This method is being called at decoding time when a DELETE operation is found.\n //\n // - This is due to using the concrete Schema class at decoding time.\n // - \"Reflected\" structures do not have this problem.\n //\n // (The property descriptors should NOT be used at decoding time. only at encoding time.)\n //\n this.root?.remove(previousValue[$changes]);\n }\n\n //\n // FIXME: this is looking a ugly and repeated\n //\n if (this.filteredChanges !== undefined) {\n deleteOperationAtIndex(this.allFilteredChanges, allChangesIndex);\n this.root?.enqueueChangeTree(this, 'filteredChanges');\n\n } else {\n this.root?.enqueueChangeTree(this, 'changes');\n }\n\n return previousValue;\n }\n\n endEncode(changeSetName: ChangeSetName) {\n this.indexedOperations = {};\n\n // clear changeset\n this[changeSetName] = createChangeSet();\n\n // ArraySchema and MapSchema have a custom \"encode end\" method\n (this.ref as any)[$onEncodeEnd]?.();\n\n // Not a new instance anymore\n this.isNew = false;\n }\n\n discard(discardAll: boolean = false) {\n //\n // > MapSchema:\n // Remove cached key to ensure ADD operations is unsed instead of\n // REPLACE in case same key is used on next patches.\n //\n (this.ref as any)[$onEncodeEnd]?.();\n\n this.indexedOperations = {};\n this.changes = createChangeSet(this.changes.queueRootNode);\n\n if (this.filteredChanges !== undefined) {\n this.filteredChanges = createChangeSet(this.filteredChanges.queueRootNode);\n }\n\n if (discardAll) {\n // preserve queueRootNode references\n this.allChanges = createChangeSet(this.allChanges.queueRootNode);\n\n if (this.allFilteredChanges !== undefined) {\n this.allFilteredChanges = createChangeSet(this.allFilteredChanges.queueRootNode);\n }\n }\n }\n\n /**\n * Recursively discard all changes from this, and child structures.\n * (Used in tests only)\n */\n discardAll() {\n const keys = Object.keys(this.indexedOperations);\n for (let i = 0, len = keys.length; i < len; i++) {\n const value = this.getValue(Number(keys[i]));\n\n if (value && value[$changes]) {\n value[$changes].discardAll();\n }\n }\n\n this.discard();\n }\n\n get changed() {\n return (Object.entries(this.indexedOperations).length > 0);\n }\n\n protected checkIsFiltered(parent: Ref, parentIndex: number, isNewChangeTree: boolean) {\n if (this.root.types.hasFilters) {\n //\n // At Schema initialization, the \"root\" structure might not be available\n // yet, as it only does once the \"Encoder\" has been set up.\n //\n // So the \"parent\" may be already set without a \"root\".\n //\n this._checkFilteredByParent(parent, parentIndex);\n\n if (this.filteredChanges !== undefined) {\n this.root?.enqueueChangeTree(this, 'filteredChanges');\n\n if (isNewChangeTree) {\n this.root?.enqueueChangeTree(this, 'allFilteredChanges');\n }\n }\n }\n\n if (!this.isFiltered) {\n this.root?.enqueueChangeTree(this, 'changes');\n\n if (isNewChangeTree) {\n this.root?.enqueueChangeTree(this, 'allChanges');\n }\n }\n }\n\n protected _checkFilteredByParent(parent: Ref, parentIndex: number) {\n // skip if parent is not set\n if (!parent) { return; }\n\n //\n // ArraySchema | MapSchema - get the child type\n // (if refType is typeof string, the parentFiltered[key] below will always be invalid)\n //\n const refType = Metadata.isValidInstance(this.ref)\n ? this.ref.constructor\n : (this.ref as any)[$childType];\n\n let parentChangeTree: ChangeTree;\n\n let parentIsCollection = !Metadata.isValidInstance(parent);\n if (parentIsCollection) {\n parentChangeTree = parent[$changes];\n parent = parentChangeTree.parent;\n parentIndex = parentChangeTree.parentIndex;\n\n } else {\n parentChangeTree = parent[$changes]\n }\n\n const parentConstructor = parent.constructor as typeof Schema;\n\n let key = `${this.root.types.getTypeId(refType as typeof Schema)}`;\n if (parentConstructor) {\n key += `-${this.root.types.schemas.get(parentConstructor)}`;\n }\n key += `-${parentIndex}`;\n\n const fieldHasViewTag = Metadata.hasViewTagAtIndex(parentConstructor?.[Symbol.metadata], parentIndex);\n\n this.isFiltered = parent[$changes].isFiltered // in case parent is already filtered\n || this.root.types.parentFiltered[key]\n || fieldHasViewTag;\n\n //\n // \"isFiltered\" may not be imedialely available during `change()` due to the instance not being attached to the root yet.\n // when it's available, we need to enqueue the \"changes\" changeset into the \"filteredChanges\" changeset.\n //\n if (this.isFiltered) {\n\n this.isVisibilitySharedWithParent = (\n parentChangeTree.isFiltered &&\n typeof (refType) !== \"string\" &&\n !fieldHasViewTag &&\n parentIsCollection\n );\n\n if (!this.filteredChanges) {\n this.filteredChanges = createChangeSet();\n this.allFilteredChanges = createChangeSet();\n }\n\n if (this.changes.operations.length > 0) {\n this.changes.operations.forEach((index) =>\n setOperationAtIndex(this.filteredChanges, index));\n\n this.allChanges.operations.forEach((index) =>\n setOperationAtIndex(this.allFilteredChanges, index));\n\n this.changes = createChangeSet();\n this.allChanges = createChangeSet();\n }\n }\n }\n\n /**\n * Get the immediate parent\n */\n get parent(): Ref | undefined {\n return this.parentChain?.ref;\n }\n\n /**\n * Get the immediate parent index\n */\n get parentIndex(): number | undefined {\n return this.parentChain?.index;\n }\n\n /**\n * Add a parent to the chain\n */\n addParent(parent: Ref, index: number) {\n // Check if this parent already exists in the chain\n if (this.hasParent((p, _) => p[$changes] === parent[$changes])) {\n // if (this.hasParent((p, i) => p[$changes] === parent[$changes] && i === index)) {\n this.parentChain.index = index;\n return;\n }\n\n this.parentChain = {\n ref: parent,\n index,\n next: this.parentChain\n };\n }\n\n /**\n * Remove a parent from the chain\n * @param parent - The parent to remove\n * @returns true if parent was removed\n */\n removeParent(parent: Ref = this.parent): boolean {\n let current = this.parentChain;\n let previous = null;\n while (current) {\n //\n // FIXME: it is required to check against `$changes` here because\n // ArraySchema is instance of Proxy\n //\n if (current.ref[$changes] === parent[$changes]) {\n if (previous) {\n previous.next = current.next;\n } else {\n this.parentChain = current.next;\n }\n return true;\n }\n previous = current;\n current = current.next;\n }\n return this.parentChain === undefined;\n }\n\n /**\n * Find a specific parent in the chain\n */\n findParent(predicate: (parent: Ref, index: number) => boolean): ParentChain | undefined {\n let current = this.parentChain;\n while (current) {\n if (predicate(current.ref, current.index)) {\n return current;\n }\n current = current.next;\n }\n return undefined;\n }\n\n /**\n * Check if this ChangeTree has a specific parent\n */\n hasParent(predicate: (parent: Ref, index: number) => boolean): boolean {\n return this.findParent(predicate) !== undefined;\n }\n\n /**\n * Get all parents as an array (for debugging/testing)\n */\n getAllParents(): Array<{ ref: Ref, index: number }> {\n const parents: Array<{ ref: Ref, index: number }> = [];\n let current = this.parentChain;\n while (current) {\n parents.push({ ref: current.ref, index: current.index });\n current = current.next;\n }\n return parents;\n }\n\n}\n"]}
|
|
@@ -3,8 +3,8 @@ import type { ChangeTree, Ref } from "./ChangeTree";
|
|
|
3
3
|
import type { Encoder } from "./Encoder";
|
|
4
4
|
import type { Iterator } from "../encoding/decode";
|
|
5
5
|
import type { Metadata } from "../Metadata";
|
|
6
|
-
export type EncodeOperation<T extends Ref = any> = (encoder: Encoder, bytes:
|
|
7
|
-
export declare function encodeValue(encoder: Encoder, bytes:
|
|
6
|
+
export type EncodeOperation<T extends Ref = any> = (encoder: Encoder, bytes: Uint8Array, changeTree: ChangeTree<T>, index: number, operation: OPERATION, it: Iterator, isEncodeAll: boolean, hasView: boolean, metadata?: Metadata) => void;
|
|
7
|
+
export declare function encodeValue(encoder: Encoder, bytes: Uint8Array, type: any, value: any, operation: OPERATION, it: Iterator): void;
|
|
8
8
|
/**
|
|
9
9
|
* Used for Schema instances.
|
|
10
10
|
* @private
|
|
@@ -14,7 +14,7 @@ function encodeValue(encoder, bytes, type, value, operation, it) {
|
|
|
14
14
|
// Encode refId for this instance.
|
|
15
15
|
// The actual instance is going to be encoded on next `changeTree` iteration.
|
|
16
16
|
//
|
|
17
|
-
encode_1.encode.number(bytes, value[symbols_1.$
|
|
17
|
+
encode_1.encode.number(bytes, value[symbols_1.$refId], it);
|
|
18
18
|
// Try to encode inherited TYPE_ID if it's an ADD operation.
|
|
19
19
|
if ((operation & spec_1.OPERATION.ADD) === spec_1.OPERATION.ADD) {
|
|
20
20
|
encoder.tryEncodeTypeId(bytes, type, value.constructor, it);
|
|
@@ -25,7 +25,7 @@ function encodeValue(encoder, bytes, type, value, operation, it) {
|
|
|
25
25
|
// Encode refId for this instance.
|
|
26
26
|
// The actual instance is going to be encoded on next `changeTree` iteration.
|
|
27
27
|
//
|
|
28
|
-
encode_1.encode.number(bytes, value[symbols_1.$
|
|
28
|
+
encode_1.encode.number(bytes, value[symbols_1.$refId], it);
|
|
29
29
|
}
|
|
30
30
|
}
|
|
31
31
|
/**
|
|
@@ -103,7 +103,7 @@ const encodeArray = function (encoder, bytes, changeTree, field, operation, it,
|
|
|
103
103
|
if (!item) {
|
|
104
104
|
return;
|
|
105
105
|
}
|
|
106
|
-
refOrIndex = item[symbols_1.$
|
|
106
|
+
refOrIndex = item[symbols_1.$refId];
|
|
107
107
|
if (operation === spec_1.OPERATION.DELETE) {
|
|
108
108
|
operation = spec_1.OPERATION.DELETE_BY_REFID;
|
|
109
109
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"EncodeOperation.js","sourceRoot":"","sources":["../../src/encoder/EncodeOperation.ts"],"names":[],"mappings":"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","sourcesContent":["import { OPERATION } from \"../encoding/spec\";\nimport { $changes, $childType, $getByIndex } from \"../types/symbols\";\n\nimport { encode } from \"../encoding/encode\";\n\nimport type { ChangeTree, Ref } from \"./ChangeTree\";\nimport type { Encoder } from \"./Encoder\";\nimport type { Schema } from \"../Schema\";\n\nimport type { Iterator } from \"../encoding/decode\";\nimport type { ArraySchema } from \"../types/custom/ArraySchema\";\nimport type { Metadata } from \"../Metadata\";\n\nexport type EncodeOperation<T extends Ref = any> = (\n encoder: Encoder,\n bytes: Buffer,\n changeTree: ChangeTree<T>,\n index: number,\n operation: OPERATION,\n it: Iterator,\n isEncodeAll: boolean,\n hasView: boolean,\n metadata?: Metadata,\n) => void;\n\nexport function encodeValue(\n encoder: Encoder,\n bytes: Buffer,\n type: any,\n value: any,\n operation: OPERATION,\n it: Iterator,\n) {\n if (typeof (type) === \"string\") {\n (encode as any)[type]?.(bytes, value, it);\n\n } else if (type[Symbol.metadata] !== undefined) {\n //\n // Encode refId for this instance.\n // The actual instance is going to be encoded on next `changeTree` iteration.\n //\n encode.number(bytes, value[$changes].refId, it);\n\n // Try to encode inherited TYPE_ID if it's an ADD operation.\n if ((operation & OPERATION.ADD) === OPERATION.ADD) {\n encoder.tryEncodeTypeId(bytes, type as typeof Schema, value.constructor as typeof Schema, it);\n }\n\n } else {\n //\n // Encode refId for this instance.\n // The actual instance is going to be encoded on next `changeTree` iteration.\n //\n encode.number(bytes, value[$changes].refId, it);\n }\n}\n\n/**\n * Used for Schema instances.\n * @private\n */\nexport const encodeSchemaOperation: EncodeOperation = function <T extends Schema> (\n encoder: Encoder,\n bytes: Buffer,\n changeTree: ChangeTree<T>,\n index: number,\n operation: OPERATION,\n it: Iterator,\n _: any,\n __: any,\n metadata: Metadata,\n) {\n // \"compress\" field index + operation\n bytes[it.offset++] = (index | operation) & 255;\n\n // Do not encode value for DELETE operations\n if (operation === OPERATION.DELETE) {\n return;\n }\n\n const ref = changeTree.ref;\n const field = metadata[index];\n\n // TODO: inline this function call small performance gain\n encodeValue(\n encoder,\n bytes,\n metadata[index].type,\n ref[field.name as keyof T],\n operation,\n it\n );\n}\n\n/**\n * Used for collections (MapSchema, CollectionSchema, SetSchema)\n * @private\n */\nexport const encodeKeyValueOperation: EncodeOperation = function (\n encoder: Encoder,\n bytes: Buffer,\n changeTree: ChangeTree,\n index: number,\n operation: OPERATION,\n it: Iterator,\n) {\n // encode operation\n bytes[it.offset++] = operation & 255;\n\n // encode index\n encode.number(bytes, index, it);\n\n // Do not encode value for DELETE operations\n if (operation === OPERATION.DELETE) {\n return;\n }\n\n const ref = changeTree.ref;\n\n //\n // encode \"alias\" for dynamic fields (maps)\n //\n if ((operation & OPERATION.ADD) === OPERATION.ADD) { // ADD or DELETE_AND_ADD\n if (typeof(ref['set']) === \"function\") {\n //\n // MapSchema dynamic key\n //\n const dynamicIndex = changeTree.ref['$indexes'].get(index);\n encode.string(bytes, dynamicIndex, it);\n }\n }\n\n const type = ref[$childType];\n const value = ref[$getByIndex](index);\n\n // try { throw new Error(); } catch (e) {\n // // only print if not coming from Reflection.ts\n // if (!e.stack.includes(\"src/Reflection.ts\")) {\n // console.log(\"encodeKeyValueOperation -> \", {\n // ref: changeTree.ref.constructor.name,\n // field,\n // operation: OPERATION[operation],\n // value: value?.toJSON(),\n // items: ref.toJSON(),\n // });\n // }\n // }\n\n // TODO: inline this function call small performance gain\n encodeValue(\n encoder,\n bytes,\n type,\n value,\n operation,\n it\n );\n}\n\n/**\n * Used for collections (MapSchema, ArraySchema, etc.)\n * @private\n */\nexport const encodeArray: EncodeOperation = function (\n encoder: Encoder,\n bytes: Buffer,\n changeTree: ChangeTree<ArraySchema>,\n field: number,\n operation: OPERATION,\n it: Iterator,\n isEncodeAll: boolean,\n hasView: boolean,\n) {\n const ref = changeTree.ref;\n const useOperationByRefId = hasView && changeTree.isFiltered && (typeof (changeTree.getType(field)) !== \"string\");\n\n let refOrIndex: number;\n\n if (useOperationByRefId) {\n const item = ref['tmpItems'][field];\n\n // Skip encoding if item is undefined (e.g. when clear() is called)\n if (!item) { return; }\n\n refOrIndex = item[$changes].refId;\n\n if (operation === OPERATION.DELETE) {\n operation = OPERATION.DELETE_BY_REFID;\n\n } else if (operation === OPERATION.ADD) {\n operation = OPERATION.ADD_BY_REFID;\n }\n\n } else {\n refOrIndex = field;\n }\n\n // encode operation\n bytes[it.offset++] = operation & 255;\n\n // encode index\n encode.number(bytes, refOrIndex, it);\n\n // Do not encode value for DELETE operations\n if (operation === OPERATION.DELETE || operation === OPERATION.DELETE_BY_REFID) {\n return;\n }\n\n const type = changeTree.getType(field);\n const value = changeTree.getValue(field, isEncodeAll);\n\n // console.log({ type, field, value });\n\n // console.log(\"encodeArray -> \", {\n // ref: changeTree.ref.constructor.name,\n // field,\n // operation: OPERATION[operation],\n // value: value?.toJSON(),\n // items: ref.toJSON(),\n // });\n\n // TODO: inline this function call small performance gain\n encodeValue(\n encoder,\n bytes,\n type,\n value,\n operation,\n it\n );\n}"]}
|
|
1
|
+
{"version":3,"file":"EncodeOperation.js","sourceRoot":"","sources":["../../src/encoder/EncodeOperation.ts"],"names":[],"mappings":"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","sourcesContent":["import { OPERATION } from \"../encoding/spec\";\nimport { $changes, $childType, $getByIndex, $refId } from \"../types/symbols\";\n\nimport { encode } from \"../encoding/encode\";\n\nimport type { ChangeTree, Ref } from \"./ChangeTree\";\nimport type { Encoder } from \"./Encoder\";\nimport type { Schema } from \"../Schema\";\n\nimport type { Iterator } from \"../encoding/decode\";\nimport type { ArraySchema } from \"../types/custom/ArraySchema\";\nimport type { Metadata } from \"../Metadata\";\n\nexport type EncodeOperation<T extends Ref = any> = (\n encoder: Encoder,\n bytes: Uint8Array,\n changeTree: ChangeTree<T>,\n index: number,\n operation: OPERATION,\n it: Iterator,\n isEncodeAll: boolean,\n hasView: boolean,\n metadata?: Metadata,\n) => void;\n\nexport function encodeValue(\n encoder: Encoder,\n bytes: Uint8Array,\n type: any,\n value: any,\n operation: OPERATION,\n it: Iterator,\n) {\n if (typeof (type) === \"string\") {\n (encode as any)[type]?.(bytes, value, it);\n\n } else if (type[Symbol.metadata] !== undefined) {\n //\n // Encode refId for this instance.\n // The actual instance is going to be encoded on next `changeTree` iteration.\n //\n encode.number(bytes, value[$refId], it);\n\n // Try to encode inherited TYPE_ID if it's an ADD operation.\n if ((operation & OPERATION.ADD) === OPERATION.ADD) {\n encoder.tryEncodeTypeId(bytes, type as typeof Schema, value.constructor as typeof Schema, it);\n }\n\n } else {\n //\n // Encode refId for this instance.\n // The actual instance is going to be encoded on next `changeTree` iteration.\n //\n encode.number(bytes, value[$refId], it);\n }\n}\n\n/**\n * Used for Schema instances.\n * @private\n */\nexport const encodeSchemaOperation: EncodeOperation = function <T extends Schema> (\n encoder: Encoder,\n bytes: Uint8Array,\n changeTree: ChangeTree<T>,\n index: number,\n operation: OPERATION,\n it: Iterator,\n _: any,\n __: any,\n metadata: Metadata,\n) {\n // \"compress\" field index + operation\n bytes[it.offset++] = (index | operation) & 255;\n\n // Do not encode value for DELETE operations\n if (operation === OPERATION.DELETE) {\n return;\n }\n\n const ref = changeTree.ref;\n const field = metadata[index];\n\n // TODO: inline this function call small performance gain\n encodeValue(\n encoder,\n bytes,\n metadata[index].type,\n ref[field.name as keyof T],\n operation,\n it\n );\n}\n\n/**\n * Used for collections (MapSchema, CollectionSchema, SetSchema)\n * @private\n */\nexport const encodeKeyValueOperation: EncodeOperation = function (\n encoder: Encoder,\n bytes: Uint8Array,\n changeTree: ChangeTree,\n index: number,\n operation: OPERATION,\n it: Iterator,\n) {\n // encode operation\n bytes[it.offset++] = operation & 255;\n\n // encode index\n encode.number(bytes, index, it);\n\n // Do not encode value for DELETE operations\n if (operation === OPERATION.DELETE) {\n return;\n }\n\n const ref = changeTree.ref;\n\n //\n // encode \"alias\" for dynamic fields (maps)\n //\n if ((operation & OPERATION.ADD) === OPERATION.ADD) { // ADD or DELETE_AND_ADD\n if (typeof(ref['set']) === \"function\") {\n //\n // MapSchema dynamic key\n //\n const dynamicIndex = changeTree.ref['$indexes'].get(index);\n encode.string(bytes, dynamicIndex, it);\n }\n }\n\n const type = ref[$childType];\n const value = ref[$getByIndex](index);\n\n // try { throw new Error(); } catch (e) {\n // // only print if not coming from Reflection.ts\n // if (!e.stack.includes(\"src/Reflection.ts\")) {\n // console.log(\"encodeKeyValueOperation -> \", {\n // ref: changeTree.ref.constructor.name,\n // field,\n // operation: OPERATION[operation],\n // value: value?.toJSON(),\n // items: ref.toJSON(),\n // });\n // }\n // }\n\n // TODO: inline this function call small performance gain\n encodeValue(\n encoder,\n bytes,\n type,\n value,\n operation,\n it\n );\n}\n\n/**\n * Used for collections (MapSchema, ArraySchema, etc.)\n * @private\n */\nexport const encodeArray: EncodeOperation = function (\n encoder: Encoder,\n bytes: Uint8Array,\n changeTree: ChangeTree<ArraySchema>,\n field: number,\n operation: OPERATION,\n it: Iterator,\n isEncodeAll: boolean,\n hasView: boolean,\n) {\n const ref = changeTree.ref;\n const useOperationByRefId = hasView && changeTree.isFiltered && (typeof (changeTree.getType(field)) !== \"string\");\n\n let refOrIndex: number;\n\n if (useOperationByRefId) {\n const item = ref['tmpItems'][field];\n\n // Skip encoding if item is undefined (e.g. when clear() is called)\n if (!item) { return; }\n\n refOrIndex = item[$refId];\n\n if (operation === OPERATION.DELETE) {\n operation = OPERATION.DELETE_BY_REFID;\n\n } else if (operation === OPERATION.ADD) {\n operation = OPERATION.ADD_BY_REFID;\n }\n\n } else {\n refOrIndex = field;\n }\n\n // encode operation\n bytes[it.offset++] = operation & 255;\n\n // encode index\n encode.number(bytes, refOrIndex, it);\n\n // Do not encode value for DELETE operations\n if (operation === OPERATION.DELETE || operation === OPERATION.DELETE_BY_REFID) {\n return;\n }\n\n const type = changeTree.getType(field);\n const value = changeTree.getValue(field, isEncodeAll);\n\n // console.log({ type, field, value });\n\n // console.log(\"encodeArray -> \", {\n // ref: changeTree.ref.constructor.name,\n // field,\n // operation: OPERATION[operation],\n // value: value?.toJSON(),\n // items: ref.toJSON(),\n // });\n\n // TODO: inline this function call small performance gain\n encodeValue(\n encoder,\n bytes,\n type,\n value,\n operation,\n it\n );\n}"]}
|
package/lib/encoder/Encoder.d.ts
CHANGED
|
@@ -6,17 +6,17 @@ import type { StateView } from "./StateView";
|
|
|
6
6
|
import type { ChangeSetName } from "./ChangeTree";
|
|
7
7
|
export declare class Encoder<T extends Schema = any> {
|
|
8
8
|
static BUFFER_SIZE: number;
|
|
9
|
-
sharedBuffer:
|
|
9
|
+
sharedBuffer: Uint8Array<ArrayBuffer>;
|
|
10
10
|
context: TypeContext;
|
|
11
11
|
state: T;
|
|
12
12
|
root: Root;
|
|
13
13
|
constructor(state: T);
|
|
14
14
|
protected setState(state: T): void;
|
|
15
|
-
encode(it?: Iterator, view?: StateView, buffer?:
|
|
16
|
-
encodeAll(it?: Iterator, buffer?:
|
|
17
|
-
encodeAllView(view: StateView, sharedOffset: number, it: Iterator, bytes?:
|
|
18
|
-
encodeView(view: StateView, sharedOffset: number, it: Iterator, bytes?:
|
|
15
|
+
encode(it?: Iterator, view?: StateView, buffer?: Uint8Array<ArrayBuffer>, changeSetName?: ChangeSetName, isEncodeAll?: boolean, initialOffset?: number): Uint8Array;
|
|
16
|
+
encodeAll(it?: Iterator, buffer?: Uint8Array<ArrayBuffer>): Uint8Array<ArrayBufferLike>;
|
|
17
|
+
encodeAllView(view: StateView, sharedOffset: number, it: Iterator, bytes?: Uint8Array<ArrayBuffer>): Uint8Array<ArrayBufferLike>;
|
|
18
|
+
encodeView(view: StateView, sharedOffset: number, it: Iterator, bytes?: Uint8Array<ArrayBuffer>): Uint8Array<ArrayBufferLike>;
|
|
19
19
|
discardChanges(): void;
|
|
20
|
-
tryEncodeTypeId(bytes:
|
|
20
|
+
tryEncodeTypeId(bytes: Uint8Array, baseType: typeof Schema, targetType: typeof Schema, it: Iterator): void;
|
|
21
21
|
get hasChanges(): boolean;
|
|
22
22
|
}
|
package/lib/encoder/Encoder.js
CHANGED
|
@@ -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 =
|
|
17
|
+
static { this.BUFFER_SIZE = 8 * 1024; } // 8KB
|
|
12
18
|
constructor(state) {
|
|
13
|
-
this.sharedBuffer =
|
|
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,
|
|
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
|
|
92
|
-
// multiples of
|
|
93
|
-
|
|
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
|
-
|
|
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
|
|
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,
|
|
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
|
|
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"]}
|
package/lib/encoder/Root.js
CHANGED
|
@@ -21,15 +21,17 @@ class Root {
|
|
|
21
21
|
return this.nextUniqueId++;
|
|
22
22
|
}
|
|
23
23
|
add(changeTree) {
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
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
|
|
29
|
+
const refId = ref[symbols_1.$refId];
|
|
30
|
+
const isNewChangeTree = (this.changeTrees[refId] === undefined);
|
|
29
31
|
if (isNewChangeTree) {
|
|
30
|
-
this.changeTrees[
|
|
32
|
+
this.changeTrees[refId] = changeTree;
|
|
31
33
|
}
|
|
32
|
-
const previousRefCount = this.refCount[
|
|
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[
|
|
46
|
-
// console.log("ADD", { refId
|
|
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
|
|
51
|
-
|
|
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[
|
|
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[
|
|
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[
|
|
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.
|