@colyseus/schema 3.0.35 → 3.0.37

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.
@@ -1 +1 @@
1
- {"version":3,"file":"CollectionSchema.js","sourceRoot":"","sources":["../../../src/types/custom/CollectionSchema.ts"],"names":[],"mappings":"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","sourcesContent":["import { $changes, $childType, $decoder, $deleteByIndex, $encoder, $filter, $getByIndex, $onEncodeEnd } from \"../symbols\";\nimport { ChangeTree } from \"../../encoder/ChangeTree\";\nimport { OPERATION } from \"../../encoding/spec\";\nimport { registerType } from \"../registry\";\nimport { Collection } from \"../HelperTypes\";\nimport { decodeKeyValueOperation } from \"../../decoder/DecodeOperation\";\nimport { encodeKeyValueOperation } from \"../../encoder/EncodeOperation\";\nimport type { StateView } from \"../../encoder/StateView\";\n\ntype K = number; // TODO: allow to specify K generic on MapSchema.\n\nexport class CollectionSchema<V=any> implements Collection<K, V>{\n\n protected $items: Map<number, V> = new Map<number, V>();\n protected $indexes: Map<number, number> = new Map<number, number>();\n protected deletedItems: { [field: string]: V } = {};\n\n protected $refId: number = 0;\n\n static [$encoder] = encodeKeyValueOperation;\n static [$decoder] = decodeKeyValueOperation;\n\n /**\n * Determine if a property must be filtered.\n * - If returns false, the property is NOT going to be encoded.\n * - If returns true, the property is going to be encoded.\n *\n * Encoding with \"filters\" happens in two steps:\n * - First, the encoder iterates over all \"not owned\" properties and encodes them.\n * - Then, the encoder iterates over all \"owned\" properties per instance and encodes them.\n */\n static [$filter] (ref: CollectionSchema, index: number, view: StateView) {\n return (\n !view ||\n typeof (ref[$childType]) === \"string\" ||\n view.isChangeTreeVisible((ref[$getByIndex](index) ?? ref.deletedItems[index])[$changes])\n );\n }\n\n static is(type: any) {\n return type['collection'] !== undefined;\n }\n\n constructor (initialValues?: Array<V>) {\n this[$changes] = new ChangeTree(this);\n this[$changes].indexes = {};\n\n if (initialValues) {\n initialValues.forEach((v) => this.add(v));\n }\n\n Object.defineProperty(this, $childType, {\n value: undefined,\n enumerable: false,\n writable: true,\n configurable: true,\n });\n }\n\n add(value: V) {\n // set \"index\" for reference.\n const index = this.$refId++;\n\n const isRef = (value[$changes]) !== undefined;\n if (isRef) {\n value[$changes].setParent(this, this[$changes].root, index);\n }\n\n this[$changes].indexes[index] = index;\n\n this.$indexes.set(index, index);\n this.$items.set(index, value);\n\n this[$changes].change(index);\n\n return index;\n }\n\n at(index: number): V | undefined {\n const key = Array.from(this.$items.keys())[index];\n return this.$items.get(key);\n }\n\n entries() {\n return this.$items.entries();\n }\n\n delete(item: V) {\n const entries = this.$items.entries();\n\n let index: K;\n let entry: IteratorResult<[number, V]>;\n while (entry = entries.next()) {\n if (entry.done) { break; }\n\n if (item === entry.value[1]) {\n index = entry.value[0];\n break;\n }\n }\n\n if (index === undefined) {\n return false;\n }\n\n this.deletedItems[index] = this[$changes].delete(index);\n this.$indexes.delete(index);\n\n return this.$items.delete(index);\n }\n\n clear() {\n const changeTree = this[$changes];\n\n // discard previous operations.\n changeTree.discard(true);\n changeTree.indexes = {};\n\n // clear previous indexes\n this.$indexes.clear();\n\n // clear items\n this.$items.clear();\n\n changeTree.operation(OPERATION.CLEAR);\n }\n\n has (value: V): boolean {\n return Array.from(this.$items.values()).some((v) => v === value);\n }\n\n forEach(callbackfn: (value: V, key: K, collection: CollectionSchema<V>) => void) {\n this.$items.forEach((value, key, _) => callbackfn(value, key, this));\n }\n\n values() {\n return this.$items.values();\n }\n\n get size () {\n return this.$items.size;\n }\n\n /** Iterator */\n [Symbol.iterator](): IterableIterator<V> {\n return this.$items.values();\n }\n\n protected setIndex(index: number, key: number) {\n this.$indexes.set(index, key);\n }\n\n protected getIndex(index: number) {\n return this.$indexes.get(index);\n }\n\n protected [$getByIndex](index: number) {\n return this.$items.get(this.$indexes.get(index));\n }\n\n protected [$deleteByIndex](index: number) {\n const key = this.$indexes.get(index);\n this.$items.delete(key);\n this.$indexes.delete(index);\n }\n\n protected [$onEncodeEnd]() {\n this.deletedItems = {};\n }\n\n toArray() {\n return Array.from(this.$items.values());\n }\n\n toJSON() {\n const values: V[] = [];\n\n this.forEach((value, key) => {\n values.push(\n (typeof (value['toJSON']) === \"function\")\n ? value['toJSON']()\n : value\n );\n });\n\n return values;\n }\n\n //\n // Decoding utilities\n //\n clone(isDecoding?: boolean): CollectionSchema<V> {\n let cloned: CollectionSchema;\n\n if (isDecoding) {\n // client-side\n cloned = Object.assign(new CollectionSchema(), this);\n\n } else {\n // server-side\n cloned = new CollectionSchema();\n this.forEach((value) => {\n if (value[$changes]) {\n cloned.add(value['clone']());\n } else {\n cloned.add(value);\n }\n })\n }\n\n return cloned;\n }\n\n}\n\nregisterType(\"collection\", { constructor: CollectionSchema, });"]}
1
+ {"version":3,"file":"CollectionSchema.js","sourceRoot":"","sources":["../../../src/types/custom/CollectionSchema.ts"],"names":[],"mappings":"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","sourcesContent":["import { $changes, $childType, $decoder, $deleteByIndex, $encoder, $filter, $getByIndex, $onEncodeEnd } from \"../symbols\";\nimport { ChangeTree } from \"../../encoder/ChangeTree\";\nimport { OPERATION } from \"../../encoding/spec\";\nimport { registerType } from \"../registry\";\nimport { Collection } from \"../HelperTypes\";\nimport { decodeKeyValueOperation } from \"../../decoder/DecodeOperation\";\nimport { encodeKeyValueOperation } from \"../../encoder/EncodeOperation\";\nimport type { StateView } from \"../../encoder/StateView\";\n\ntype K = number; // TODO: allow to specify K generic on MapSchema.\n\nexport class CollectionSchema<V=any> implements Collection<K, V>{\n\n protected $items: Map<number, V> = new Map<number, V>();\n protected $indexes: Map<number, number> = new Map<number, number>();\n protected deletedItems: { [field: string]: V } = {};\n\n protected $refId: number = 0;\n\n static [$encoder] = encodeKeyValueOperation;\n static [$decoder] = decodeKeyValueOperation;\n\n /**\n * Determine if a property must be filtered.\n * - If returns false, the property is NOT going to be encoded.\n * - If returns true, the property is going to be encoded.\n *\n * Encoding with \"filters\" happens in two steps:\n * - First, the encoder iterates over all \"not owned\" properties and encodes them.\n * - Then, the encoder iterates over all \"owned\" properties per instance and encodes them.\n */\n static [$filter] (ref: CollectionSchema, index: number, view: StateView) {\n return (\n !view ||\n typeof (ref[$childType]) === \"string\" ||\n view.isChangeTreeVisible((ref[$getByIndex](index) ?? ref.deletedItems[index])[$changes])\n );\n }\n\n static is(type: any) {\n return type['collection'] !== undefined;\n }\n\n constructor (initialValues?: Array<V>) {\n this[$changes] = new ChangeTree(this);\n this[$changes].indexes = {};\n\n if (initialValues) {\n initialValues.forEach((v) => this.add(v));\n }\n\n Object.defineProperty(this, $childType, {\n value: undefined,\n enumerable: false,\n writable: true,\n configurable: true,\n });\n }\n\n add(value: V) {\n // set \"index\" for reference.\n const index = this.$refId++;\n\n const isRef = (value[$changes]) !== undefined;\n if (isRef) {\n value[$changes].setParent(this, this[$changes].root, index);\n }\n\n this[$changes].indexes[index] = index;\n\n this.$indexes.set(index, index);\n this.$items.set(index, value);\n\n this[$changes].change(index);\n\n return index;\n }\n\n at(index: number): V | undefined {\n const key = Array.from(this.$items.keys())[index];\n return this.$items.get(key);\n }\n\n entries() {\n return this.$items.entries();\n }\n\n delete(item: V) {\n const entries = this.$items.entries();\n\n let index: K;\n let entry: IteratorResult<[number, V]>;\n while (entry = entries.next()) {\n if (entry.done) { break; }\n\n if (item === entry.value[1]) {\n index = entry.value[0];\n break;\n }\n }\n\n if (index === undefined) {\n return false;\n }\n\n this.deletedItems[index] = this[$changes].delete(index);\n this.$indexes.delete(index);\n\n return this.$items.delete(index);\n }\n\n clear() {\n const changeTree = this[$changes];\n\n // discard previous operations.\n changeTree.discard(true);\n changeTree.indexes = {};\n\n // remove children references\n changeTree.forEachChild((childChangeTree, _) => {\n changeTree.root?.remove(childChangeTree);\n });\n\n // clear previous indexes\n this.$indexes.clear();\n\n // clear items\n this.$items.clear();\n\n changeTree.operation(OPERATION.CLEAR);\n }\n\n has (value: V): boolean {\n return Array.from(this.$items.values()).some((v) => v === value);\n }\n\n forEach(callbackfn: (value: V, key: K, collection: CollectionSchema<V>) => void) {\n this.$items.forEach((value, key, _) => callbackfn(value, key, this));\n }\n\n values() {\n return this.$items.values();\n }\n\n get size () {\n return this.$items.size;\n }\n\n /** Iterator */\n [Symbol.iterator](): IterableIterator<V> {\n return this.$items.values();\n }\n\n protected setIndex(index: number, key: number) {\n this.$indexes.set(index, key);\n }\n\n protected getIndex(index: number) {\n return this.$indexes.get(index);\n }\n\n protected [$getByIndex](index: number) {\n return this.$items.get(this.$indexes.get(index));\n }\n\n protected [$deleteByIndex](index: number) {\n const key = this.$indexes.get(index);\n this.$items.delete(key);\n this.$indexes.delete(index);\n }\n\n protected [$onEncodeEnd]() {\n this.deletedItems = {};\n }\n\n toArray() {\n return Array.from(this.$items.values());\n }\n\n toJSON() {\n const values: V[] = [];\n\n this.forEach((value, key) => {\n values.push(\n (typeof (value['toJSON']) === \"function\")\n ? value['toJSON']()\n : value\n );\n });\n\n return values;\n }\n\n //\n // Decoding utilities\n //\n clone(isDecoding?: boolean): CollectionSchema<V> {\n let cloned: CollectionSchema;\n\n if (isDecoding) {\n // client-side\n cloned = Object.assign(new CollectionSchema(), this);\n\n } else {\n // server-side\n cloned = new CollectionSchema();\n this.forEach((value) => {\n if (value[$changes]) {\n cloned.add(value['clone']());\n } else {\n cloned.add(value);\n }\n })\n }\n\n return cloned;\n }\n\n}\n\nregisterType(\"collection\", { constructor: CollectionSchema, });"]}
@@ -120,6 +120,10 @@ class MapSchema {
120
120
  // discard previous operations.
121
121
  changeTree.discard(true);
122
122
  changeTree.indexes = {};
123
+ // remove children references
124
+ changeTree.forEachChild((childChangeTree, _) => {
125
+ changeTree.root?.remove(childChangeTree);
126
+ });
123
127
  // clear previous indexes
124
128
  this.$indexes.clear();
125
129
  // clear items
@@ -1 +1 @@
1
- {"version":3,"file":"MapSchema.js","sourceRoot":"","sources":["../../../src/types/custom/MapSchema.ts"],"names":[],"mappings":"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","sourcesContent":["import { $changes, $childType, $decoder, $deleteByIndex, $onEncodeEnd, $encoder, $filter, $getByIndex, $numFields } from \"../symbols\";\nimport { ChangeTree } from \"../../encoder/ChangeTree\";\nimport { OPERATION } from \"../../encoding/spec\";\nimport { registerType } from \"../registry\";\nimport { Collection } from \"../HelperTypes\";\nimport { decodeKeyValueOperation } from \"../../decoder/DecodeOperation\";\nimport { encodeKeyValueOperation } from \"../../encoder/EncodeOperation\";\nimport type { StateView } from \"../../encoder/StateView\";\nimport type { Schema } from \"../../Schema\";\nimport { assertInstanceType } from \"../../encoding/assert\";\n\nexport class MapSchema<V=any, K extends string = string> implements Map<K, V>, Collection<K, V, [K, V]> {\n protected childType: new () => V;\n\n protected $items: Map<K, V> = new Map<K, V>();\n protected $indexes: Map<number, K> = new Map<number, K>();\n protected deletedItems: { [field: string]: V } = {};\n\n protected [$changes]: ChangeTree;\n\n static [$encoder] = encodeKeyValueOperation;\n static [$decoder] = decodeKeyValueOperation;\n\n /**\n * Determine if a property must be filtered.\n * - If returns false, the property is NOT going to be encoded.\n * - If returns true, the property is going to be encoded.\n *\n * Encoding with \"filters\" happens in two steps:\n * - First, the encoder iterates over all \"not owned\" properties and encodes them.\n * - Then, the encoder iterates over all \"owned\" properties per instance and encodes them.\n */\n static [$filter] (ref: MapSchema, index: number, view: StateView) {\n return (\n !view ||\n typeof (ref[$childType]) === \"string\" ||\n view.isChangeTreeVisible((ref[$getByIndex](index) ?? ref.deletedItems[index])[$changes])\n );\n }\n\n static is(type: any) {\n return type['map'] !== undefined;\n }\n\n constructor (initialValues?: Map<K, V> | Record<K, V>) {\n this[$changes] = new ChangeTree(this);\n this[$changes].indexes = {};\n\n if (initialValues) {\n if (\n initialValues instanceof Map ||\n initialValues instanceof MapSchema\n ) {\n initialValues.forEach((v, k) => this.set(k, v));\n\n } else {\n for (const k in initialValues) {\n this.set(k, initialValues[k]);\n }\n }\n }\n\n Object.defineProperty(this, $childType, {\n value: undefined,\n enumerable: false,\n writable: true,\n configurable: true,\n });\n }\n\n /** Iterator */\n [Symbol.iterator](): IterableIterator<[K, V]> { return this.$items[Symbol.iterator](); }\n get [Symbol.toStringTag]() { return this.$items[Symbol.toStringTag] }\n\n static get [Symbol.species]() { return MapSchema; }\n\n set(key: K, value: V) {\n if (value === undefined || value === null) {\n throw new Error(`MapSchema#set('${key}', ${value}): trying to set ${value} value on '${key}'.`);\n\n } else if (typeof(value) === \"object\" && this[$childType]) {\n assertInstanceType(value as any, this[$childType] as typeof Schema, this, key);\n }\n\n // Force \"key\" as string\n // See: https://github.com/colyseus/colyseus/issues/561#issuecomment-1646733468\n key = key.toString() as K;\n\n const changeTree = this[$changes];\n const isRef = (value[$changes]) !== undefined;\n\n let index: number;\n let operation: OPERATION;\n\n // IS REPLACE?\n if (typeof(changeTree.indexes[key]) !== \"undefined\") {\n index = changeTree.indexes[key];\n operation = OPERATION.REPLACE;\n\n const previousValue = this.$items.get(key);\n if (previousValue === value) {\n // if value is the same, avoid re-encoding it.\n return;\n\n } else if (isRef) {\n // if is schema, force ADD operation if value differ from previous one.\n operation = OPERATION.DELETE_AND_ADD;\n\n // remove reference from previous value\n if (previousValue !== undefined) {\n previousValue[$changes].root?.remove(previousValue[$changes]);\n }\n }\n\n } else {\n index = changeTree.indexes[$numFields] ?? 0;\n operation = OPERATION.ADD;\n\n this.$indexes.set(index, key);\n changeTree.indexes[key] = index;\n changeTree.indexes[$numFields] = index + 1;\n }\n\n this.$items.set(key, value);\n\n changeTree.change(index, operation);\n\n //\n // set value's parent after the value is set\n // (to avoid encoding \"refId\" operations before parent's \"ADD\" operation)\n //\n if (isRef) {\n value[$changes].setParent(this, changeTree.root, index);\n }\n\n return this;\n }\n\n get(key: K): V | undefined {\n return this.$items.get(key);\n }\n\n delete(key: K) {\n const index = this[$changes].indexes[key];\n\n this.deletedItems[index] = this[$changes].delete(index);\n\n return this.$items.delete(key);\n }\n\n clear() {\n const changeTree = this[$changes];\n\n // discard previous operations.\n changeTree.discard(true);\n changeTree.indexes = {};\n\n // clear previous indexes\n this.$indexes.clear();\n\n // clear items\n this.$items.clear();\n\n changeTree.operation(OPERATION.CLEAR);\n }\n\n has (key: K) {\n return this.$items.has(key);\n }\n\n forEach(callbackfn: (value: V, key: K, map: Map<K, V>) => void) {\n this.$items.forEach(callbackfn);\n }\n\n entries () {\n return this.$items.entries();\n }\n\n keys () {\n return this.$items.keys();\n }\n\n values() {\n return this.$items.values();\n }\n\n get size () {\n return this.$items.size;\n }\n\n protected setIndex(index: number, key: K) {\n this.$indexes.set(index, key);\n }\n\n protected getIndex(index: number) {\n return this.$indexes.get(index);\n }\n\n protected [$getByIndex](index: number) {\n return this.$items.get(this.$indexes.get(index));\n }\n\n protected [$deleteByIndex](index: number) {\n const key = this.$indexes.get(index);\n this.$items.delete(key);\n this.$indexes.delete(index);\n }\n\n protected [$onEncodeEnd]() {\n this.deletedItems = {};\n }\n\n toJSON() {\n const map: any = {};\n\n this.forEach((value, key) => {\n map[key] = (typeof (value['toJSON']) === \"function\")\n ? value['toJSON']()\n : value;\n });\n\n return map;\n }\n\n //\n // Decoding utilities\n //\n // @ts-ignore\n clone(isDecoding?: boolean): MapSchema<V> {\n let cloned: MapSchema<V>;\n\n if (isDecoding) {\n // client-side\n cloned = Object.assign(new MapSchema(), this);\n\n } else {\n // server-side\n cloned = new MapSchema();\n\n this.forEach((value, key) => {\n if (value[$changes]) {\n cloned.set(key, value['clone']());\n } else {\n cloned.set(key, value);\n }\n })\n\n }\n\n return cloned;\n }\n\n}\n\nregisterType(\"map\", { constructor: MapSchema });"]}
1
+ {"version":3,"file":"MapSchema.js","sourceRoot":"","sources":["../../../src/types/custom/MapSchema.ts"],"names":[],"mappings":"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","sourcesContent":["import { $changes, $childType, $decoder, $deleteByIndex, $onEncodeEnd, $encoder, $filter, $getByIndex, $numFields } from \"../symbols\";\nimport { ChangeTree } from \"../../encoder/ChangeTree\";\nimport { OPERATION } from \"../../encoding/spec\";\nimport { registerType } from \"../registry\";\nimport { Collection } from \"../HelperTypes\";\nimport { decodeKeyValueOperation } from \"../../decoder/DecodeOperation\";\nimport { encodeKeyValueOperation } from \"../../encoder/EncodeOperation\";\nimport type { StateView } from \"../../encoder/StateView\";\nimport type { Schema } from \"../../Schema\";\nimport { assertInstanceType } from \"../../encoding/assert\";\n\nexport class MapSchema<V=any, K extends string = string> implements Map<K, V>, Collection<K, V, [K, V]> {\n protected childType: new () => V;\n\n protected $items: Map<K, V> = new Map<K, V>();\n protected $indexes: Map<number, K> = new Map<number, K>();\n protected deletedItems: { [field: string]: V } = {};\n\n protected [$changes]: ChangeTree;\n\n static [$encoder] = encodeKeyValueOperation;\n static [$decoder] = decodeKeyValueOperation;\n\n /**\n * Determine if a property must be filtered.\n * - If returns false, the property is NOT going to be encoded.\n * - If returns true, the property is going to be encoded.\n *\n * Encoding with \"filters\" happens in two steps:\n * - First, the encoder iterates over all \"not owned\" properties and encodes them.\n * - Then, the encoder iterates over all \"owned\" properties per instance and encodes them.\n */\n static [$filter] (ref: MapSchema, index: number, view: StateView) {\n return (\n !view ||\n typeof (ref[$childType]) === \"string\" ||\n view.isChangeTreeVisible((ref[$getByIndex](index) ?? ref.deletedItems[index])[$changes])\n );\n }\n\n static is(type: any) {\n return type['map'] !== undefined;\n }\n\n constructor (initialValues?: Map<K, V> | Record<K, V>) {\n this[$changes] = new ChangeTree(this);\n this[$changes].indexes = {};\n\n if (initialValues) {\n if (\n initialValues instanceof Map ||\n initialValues instanceof MapSchema\n ) {\n initialValues.forEach((v, k) => this.set(k, v));\n\n } else {\n for (const k in initialValues) {\n this.set(k, initialValues[k]);\n }\n }\n }\n\n Object.defineProperty(this, $childType, {\n value: undefined,\n enumerable: false,\n writable: true,\n configurable: true,\n });\n }\n\n /** Iterator */\n [Symbol.iterator](): IterableIterator<[K, V]> { return this.$items[Symbol.iterator](); }\n get [Symbol.toStringTag]() { return this.$items[Symbol.toStringTag] }\n\n static get [Symbol.species]() { return MapSchema; }\n\n set(key: K, value: V) {\n if (value === undefined || value === null) {\n throw new Error(`MapSchema#set('${key}', ${value}): trying to set ${value} value on '${key}'.`);\n\n } else if (typeof(value) === \"object\" && this[$childType]) {\n assertInstanceType(value as any, this[$childType] as typeof Schema, this, key);\n }\n\n // Force \"key\" as string\n // See: https://github.com/colyseus/colyseus/issues/561#issuecomment-1646733468\n key = key.toString() as K;\n\n const changeTree = this[$changes];\n const isRef = (value[$changes]) !== undefined;\n\n let index: number;\n let operation: OPERATION;\n\n // IS REPLACE?\n if (typeof(changeTree.indexes[key]) !== \"undefined\") {\n index = changeTree.indexes[key];\n operation = OPERATION.REPLACE;\n\n const previousValue = this.$items.get(key);\n if (previousValue === value) {\n // if value is the same, avoid re-encoding it.\n return;\n\n } else if (isRef) {\n // if is schema, force ADD operation if value differ from previous one.\n operation = OPERATION.DELETE_AND_ADD;\n\n // remove reference from previous value\n if (previousValue !== undefined) {\n previousValue[$changes].root?.remove(previousValue[$changes]);\n }\n }\n\n } else {\n index = changeTree.indexes[$numFields] ?? 0;\n operation = OPERATION.ADD;\n\n this.$indexes.set(index, key);\n changeTree.indexes[key] = index;\n changeTree.indexes[$numFields] = index + 1;\n }\n\n this.$items.set(key, value);\n\n changeTree.change(index, operation);\n\n //\n // set value's parent after the value is set\n // (to avoid encoding \"refId\" operations before parent's \"ADD\" operation)\n //\n if (isRef) {\n value[$changes].setParent(this, changeTree.root, index);\n }\n\n return this;\n }\n\n get(key: K): V | undefined {\n return this.$items.get(key);\n }\n\n delete(key: K) {\n const index = this[$changes].indexes[key];\n\n this.deletedItems[index] = this[$changes].delete(index);\n\n return this.$items.delete(key);\n }\n\n clear() {\n const changeTree = this[$changes];\n\n // discard previous operations.\n changeTree.discard(true);\n changeTree.indexes = {};\n\n // remove children references\n changeTree.forEachChild((childChangeTree, _) => {\n changeTree.root?.remove(childChangeTree);\n });\n\n // clear previous indexes\n this.$indexes.clear();\n\n // clear items\n this.$items.clear();\n\n changeTree.operation(OPERATION.CLEAR);\n }\n\n has (key: K) {\n return this.$items.has(key);\n }\n\n forEach(callbackfn: (value: V, key: K, map: Map<K, V>) => void) {\n this.$items.forEach(callbackfn);\n }\n\n entries () {\n return this.$items.entries();\n }\n\n keys () {\n return this.$items.keys();\n }\n\n values() {\n return this.$items.values();\n }\n\n get size () {\n return this.$items.size;\n }\n\n protected setIndex(index: number, key: K) {\n this.$indexes.set(index, key);\n }\n\n protected getIndex(index: number) {\n return this.$indexes.get(index);\n }\n\n protected [$getByIndex](index: number) {\n return this.$items.get(this.$indexes.get(index));\n }\n\n protected [$deleteByIndex](index: number) {\n const key = this.$indexes.get(index);\n this.$items.delete(key);\n this.$indexes.delete(index);\n }\n\n protected [$onEncodeEnd]() {\n this.deletedItems = {};\n }\n\n toJSON() {\n const map: any = {};\n\n this.forEach((value, key) => {\n map[key] = (typeof (value['toJSON']) === \"function\")\n ? value['toJSON']()\n : value;\n });\n\n return map;\n }\n\n //\n // Decoding utilities\n //\n // @ts-ignore\n clone(isDecoding?: boolean): MapSchema<V> {\n let cloned: MapSchema<V>;\n\n if (isDecoding) {\n // client-side\n cloned = Object.assign(new MapSchema(), this);\n\n } else {\n // server-side\n cloned = new MapSchema();\n\n this.forEach((value, key) => {\n if (value[$changes]) {\n cloned.set(key, value['clone']());\n } else {\n cloned.set(key, value);\n }\n })\n\n }\n\n return cloned;\n }\n\n}\n\nregisterType(\"map\", { constructor: MapSchema });"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@colyseus/schema",
3
- "version": "3.0.35",
3
+ "version": "3.0.37",
4
4
  "description": "Binary state serializer with delta encoding for games",
5
5
  "bin": {
6
6
  "schema-codegen": "bin/schema-codegen",
package/src/Schema.ts CHANGED
@@ -158,6 +158,10 @@ export class Schema {
158
158
  return obj as ToJSON<typeof this>;
159
159
  }
160
160
 
161
+ /**
162
+ * Used in tests only
163
+ * @internal
164
+ */
161
165
  discardAllChanges() {
162
166
  this[$changes].discardAll();
163
167
  }
@@ -185,8 +189,12 @@ export class Schema {
185
189
  const changeTree: ChangeTree = ref[$changes];
186
190
  const refId = changeTree.refId;
187
191
 
188
- let output = "";
189
- output += `${getIndent(level)}${ref.constructor.name} (refId: ${refId})${contents}\n`;
192
+ // log reference count if > 1
193
+ const refCount = (changeTree.root?.refCount?.[refId] > 1)
194
+ ? ` [×${changeTree.root.refCount[refId]}]`
195
+ : '';
196
+
197
+ let output = `${getIndent(level)}${ref.constructor.name} (refId: ${refId})${refCount}${contents}\n`;
190
198
 
191
199
  changeTree.forEachChild((childChangeTree) =>
192
200
  output += this.debugRefIds(childChangeTree.ref, showContents, level + 1));
@@ -149,8 +149,8 @@ export class ReferenceTracker {
149
149
  }
150
150
 
151
151
  removeCallback(refId: number, field: string | number, callback: Function) {
152
- const index = this.callbacks?.[refId]?.[field]?.indexOf(callback);
153
- if (index !== -1) {
152
+ const index: number | undefined = this.callbacks?.[refId]?.[field]?.indexOf(callback);
153
+ if (index !== undefined && index !== -1) {
154
154
  spliceOne(this.callbacks[refId][field], index);
155
155
  }
156
156
  }
@@ -160,22 +160,36 @@ export class ChangeTree<T extends Ref=any> {
160
160
  this.root = root;
161
161
  this.checkIsFiltered(this.parent, this.parentIndex);
162
162
 
163
+ //
164
+ // TODO: refactor and possibly unify .setRoot() and .setParent()
165
+ //
166
+
163
167
  // Recursively set root on child structures
164
168
  const metadata: Metadata = this.ref.constructor[Symbol.metadata];
165
169
  if (metadata) {
166
170
  metadata[$refTypeFieldIndexes]?.forEach((index) => {
167
171
  const field = metadata[index as any as number];
168
- const value = this.ref[field.name];
169
- value?.[$changes].setRoot(root);
172
+ const changeTree: ChangeTree = this.ref[field.name]?.[$changes];
173
+ if (changeTree) {
174
+ if (changeTree.root !== root) {
175
+ changeTree.setRoot(root);
176
+ } else {
177
+ root.add(changeTree); // increment refCount
178
+ }
179
+ }
170
180
  });
171
181
 
172
182
  } else if (this.ref[$childType] && typeof(this.ref[$childType]) !== "string") {
173
183
  // MapSchema / ArraySchema, etc.
174
184
  (this.ref as MapSchema).forEach((value, key) => {
175
- value[$changes].setRoot(root);
185
+ const changeTree: ChangeTree = value[$changes];
186
+ if (changeTree.root !== root) {
187
+ changeTree.setRoot(root);
188
+ } else {
189
+ root.add(changeTree); // increment refCount
190
+ }
176
191
  });
177
192
  }
178
-
179
193
  }
180
194
 
181
195
  setParent(
@@ -203,14 +217,19 @@ export class ChangeTree<T extends Ref=any> {
203
217
  if (metadata) {
204
218
  metadata[$refTypeFieldIndexes]?.forEach((index) => {
205
219
  const field = metadata[index as any as number];
206
- const value = this.ref[field.name];
207
- value?.[$changes].setParent(this.ref, root, index);
220
+ const changeTree: ChangeTree = this.ref[field.name]?.[$changes];
221
+ if (changeTree && changeTree.root !== root) {
222
+ changeTree.setParent(this.ref, root, index);
223
+ }
208
224
  });
209
225
 
210
226
  } else if (this.ref[$childType] && typeof(this.ref[$childType]) !== "string") {
211
227
  // MapSchema / ArraySchema, etc.
212
228
  (this.ref as MapSchema).forEach((value, key) => {
213
- value[$changes].setParent(this.ref, root, this.indexes[key] ?? key);
229
+ const changeTree: ChangeTree = value[$changes];
230
+ if (changeTree.root !== root) {
231
+ changeTree.setParent(this.ref, root, this.indexes[key] ?? key);
232
+ }
214
233
  });
215
234
  }
216
235
 
@@ -478,15 +497,12 @@ export class ChangeTree<T extends Ref=any> {
478
497
  this.allFilteredChanges.indexes = {};
479
498
  this.allFilteredChanges.operations.length = 0;
480
499
  }
481
-
482
- // remove children references
483
- this.forEachChild((changeTree, _) =>
484
- this.root?.remove(changeTree));
485
500
  }
486
501
  }
487
502
 
488
503
  /**
489
504
  * Recursively discard all changes from this, and child structures.
505
+ * (Used in tests only)
490
506
  */
491
507
  discardAll() {
492
508
  const keys = Object.keys(this.indexedOperations);
@@ -69,6 +69,8 @@ export class Root {
69
69
 
70
70
  this.refCount[changeTree.refId] = 0;
71
71
 
72
+ changeTree.forEachChild((child, _) => this.remove(child));
73
+
72
74
  } else {
73
75
  this.refCount[changeTree.refId] = refCount;
74
76
 
@@ -90,8 +92,6 @@ export class Root {
90
92
  }
91
93
  }
92
94
 
93
- changeTree.forEachChild((child, _) => this.remove(child));
94
-
95
95
  return refCount;
96
96
  }
97
97
 
@@ -185,9 +185,7 @@ export class ArraySchema<V = any> implements Array<V>, Collection<number, V> {
185
185
 
186
186
  const changeTree = this[$changes];
187
187
 
188
- // values.forEach((value, i) => {
189
-
190
- for (let i = 0, l = values.length; i < values.length; i++, length++) {
188
+ for (let i = 0, l = values.length; i < l; i++, length++) {
191
189
  const value = values[i];
192
190
 
193
191
  if (value === undefined || value === null) {
@@ -211,9 +209,6 @@ export class ArraySchema<V = any> implements Array<V>, Collection<number, V> {
211
209
  value[$changes]?.setParent(this, changeTree.root, length);
212
210
  }
213
211
 
214
- // length++;
215
- // });
216
-
217
212
  return length;
218
213
  }
219
214
 
@@ -310,22 +305,9 @@ export class ArraySchema<V = any> implements Array<V>, Collection<number, V> {
310
305
  // discard previous operations.
311
306
  const changeTree = this[$changes];
312
307
 
313
- // discard children
314
- changeTree.forEachChild((changeTree, _) => {
315
- changeTree.discard(true);
316
-
317
- //
318
- // TODO: add tests with instance sharing + .clear()
319
- // FIXME: this.root? is required because it is being called at decoding time.
320
- //
321
- // TODO: do not use [$changes] at decoding time.
322
- //
323
- const root = changeTree.root;
324
- if (root !== undefined) {
325
- root.removeChangeFromChangeSet("changes", changeTree);
326
- root.removeChangeFromChangeSet("allChanges", changeTree);
327
- root.removeChangeFromChangeSet("allFilteredChanges", changeTree);
328
- }
308
+ // remove children references
309
+ changeTree.forEachChild((childChangeTree, _) => {
310
+ changeTree.root?.remove(childChangeTree);
329
311
  });
330
312
 
331
313
  changeTree.discard(true);
@@ -116,6 +116,11 @@ export class CollectionSchema<V=any> implements Collection<K, V>{
116
116
  changeTree.discard(true);
117
117
  changeTree.indexes = {};
118
118
 
119
+ // remove children references
120
+ changeTree.forEachChild((childChangeTree, _) => {
121
+ changeTree.root?.remove(childChangeTree);
122
+ });
123
+
119
124
  // clear previous indexes
120
125
  this.$indexes.clear();
121
126
 
@@ -155,6 +155,11 @@ export class MapSchema<V=any, K extends string = string> implements Map<K, V>, C
155
155
  changeTree.discard(true);
156
156
  changeTree.indexes = {};
157
157
 
158
+ // remove children references
159
+ changeTree.forEachChild((childChangeTree, _) => {
160
+ changeTree.root?.remove(childChangeTree);
161
+ });
162
+
158
163
  // clear previous indexes
159
164
  this.$indexes.clear();
160
165