@colyseus/schema 3.0.57 → 3.0.59
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 +78 -31
- package/build/cjs/index.js.map +1 -1
- package/build/esm/index.mjs +78 -31
- package/build/esm/index.mjs.map +1 -1
- package/build/umd/index.js +78 -31
- package/lib/decoder/Decoder.js +1 -3
- package/lib/decoder/Decoder.js.map +1 -1
- package/lib/encoder/ChangeTree.d.ts +1 -1
- package/lib/encoder/ChangeTree.js +4 -4
- package/lib/encoder/ChangeTree.js.map +1 -1
- package/lib/encoder/Encoder.js +2 -2
- package/lib/encoder/Encoder.js.map +1 -1
- package/lib/encoder/Root.d.ts +5 -2
- package/lib/encoder/Root.js +72 -23
- package/lib/encoder/Root.js.map +1 -1
- package/package.json +1 -1
- package/src/decoder/Decoder.ts +1 -2
- package/src/encoder/ChangeTree.ts +5 -5
- package/src/encoder/Encoder.ts +3 -3
- package/src/encoder/Root.ts +81 -24
package/build/umd/index.js
CHANGED
|
@@ -994,7 +994,7 @@
|
|
|
994
994
|
}
|
|
995
995
|
// Linked list helper functions
|
|
996
996
|
function createChangeTreeList() {
|
|
997
|
-
return { next: undefined, tail: undefined
|
|
997
|
+
return { next: undefined, tail: undefined };
|
|
998
998
|
}
|
|
999
999
|
function setOperationAtIndex(changeSet, index) {
|
|
1000
1000
|
const operationsIndex = changeSet.indexes[index];
|
|
@@ -1086,11 +1086,11 @@
|
|
|
1086
1086
|
this.forEachChild((child, index) => {
|
|
1087
1087
|
if (child.root === root) {
|
|
1088
1088
|
//
|
|
1089
|
-
// re-assigning a child of the same root, move it to
|
|
1090
|
-
//
|
|
1089
|
+
// re-assigning a child of the same root, move it next to parent
|
|
1090
|
+
// so encoding order is preserved
|
|
1091
1091
|
//
|
|
1092
1092
|
root.add(child);
|
|
1093
|
-
root.
|
|
1093
|
+
root.moveNextToParent(child);
|
|
1094
1094
|
return;
|
|
1095
1095
|
}
|
|
1096
1096
|
child.setParent(this.ref, root, index);
|
|
@@ -4017,8 +4017,8 @@
|
|
|
4017
4017
|
this.remove(child);
|
|
4018
4018
|
}
|
|
4019
4019
|
else if (child.parentChain) {
|
|
4020
|
-
// re-assigning a child of the same root, move it to
|
|
4021
|
-
this.
|
|
4020
|
+
// re-assigning a child of the same root, move it next to parent
|
|
4021
|
+
this.moveNextToParent(child);
|
|
4022
4022
|
}
|
|
4023
4023
|
}
|
|
4024
4024
|
});
|
|
@@ -4027,34 +4027,52 @@
|
|
|
4027
4027
|
this.refCount[changeTree.refId] = refCount;
|
|
4028
4028
|
//
|
|
4029
4029
|
// When losing a reference to an instance, it is best to move the
|
|
4030
|
-
// ChangeTree to
|
|
4030
|
+
// ChangeTree next to its parent in the encoding queue.
|
|
4031
4031
|
//
|
|
4032
4032
|
// This way, at decoding time, the instance that contains the
|
|
4033
4033
|
// ChangeTree will be available before the ChangeTree itself. If the
|
|
4034
4034
|
// containing instance is not available, the Decoder will throw
|
|
4035
4035
|
// "refId not found" error.
|
|
4036
4036
|
//
|
|
4037
|
-
this.
|
|
4038
|
-
changeTree.forEachChild((child, _) => this.moveToEndOfChanges(child));
|
|
4037
|
+
this.recursivelyMoveNextToParent(changeTree);
|
|
4039
4038
|
}
|
|
4040
4039
|
return refCount;
|
|
4041
4040
|
}
|
|
4042
|
-
|
|
4041
|
+
recursivelyMoveNextToParent(changeTree) {
|
|
4042
|
+
this.moveNextToParent(changeTree);
|
|
4043
|
+
changeTree.forEachChild((child, _) => this.recursivelyMoveNextToParent(child));
|
|
4044
|
+
}
|
|
4045
|
+
moveNextToParent(changeTree) {
|
|
4043
4046
|
if (changeTree.filteredChanges) {
|
|
4044
|
-
this.
|
|
4045
|
-
this.
|
|
4047
|
+
this.moveNextToParentInChangeTreeList("filteredChanges", changeTree);
|
|
4048
|
+
this.moveNextToParentInChangeTreeList("allFilteredChanges", changeTree);
|
|
4046
4049
|
}
|
|
4047
4050
|
else {
|
|
4048
|
-
this.
|
|
4049
|
-
this.
|
|
4051
|
+
this.moveNextToParentInChangeTreeList("changes", changeTree);
|
|
4052
|
+
this.moveNextToParentInChangeTreeList("allChanges", changeTree);
|
|
4050
4053
|
}
|
|
4051
4054
|
}
|
|
4052
|
-
|
|
4055
|
+
moveNextToParentInChangeTreeList(changeSetName, changeTree) {
|
|
4053
4056
|
const changeSet = this[changeSetName];
|
|
4054
4057
|
const node = changeTree[changeSetName].queueRootNode;
|
|
4055
|
-
if (!node
|
|
4058
|
+
if (!node)
|
|
4059
|
+
return;
|
|
4060
|
+
// Find the parent in the linked list
|
|
4061
|
+
const parent = changeTree.parent;
|
|
4062
|
+
if (!parent || !parent[$changes])
|
|
4063
|
+
return;
|
|
4064
|
+
const parentNode = parent[$changes][changeSetName]?.queueRootNode;
|
|
4065
|
+
if (!parentNode || parentNode === node)
|
|
4066
|
+
return;
|
|
4067
|
+
// Use cached positions - no iteration needed!
|
|
4068
|
+
const parentPosition = parentNode.position;
|
|
4069
|
+
const childPosition = node.position;
|
|
4070
|
+
// If child is already after parent, no need to move
|
|
4071
|
+
if (childPosition > parentPosition)
|
|
4056
4072
|
return;
|
|
4057
|
-
//
|
|
4073
|
+
// Child is before parent, so we need to move it after parent
|
|
4074
|
+
// This maintains decoding order (parent before child)
|
|
4075
|
+
// Remove node from current position
|
|
4058
4076
|
if (node.prev) {
|
|
4059
4077
|
node.prev.next = node.next;
|
|
4060
4078
|
}
|
|
@@ -4067,16 +4085,18 @@
|
|
|
4067
4085
|
else {
|
|
4068
4086
|
changeSet.tail = node.prev;
|
|
4069
4087
|
}
|
|
4070
|
-
//
|
|
4071
|
-
node.prev =
|
|
4072
|
-
node.next =
|
|
4073
|
-
if (
|
|
4074
|
-
|
|
4088
|
+
// Insert node right after parent
|
|
4089
|
+
node.prev = parentNode;
|
|
4090
|
+
node.next = parentNode.next;
|
|
4091
|
+
if (parentNode.next) {
|
|
4092
|
+
parentNode.next.prev = node;
|
|
4075
4093
|
}
|
|
4076
4094
|
else {
|
|
4077
|
-
changeSet.
|
|
4095
|
+
changeSet.tail = node;
|
|
4078
4096
|
}
|
|
4079
|
-
|
|
4097
|
+
parentNode.next = node;
|
|
4098
|
+
// Update positions after the move
|
|
4099
|
+
this.updatePositionsAfterMove(changeSet, node, parentPosition + 1);
|
|
4080
4100
|
}
|
|
4081
4101
|
enqueueChangeTree(changeTree, changeSet, queueRootNode = changeTree[changeSet].queueRootNode) {
|
|
4082
4102
|
// skip
|
|
@@ -4087,7 +4107,12 @@
|
|
|
4087
4107
|
changeTree[changeSet].queueRootNode = this.addToChangeTreeList(this[changeSet], changeTree);
|
|
4088
4108
|
}
|
|
4089
4109
|
addToChangeTreeList(list, changeTree) {
|
|
4090
|
-
const node = {
|
|
4110
|
+
const node = {
|
|
4111
|
+
changeTree,
|
|
4112
|
+
next: undefined,
|
|
4113
|
+
prev: undefined,
|
|
4114
|
+
position: list.tail ? list.tail.position + 1 : 0
|
|
4115
|
+
};
|
|
4091
4116
|
if (!list.next) {
|
|
4092
4117
|
list.next = node;
|
|
4093
4118
|
list.tail = node;
|
|
@@ -4097,13 +4122,35 @@
|
|
|
4097
4122
|
list.tail.next = node;
|
|
4098
4123
|
list.tail = node;
|
|
4099
4124
|
}
|
|
4100
|
-
list.length++;
|
|
4101
4125
|
return node;
|
|
4102
4126
|
}
|
|
4127
|
+
updatePositionsAfterRemoval(list, removedPosition) {
|
|
4128
|
+
// Update positions for all nodes after the removed position
|
|
4129
|
+
let current = list.next;
|
|
4130
|
+
let position = 0;
|
|
4131
|
+
while (current) {
|
|
4132
|
+
if (position >= removedPosition) {
|
|
4133
|
+
current.position = position;
|
|
4134
|
+
}
|
|
4135
|
+
current = current.next;
|
|
4136
|
+
position++;
|
|
4137
|
+
}
|
|
4138
|
+
}
|
|
4139
|
+
updatePositionsAfterMove(list, node, newPosition) {
|
|
4140
|
+
// Recalculate all positions - this is more reliable than trying to be clever
|
|
4141
|
+
let current = list.next;
|
|
4142
|
+
let position = 0;
|
|
4143
|
+
while (current) {
|
|
4144
|
+
current.position = position;
|
|
4145
|
+
current = current.next;
|
|
4146
|
+
position++;
|
|
4147
|
+
}
|
|
4148
|
+
}
|
|
4103
4149
|
removeChangeFromChangeSet(changeSetName, changeTree) {
|
|
4104
4150
|
const changeSet = this[changeSetName];
|
|
4105
4151
|
const node = changeTree[changeSetName].queueRootNode;
|
|
4106
4152
|
if (node && node.changeTree === changeTree) {
|
|
4153
|
+
const removedPosition = node.position;
|
|
4107
4154
|
// Remove the node from the linked list
|
|
4108
4155
|
if (node.prev) {
|
|
4109
4156
|
node.prev.next = node.next;
|
|
@@ -4117,7 +4164,8 @@
|
|
|
4117
4164
|
else {
|
|
4118
4165
|
changeSet.tail = node.prev;
|
|
4119
4166
|
}
|
|
4120
|
-
|
|
4167
|
+
// Update positions for nodes that came after the removed node
|
|
4168
|
+
this.updatePositionsAfterRemoval(changeSet, removedPosition);
|
|
4121
4169
|
// Clear ChangeTree reference
|
|
4122
4170
|
changeTree[changeSetName].queueRootNode = undefined;
|
|
4123
4171
|
return true;
|
|
@@ -4339,8 +4387,8 @@
|
|
|
4339
4387
|
}
|
|
4340
4388
|
}
|
|
4341
4389
|
get hasChanges() {
|
|
4342
|
-
return (this.root.changes.
|
|
4343
|
-
this.root.filteredChanges.
|
|
4390
|
+
return (this.root.changes.next !== undefined ||
|
|
4391
|
+
this.root.filteredChanges.next !== undefined);
|
|
4344
4392
|
}
|
|
4345
4393
|
}
|
|
4346
4394
|
|
|
@@ -4523,8 +4571,7 @@
|
|
|
4523
4571
|
if (!nextRef) {
|
|
4524
4572
|
// throw new Error(`"refId" not found: ${nextRefId}`);
|
|
4525
4573
|
console.error(`"refId" not found: ${nextRefId}`, { previousRef: ref, previousRefId: this.currentRefId });
|
|
4526
|
-
console.warn("Please report this to the developers.
|
|
4527
|
-
console.warn(Schema.debugRefIdsFromDecoder(this));
|
|
4574
|
+
console.warn("Please report this issue to the developers.");
|
|
4528
4575
|
this.skipCurrentStructure(bytes, it, totalBytes);
|
|
4529
4576
|
}
|
|
4530
4577
|
else {
|
package/lib/decoder/Decoder.js
CHANGED
|
@@ -3,7 +3,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.Decoder = void 0;
|
|
4
4
|
const TypeContext_1 = require("../types/TypeContext");
|
|
5
5
|
const symbols_1 = require("../types/symbols");
|
|
6
|
-
const Schema_1 = require("../Schema");
|
|
7
6
|
const decode_1 = require("../encoding/decode");
|
|
8
7
|
const spec_1 = require("../encoding/spec");
|
|
9
8
|
const ReferenceTracker_1 = require("./ReferenceTracker");
|
|
@@ -44,8 +43,7 @@ class Decoder {
|
|
|
44
43
|
if (!nextRef) {
|
|
45
44
|
// throw new Error(`"refId" not found: ${nextRefId}`);
|
|
46
45
|
console.error(`"refId" not found: ${nextRefId}`, { previousRef: ref, previousRefId: this.currentRefId });
|
|
47
|
-
console.warn("Please report this to the developers.
|
|
48
|
-
console.warn(Schema_1.Schema.debugRefIdsFromDecoder(this));
|
|
46
|
+
console.warn("Please report this issue to the developers.");
|
|
49
47
|
this.skipCurrentStructure(bytes, it, totalBytes);
|
|
50
48
|
}
|
|
51
49
|
else {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Decoder.js","sourceRoot":"","sources":["../../src/decoder/Decoder.ts"],"names":[],"mappings":";;;AAAA,sDAAmD;AACnD,8CAAgF;
|
|
1
|
+
{"version":3,"file":"Decoder.js","sourceRoot":"","sources":["../../src/decoder/Decoder.ts"],"names":[],"mappings":"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","sourcesContent":["import { TypeContext } from \"../types/TypeContext\";\nimport { $changes, $childType, $decoder, $onDecodeEnd } from \"../types/symbols\";\nimport { Schema } from \"../Schema\";\n\nimport { decode } from \"../encoding/decode\";\nimport { OPERATION, SWITCH_TO_STRUCTURE, TYPE_ID } from '../encoding/spec';\nimport type { Ref } from \"../encoder/ChangeTree\";\nimport type { Iterator } from \"../encoding/decode\";\nimport { ReferenceTracker } from \"./ReferenceTracker\";\nimport { DEFINITION_MISMATCH, type DataChange, type DecodeOperation } from \"./DecodeOperation\";\nimport { Collection } from \"../types/HelperTypes\";\n\nexport class Decoder<T extends Schema = any> {\n context: TypeContext;\n\n state: T;\n root: ReferenceTracker;\n\n currentRefId: number = 0;\n\n triggerChanges?: (allChanges: DataChange[]) => void;\n\n constructor(root: T, context?: TypeContext) {\n this.setState(root);\n\n this.context = context || new TypeContext(root.constructor as typeof Schema);\n\n // console.log(\">>>>>>>>>>>>>>>> Decoder types\");\n // this.context.schemas.forEach((id, schema) => {\n // console.log(\"type:\", id, schema.name, Object.keys(schema[Symbol.metadata]));\n // });\n }\n\n protected setState(root: T) {\n this.state = root;\n this.root = new ReferenceTracker();\n this.root.addRef(0, root);\n }\n\n decode(\n bytes: Buffer,\n it: Iterator = { offset: 0 },\n ref: Ref = this.state,\n ) {\n const allChanges: DataChange[] = [];\n\n const $root = this.root;\n const totalBytes = bytes.byteLength;\n\n let decoder: DecodeOperation = ref['constructor'][$decoder];\n\n this.currentRefId = 0;\n\n while (it.offset < totalBytes) {\n //\n // Peek ahead, check if it's a switch to a different structure\n //\n if (bytes[it.offset] == SWITCH_TO_STRUCTURE) {\n it.offset++;\n\n ref[$onDecodeEnd]?.()\n\n const nextRefId = decode.number(bytes, it);\n const nextRef = $root.refs.get(nextRefId);\n\n //\n // Trying to access a reference that haven't been decoded yet.\n //\n if (!nextRef) {\n // throw new Error(`\"refId\" not found: ${nextRefId}`);\n console.error(`\"refId\" not found: ${nextRefId}`, { previousRef: ref, previousRefId: this.currentRefId });\n console.warn(\"Please report this issue to the developers.\");\n this.skipCurrentStructure(bytes, it, totalBytes);\n\n } else {\n ref = nextRef;\n decoder = ref.constructor[$decoder];\n this.currentRefId = nextRefId;\n }\n\n continue;\n }\n\n const result = decoder(this, bytes, it, ref, allChanges);\n\n if (result === DEFINITION_MISMATCH) {\n console.warn(\"@colyseus/schema: definition mismatch\");\n this.skipCurrentStructure(bytes, it, totalBytes);\n continue;\n }\n }\n\n // FIXME: DRY with SWITCH_TO_STRUCTURE block.\n ref[$onDecodeEnd]?.()\n\n // trigger changes\n this.triggerChanges?.(allChanges);\n\n // drop references of unused schemas\n $root.garbageCollectDeletedRefs();\n\n return allChanges;\n }\n\n skipCurrentStructure(bytes: Buffer, it: Iterator, totalBytes: number) {\n //\n // keep skipping next bytes until reaches a known structure\n // by local decoder.\n //\n const nextIterator: Iterator = { offset: it.offset };\n while (it.offset < totalBytes) {\n if (bytes[it.offset] === SWITCH_TO_STRUCTURE) {\n nextIterator.offset = it.offset + 1;\n if (this.root.refs.has(decode.number(bytes, nextIterator))) {\n break;\n }\n }\n it.offset++;\n }\n }\n\n getInstanceType(bytes: Buffer, it: Iterator, defaultType: typeof Schema): typeof Schema {\n let type: typeof Schema;\n\n if (bytes[it.offset] === TYPE_ID) {\n it.offset++;\n const type_id = decode.number(bytes, it);\n type = this.context.get(type_id);\n }\n\n return type || defaultType;\n }\n\n createInstanceOfType (type: typeof Schema): Schema {\n return new (type as any)();\n }\n\n removeChildRefs(ref: Collection, allChanges: DataChange[]) {\n const needRemoveRef = typeof (ref[$childType]) !== \"string\";\n const refId = this.root.refIds.get(ref as Ref);\n\n ref.forEach((value: any, key: any) => {\n allChanges.push({\n ref: ref as Ref,\n refId,\n op: OPERATION.DELETE,\n field: key,\n value: undefined,\n previousValue: value\n });\n\n if (needRemoveRef) {\n this.root.removeRef(this.root.refIds.get(value));\n }\n });\n }\n\n}\n"]}
|
|
@@ -25,11 +25,11 @@ export interface ChangeTreeNode {
|
|
|
25
25
|
changeTree: ChangeTree;
|
|
26
26
|
next?: ChangeTreeNode;
|
|
27
27
|
prev?: ChangeTreeNode;
|
|
28
|
+
position: number;
|
|
28
29
|
}
|
|
29
30
|
export interface ChangeTreeList {
|
|
30
31
|
next?: ChangeTreeNode;
|
|
31
32
|
tail?: ChangeTreeNode;
|
|
32
|
-
length: number;
|
|
33
33
|
}
|
|
34
34
|
export interface ChangeSet {
|
|
35
35
|
indexes: {
|
|
@@ -13,7 +13,7 @@ function createChangeSet(queueRootNode) {
|
|
|
13
13
|
}
|
|
14
14
|
// Linked list helper functions
|
|
15
15
|
function createChangeTreeList() {
|
|
16
|
-
return { next: undefined, tail: undefined
|
|
16
|
+
return { next: undefined, tail: undefined };
|
|
17
17
|
}
|
|
18
18
|
function setOperationAtIndex(changeSet, index) {
|
|
19
19
|
const operationsIndex = changeSet.indexes[index];
|
|
@@ -122,11 +122,11 @@ class ChangeTree {
|
|
|
122
122
|
this.forEachChild((child, index) => {
|
|
123
123
|
if (child.root === root) {
|
|
124
124
|
//
|
|
125
|
-
// re-assigning a child of the same root, move it to
|
|
126
|
-
//
|
|
125
|
+
// re-assigning a child of the same root, move it next to parent
|
|
126
|
+
// so encoding order is preserved
|
|
127
127
|
//
|
|
128
128
|
root.add(child);
|
|
129
|
-
root.
|
|
129
|
+
root.moveNextToParent(child);
|
|
130
130
|
return;
|
|
131
131
|
}
|
|
132
132
|
child.setParent(this.ref, root, index);
|
|
@@ -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 } 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 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}\n\n// Linked list for change trees\nexport interface ChangeTreeList {\n next?: ChangeTreeNode;\n tail?: ChangeTreeNode;\n length: number;\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, length: 0 };\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];\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];\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[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 to the end\n // of the changes queue so encoding order is preserved\n //\n root.add(child);\n root.moveToEndOfChanges(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[$childType]) {\n if (typeof (this.ref[$childType]) !== \"string\") {\n // MapSchema / ArraySchema, etc.\n for (const [key, value] of (this.ref as MapSchema).entries()) {\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];\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 = {};\n const newIndexes = {};\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 = {};\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[$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[$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[$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[$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[$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, $refTypeFieldIndexes, $viewFieldIndexes } 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 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];\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];\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[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[$childType]) {\n if (typeof (this.ref[$childType]) !== \"string\") {\n // MapSchema / ArraySchema, etc.\n for (const [key, value] of (this.ref as MapSchema).entries()) {\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];\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 = {};\n const newIndexes = {};\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 = {};\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[$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[$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[$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[$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[$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"]}
|
package/lib/encoder/Encoder.js
CHANGED
|
@@ -220,8 +220,8 @@ class Encoder {
|
|
|
220
220
|
}
|
|
221
221
|
}
|
|
222
222
|
get hasChanges() {
|
|
223
|
-
return (this.root.changes.
|
|
224
|
-
this.root.filteredChanges.
|
|
223
|
+
return (this.root.changes.next !== undefined ||
|
|
224
|
+
this.root.filteredChanges.next !== undefined);
|
|
225
225
|
}
|
|
226
226
|
}
|
|
227
227
|
exports.Encoder = Encoder;
|
|
@@ -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.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 debugChanges(field: \"changes\" | \"allFilteredChanges\" | \"allChanges\" | \"filteredChanges\") {\n const rootChangeSet = (typeof (field) === \"string\")\n ? this.root[field]\n : field;\n\n let current = rootChangeSet.next;\n while (current) {\n const changeTree = current.changeTree;\n const changeSet = changeTree[field];\n\n const metadata: Metadata = changeTree.ref.constructor[Symbol.metadata];\n console.log(\"->\", { ref: changeTree.ref.constructor.name, refId: changeTree.refId, changes: Object.keys(changeSet).length });\n for (const index in changeSet) {\n const op = changeSet[index];\n console.log(\" ->\", {\n index,\n field: metadata?.[index],\n op: OPERATION[op],\n });\n }\n current = current.next;\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.length > 0 ||\n this.root.filteredChanges.length > 0\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 } 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 debugChanges(field: \"changes\" | \"allFilteredChanges\" | \"allChanges\" | \"filteredChanges\") {\n const rootChangeSet = (typeof (field) === \"string\")\n ? this.root[field]\n : field;\n\n let current = rootChangeSet.next;\n while (current) {\n const changeTree = current.changeTree;\n const changeSet = changeTree[field];\n\n const metadata: Metadata = changeTree.ref.constructor[Symbol.metadata];\n console.log(\"->\", { ref: changeTree.ref.constructor.name, refId: changeTree.refId, changes: Object.keys(changeSet).length });\n for (const index in changeSet) {\n const op = changeSet[index];\n console.log(\" ->\", {\n index,\n field: metadata?.[index],\n op: OPERATION[op],\n });\n }\n current = current.next;\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"]}
|