@colyseus/schema 3.0.0-alpha.16 → 3.0.0-alpha.18

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.
@@ -146,6 +146,14 @@
146
146
  isDeprecated(metadata, field) {
147
147
  return metadata[field].deprecated === true;
148
148
  },
149
+ init(klass) {
150
+ //
151
+ // Used only to initialize an empty Schema (Encoder#constructor)
152
+ //
153
+ const metadata = {};
154
+ klass.constructor[Symbol.metadata] = metadata;
155
+ Object.defineProperty(metadata, -1, { value: 0, enumerable: false, configurable: true });
156
+ },
149
157
  isValidInstance(klass) {
150
158
  return (klass.constructor[Symbol.metadata] &&
151
159
  Object.prototype.hasOwnProperty.call(klass.constructor[Symbol.metadata], -1));
@@ -3414,6 +3422,10 @@
3414
3422
  setRoot(state) {
3415
3423
  this.root = new Root();
3416
3424
  this.state = state;
3425
+ // Workaround to allow using an empty Schema.
3426
+ if (state.constructor[Symbol.metadata] === undefined) {
3427
+ Metadata.init(state);
3428
+ }
3417
3429
  state[$changes].setRoot(this.root);
3418
3430
  }
3419
3431
  encode(it = { offset: 0 }, view, buffer = this.sharedBuffer, changeTrees = this.root.changes, isEncodeAll = this.root.allChanges === changeTrees) {
@@ -4236,12 +4248,18 @@
4236
4248
  console.warn("StateView#add(), invalid object:", obj);
4237
4249
  return this;
4238
4250
  }
4251
+ // FIXME: ArraySchema/MapSchema does not have metadata
4252
+ const metadata = obj.constructor[Symbol.metadata];
4239
4253
  let changeTree = obj[$changes];
4240
4254
  this.items.add(changeTree);
4241
4255
  // Add children of this ChangeTree to this view
4242
- changeTree.forEachChild((change, _) => this.add(change.ref, tag));
4243
- // FIXME: ArraySchema/MapSchema does not have metadata
4244
- const metadata = obj.constructor[Symbol.metadata];
4256
+ changeTree.forEachChild((change, index) => {
4257
+ // Do not ADD children that don't have the same tag
4258
+ if (metadata && metadata[metadata[index]].tag !== tag) {
4259
+ return;
4260
+ }
4261
+ this.add(change.ref, tag);
4262
+ });
4245
4263
  // add parent ChangeTree's, if they are invisible to this view
4246
4264
  // TODO: REFACTOR addParent()
4247
4265
  this.addParent(changeTree, tag);
@@ -4268,7 +4286,6 @@
4268
4286
  tags = this.tags.get(changeTree);
4269
4287
  }
4270
4288
  tags.add(tag);
4271
- // console.log("BY TAG:", tag);
4272
4289
  // Ref: add tagged properties
4273
4290
  metadata?.[-3]?.[tag]?.forEach((index) => {
4274
4291
  if (changeTree.getChange(index) !== exports.OPERATION.DELETE) {
package/lib/Metadata.d.ts CHANGED
@@ -31,6 +31,7 @@ export declare const Metadata: {
31
31
  [field: string]: DefinitionType;
32
32
  }): void;
33
33
  isDeprecated(metadata: any, field: string): boolean;
34
+ init(klass: any): void;
34
35
  isValidInstance(klass: any): boolean;
35
36
  getFields(klass: any): {};
36
37
  };
package/lib/Metadata.js CHANGED
@@ -75,6 +75,14 @@ exports.Metadata = {
75
75
  isDeprecated(metadata, field) {
76
76
  return metadata[field].deprecated === true;
77
77
  },
78
+ init(klass) {
79
+ //
80
+ // Used only to initialize an empty Schema (Encoder#constructor)
81
+ //
82
+ const metadata = {};
83
+ klass.constructor[Symbol.metadata] = metadata;
84
+ Object.defineProperty(metadata, -1, { value: 0, enumerable: false, configurable: true });
85
+ },
78
86
  isValidInstance(klass) {
79
87
  return (klass.constructor[Symbol.metadata] &&
80
88
  Object.prototype.hasOwnProperty.call(klass.constructor[Symbol.metadata], -1));
@@ -1 +1 @@
1
- {"version":3,"file":"Metadata.js","sourceRoot":"","sources":["../src/Metadata.ts"],"names":[],"mappings":"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","sourcesContent":["import { getPropertyDescriptor, type DefinitionType } from \"./annotations\";\nimport { getType } from \"./types/registry\";\n\nexport type MetadataField = {\n type: DefinitionType,\n index: number,\n tag?: number,\n unreliable?: boolean,\n deprecated?: boolean,\n descriptor?: PropertyDescriptor,\n};\n\nexport type Metadata =\n { [-1]: number; } & // number of fields\n { [-2]: number[]; } & // all field indexes with \"view\" tag\n { [-3]: {[tag: number]: number[]}; } & // field indexes by \"view\" tag\n { [field: number]: string; } & // index => field name\n { [field: string]: MetadataField; } // field name => field metadata\n\nexport const Metadata = {\n\n addField(metadata: any, index: number, field: string, type: DefinitionType, descriptor?: PropertyDescriptor) {\n if (index > 64) {\n throw new Error(`Can't define field '${field}'.\\nSchema instances may only have up to 64 fields.`);\n }\n\n metadata[field] = Object.assign(\n metadata[field] || {}, // avoid overwriting previous field metadata (@owned / @deprecated)\n {\n type: (Array.isArray(type))\n ? { array: type[0] }\n : type,\n index,\n descriptor,\n }\n );\n\n // map -1 as last field index\n Object.defineProperty(metadata, -1, {\n value: index,\n enumerable: false,\n configurable: true\n });\n\n // map index => field name (non enumerable)\n Object.defineProperty(metadata, index, {\n value: field,\n enumerable: false,\n configurable: true,\n });\n },\n\n setTag(metadata: Metadata, fieldName: string, tag: number) {\n // add 'tag' to the field\n const field = metadata[fieldName];\n field.tag = tag;\n\n if (!metadata[-2]) {\n // -2: all field indexes with \"view\" tag\n Object.defineProperty(metadata, -2, {\n value: [],\n enumerable: false,\n configurable: true\n });\n\n // -3: field indexes by \"view\" tag\n Object.defineProperty(metadata, -3, {\n value: {},\n enumerable: false,\n configurable: true\n });\n }\n\n metadata[-2].push(field.index);\n\n if (!metadata[-3][tag]) {\n metadata[-3][tag] = [];\n }\n\n metadata[-3][tag].push(field.index);\n },\n\n setFields(target: any, fields: { [field: string]: DefinitionType }) {\n const metadata = (target.prototype.constructor[Symbol.metadata] ??= {});\n\n // target[$track] = function (changeTree, index: number, operation: OPERATION = OPERATION.ADD) {\n // changeTree.change(index, operation, encodeSchemaOperation);\n // };\n\n // target[$encoder] = encodeSchemaOperation;\n // target[$decoder] = decodeSchemaOperation;\n\n // if (!target.prototype.toJSON) { target.prototype.toJSON = Schema.prototype.toJSON; }\n\n let index = 0;\n for (const field in fields) {\n const type = fields[field];\n\n // FIXME: this code is duplicated from @type() annotation\n const complexTypeKlass = (Array.isArray(type))\n ? getType(\"array\")\n : (typeof(Object.keys(type)[0]) === \"string\") && getType(Object.keys(type)[0]);\n\n Metadata.addField(\n metadata,\n index,\n field,\n type,\n getPropertyDescriptor(`_${field}`, index, type, complexTypeKlass, metadata, field)\n );\n\n index++;\n }\n },\n\n isDeprecated(metadata: any, field: string) {\n return metadata[field].deprecated === true;\n },\n\n isValidInstance(klass: any) {\n return (\n klass.constructor[Symbol.metadata] &&\n Object.prototype.hasOwnProperty.call(klass.constructor[Symbol.metadata], -1) as boolean\n );\n },\n\n getFields(klass: any) {\n const metadata = klass[Symbol.metadata];\n const fields = {};\n for (let i = 0; i <= metadata[-1]; i++) {\n fields[metadata[i]] = metadata[metadata[i]].type;\n }\n return fields;\n }\n}"]}
1
+ {"version":3,"file":"Metadata.js","sourceRoot":"","sources":["../src/Metadata.ts"],"names":[],"mappings":"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","sourcesContent":["import { getPropertyDescriptor, type DefinitionType } from \"./annotations\";\nimport { getType } from \"./types/registry\";\n\nexport type MetadataField = {\n type: DefinitionType,\n index: number,\n tag?: number,\n unreliable?: boolean,\n deprecated?: boolean,\n descriptor?: PropertyDescriptor,\n};\n\nexport type Metadata =\n { [-1]: number; } & // number of fields\n { [-2]: number[]; } & // all field indexes with \"view\" tag\n { [-3]: {[tag: number]: number[]}; } & // field indexes by \"view\" tag\n { [field: number]: string; } & // index => field name\n { [field: string]: MetadataField; } // field name => field metadata\n\nexport const Metadata = {\n\n addField(metadata: any, index: number, field: string, type: DefinitionType, descriptor?: PropertyDescriptor) {\n if (index > 64) {\n throw new Error(`Can't define field '${field}'.\\nSchema instances may only have up to 64 fields.`);\n }\n\n metadata[field] = Object.assign(\n metadata[field] || {}, // avoid overwriting previous field metadata (@owned / @deprecated)\n {\n type: (Array.isArray(type))\n ? { array: type[0] }\n : type,\n index,\n descriptor,\n }\n );\n\n // map -1 as last field index\n Object.defineProperty(metadata, -1, {\n value: index,\n enumerable: false,\n configurable: true\n });\n\n // map index => field name (non enumerable)\n Object.defineProperty(metadata, index, {\n value: field,\n enumerable: false,\n configurable: true,\n });\n },\n\n setTag(metadata: Metadata, fieldName: string, tag: number) {\n // add 'tag' to the field\n const field = metadata[fieldName];\n field.tag = tag;\n\n if (!metadata[-2]) {\n // -2: all field indexes with \"view\" tag\n Object.defineProperty(metadata, -2, {\n value: [],\n enumerable: false,\n configurable: true\n });\n\n // -3: field indexes by \"view\" tag\n Object.defineProperty(metadata, -3, {\n value: {},\n enumerable: false,\n configurable: true\n });\n }\n\n metadata[-2].push(field.index);\n\n if (!metadata[-3][tag]) {\n metadata[-3][tag] = [];\n }\n\n metadata[-3][tag].push(field.index);\n },\n\n setFields(target: any, fields: { [field: string]: DefinitionType }) {\n const metadata = (target.prototype.constructor[Symbol.metadata] ??= {});\n\n // target[$track] = function (changeTree, index: number, operation: OPERATION = OPERATION.ADD) {\n // changeTree.change(index, operation, encodeSchemaOperation);\n // };\n\n // target[$encoder] = encodeSchemaOperation;\n // target[$decoder] = decodeSchemaOperation;\n\n // if (!target.prototype.toJSON) { target.prototype.toJSON = Schema.prototype.toJSON; }\n\n let index = 0;\n for (const field in fields) {\n const type = fields[field];\n\n // FIXME: this code is duplicated from @type() annotation\n const complexTypeKlass = (Array.isArray(type))\n ? getType(\"array\")\n : (typeof(Object.keys(type)[0]) === \"string\") && getType(Object.keys(type)[0]);\n\n Metadata.addField(\n metadata,\n index,\n field,\n type,\n getPropertyDescriptor(`_${field}`, index, type, complexTypeKlass, metadata, field)\n );\n\n index++;\n }\n },\n\n isDeprecated(metadata: any, field: string) {\n return metadata[field].deprecated === true;\n },\n\n init(klass: any) {\n //\n // Used only to initialize an empty Schema (Encoder#constructor)\n //\n const metadata = {};\n klass.constructor[Symbol.metadata] = metadata;\n Object.defineProperty(metadata, -1, { value: 0, enumerable: false, configurable: true });\n },\n\n isValidInstance(klass: any) {\n return (\n klass.constructor[Symbol.metadata] &&\n Object.prototype.hasOwnProperty.call(klass.constructor[Symbol.metadata], -1) as boolean\n );\n },\n\n getFields(klass: any) {\n const metadata = klass[Symbol.metadata];\n const fields = {};\n for (let i = 0; i <= metadata[-1]; i++) {\n fields[metadata[i]] = metadata[metadata[i]].type;\n }\n return fields;\n }\n}"]}
@@ -7,6 +7,7 @@ const encode = require("../encoding/encode");
7
7
  const spec_1 = require("../encoding/spec");
8
8
  const ChangeTree_1 = require("./ChangeTree");
9
9
  const utils_1 = require("../utils");
10
+ const Metadata_1 = require("../Metadata");
10
11
  class Encoder {
11
12
  static { this.BUFFER_SIZE = 8 * 1024; } // 8KB
12
13
  constructor(root) {
@@ -25,6 +26,10 @@ class Encoder {
25
26
  setRoot(state) {
26
27
  this.root = new ChangeTree_1.Root();
27
28
  this.state = state;
29
+ // Workaround to allow using an empty Schema.
30
+ if (state.constructor[Symbol.metadata] === undefined) {
31
+ Metadata_1.Metadata.init(state);
32
+ }
28
33
  state[symbols_1.$changes].setRoot(this.root);
29
34
  }
30
35
  encode(it = { offset: 0 }, view, buffer = this.sharedBuffer, changeTrees = this.root.changes, isEncodeAll = this.root.allChanges === changeTrees) {
@@ -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 \"../annotations\";\nimport { $changes, $encoder, $filter } from \"../types/symbols\";\n\nimport * as encode from \"../encoding/encode\";\nimport type { Iterator } from \"../encoding/decode\";\n\nimport { OPERATION, SWITCH_TO_STRUCTURE, TYPE_ID } from '../encoding/spec';\nimport { Root } from \"./ChangeTree\";\nimport { getNextPowerOf2 } from \"../utils\";\nimport type { StateView } from \"./StateView\";\n\nexport class Encoder<T extends Schema = any> {\n static BUFFER_SIZE = 8 * 1024;// 8KB\n sharedBuffer = Buffer.allocUnsafeSlow(Encoder.BUFFER_SIZE);\n\n context: TypeContext;\n state: T;\n\n root: Root;\n\n constructor(root: T) {\n this.setRoot(root);\n\n //\n // TODO: cache and restore \"Context\" based on root schema\n // (to avoid creating a new context for every new room)\n //\n this.context = new TypeContext(root.constructor as typeof Schema);\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 setRoot(state: T) {\n this.root = new Root();\n this.state = state;\n state[$changes].setRoot(this.root);\n }\n\n encode(\n it: Iterator = { offset: 0 },\n view?: StateView,\n buffer = this.sharedBuffer,\n changeTrees = this.root.changes,\n isEncodeAll = this.root.allChanges === changeTrees,\n ): Buffer {\n const initialOffset = it.offset; // cache current offset in case we need to resize the buffer\n\n const hasView = (view !== undefined);\n const rootChangeTree = this.state[$changes];\n\n const changeTreesIterator = changeTrees.entries();\n\n for (const [changeTree, changes] of changeTreesIterator) {\n const ref = changeTree.ref;\n\n const ctor = ref['constructor'];\n const encoder = ctor[$encoder];\n const filter = ctor[$filter];\n\n // try { throw new Error(); } catch (e) {\n // // only print if not coming from Reflection.ts\n // if (!e.stack.includes(\"src/Reflection.ts\")) {\n // console.log(\"ChangeTree:\", { ref: ref.constructor.name, });\n // }\n // }\n\n if (hasView) {\n if (!view.items.has(changeTree)) {\n view.invisible.add(changeTree);\n continue; // skip this change tree\n\n } else if (view.invisible.has(changeTree)) {\n view.invisible.delete(changeTree); // remove from invisible list\n }\n }\n\n // skip root `refId` if it's the first change tree\n if (it.offset !== initialOffset || changeTree !== rootChangeTree) {\n buffer[it.offset++] = SWITCH_TO_STRUCTURE & 255;\n encode.number(buffer, changeTree.refId, it);\n }\n\n const changesIterator = changes.entries();\n\n for (const [fieldIndex, operation] of changesIterator) {\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 (filter && !filter(ref, fieldIndex, view)) {\n // console.log(\"SKIP FIELD:\", { ref: changeTree.ref.constructor.name, fieldIndex, })\n\n // console.log(\"ADD AS INVISIBLE:\", fieldIndex, changeTree.ref.constructor.name)\n // view?.invisible.add(changeTree);\n continue;\n }\n\n // try { throw new Error(); } catch (e) {\n // // only print if not coming from Reflection.ts\n // if (!e.stack.includes(\"src/Reflection.ts\")) {\n // // console.log(\"WILL ENCODE\", {\n // // ref: changeTree.ref.constructor.name,\n // // fieldIndex,\n // // operation: OPERATION[operation],\n // // });\n // }\n // }\n\n encoder(this, buffer, changeTree, fieldIndex, operation, it, isEncodeAll, hasView);\n }\n }\n\n if (it.offset > buffer.byteLength) {\n const newSize = getNextPowerOf2(buffer.byteLength * 2);\n console.warn(\"@colyseus/schema encode buffer overflow. Current buffer size: \" + buffer.byteLength + \", encoding offset: \" + it.offset + \", new size: \" + newSize);\n\n //\n // resize buffer and re-encode (TODO: can we avoid re-encoding here?)\n //\n buffer = Buffer.allocUnsafeSlow(newSize);\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, changeTrees, isEncodeAll);\n\n } else {\n //\n // only clear changes after making sure buffer resize is not required.\n //\n if (!isEncodeAll && !hasView) {\n //\n // FIXME: avoid iterating over change trees twice.\n //\n this.onEndEncode(changeTrees);\n }\n\n return buffer.subarray(0, it.offset);\n }\n }\n\n encodeAll(it: Iterator = { offset: 0 }, buffer: Buffer = this.sharedBuffer) {\n // console.log(`encodeAll(), this.root.allChanges (${this.root.allChanges.size})`);\n\n // Array.from(this.root.allChanges.entries()).map((item) => {\n // console.log(\"->\", { ref: item[0].ref.constructor.name, refId: item[0].refId, changes: item[1].size });\n // });\n\n return this.encode(it, undefined, buffer, this.root.allChanges, true);\n }\n\n encodeAllView(view: StateView, sharedOffset: number, it: Iterator, bytes = this.sharedBuffer) {\n const viewOffset = it.offset;\n\n // console.log(`encodeAllView(), this.root.allFilteredChanges (${this.root.allFilteredChanges.size})`);\n // this.debugAllFilteredChanges();\n\n // try to encode \"filtered\" changes\n this.encode(it, view, bytes, this.root.allFilteredChanges, true);\n\n return Buffer.concat([\n bytes.subarray(0, sharedOffset),\n bytes.subarray(viewOffset, it.offset)\n ]);\n }\n\n\n debugAllFilteredChanges() {\n Array.from(this.root.allFilteredChanges.entries()).map((item) => {\n console.log(\"->\", { refId: item[0].refId, changes: item[1].size }, item[0].ref.toJSON());\n if (Array.isArray(item[0].ref.toJSON())) {\n item[1].forEach((op, key) => {\n console.log(\" ->\", { key, op: OPERATION[op] });\n })\n }\n });\n }\n\n encodeView(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, this.root.filteredChanges);\n\n // encode visibility changes (add/remove for this view)\n const viewChangesIterator = view.changes.entries();\n for (const [changeTree, changes] of viewChangesIterator) {\n if (changes.size === 0) {\n // FIXME: avoid having empty changes if no changes were made\n // console.log(\"changes.size === 0\", 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\n bytes[it.offset++] = SWITCH_TO_STRUCTURE & 255;\n encode.number(bytes, changeTree.refId, it);\n\n const changesIterator = changes.entries();\n\n for (const [fieldIndex, operation] of changesIterator) {\n // isEncodeAll = false\n // hasView = true\n encoder(this, bytes, changeTree, fieldIndex, operation, it, false, true);\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 return Buffer.concat([\n bytes.subarray(0, sharedOffset),\n bytes.subarray(viewOffset, it.offset)\n ]);\n }\n\n onEndEncode(changeTrees = this.root.changes) {\n const changeTreesIterator = changeTrees.entries();\n for (const [changeTree, _] of changeTreesIterator) {\n changeTree.endEncode();\n }\n }\n\n discardChanges() {\n // discard shared changes\n if (this.root.changes.size > 0) {\n this.onEndEncode(this.root.changes);\n this.root.changes.clear();\n }\n // discard filtered changes\n if (this.root.filteredChanges.size > 0) {\n this.onEndEncode(this.root.filteredChanges);\n this.root.filteredChanges.clear();\n }\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 (baseTypeId !== targetTypeId) {\n bytes[it.offset++] = TYPE_ID & 255;\n encode.number(bytes, targetTypeId, it);\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 \"../annotations\";\nimport { $changes, $encoder, $filter } from \"../types/symbols\";\n\nimport * as encode from \"../encoding/encode\";\nimport type { Iterator } from \"../encoding/decode\";\n\nimport { OPERATION, SWITCH_TO_STRUCTURE, TYPE_ID } from '../encoding/spec';\nimport { Root } from \"./ChangeTree\";\nimport { getNextPowerOf2 } from \"../utils\";\nimport type { StateView } from \"./StateView\";\nimport { Metadata } from \"../Metadata\";\n\nexport class Encoder<T extends Schema = any> {\n static BUFFER_SIZE = 8 * 1024;// 8KB\n sharedBuffer = Buffer.allocUnsafeSlow(Encoder.BUFFER_SIZE);\n\n context: TypeContext;\n state: T;\n\n root: Root;\n\n constructor(root: T) {\n this.setRoot(root);\n\n //\n // TODO: cache and restore \"Context\" based on root schema\n // (to avoid creating a new context for every new room)\n //\n this.context = new TypeContext(root.constructor as typeof Schema);\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 setRoot(state: T) {\n this.root = new Root();\n this.state = state;\n\n // Workaround to allow using an empty Schema.\n if (state.constructor[Symbol.metadata] === undefined) {\n Metadata.init(state);\n }\n\n state[$changes].setRoot(this.root);\n }\n\n encode(\n it: Iterator = { offset: 0 },\n view?: StateView,\n buffer = this.sharedBuffer,\n changeTrees = this.root.changes,\n isEncodeAll = this.root.allChanges === changeTrees,\n ): Buffer {\n const initialOffset = it.offset; // cache current offset in case we need to resize the buffer\n\n const hasView = (view !== undefined);\n const rootChangeTree = this.state[$changes];\n\n const changeTreesIterator = changeTrees.entries();\n\n for (const [changeTree, changes] of changeTreesIterator) {\n const ref = changeTree.ref;\n\n const ctor = ref['constructor'];\n const encoder = ctor[$encoder];\n const filter = ctor[$filter];\n\n // try { throw new Error(); } catch (e) {\n // // only print if not coming from Reflection.ts\n // if (!e.stack.includes(\"src/Reflection.ts\")) {\n // console.log(\"ChangeTree:\", { ref: ref.constructor.name, });\n // }\n // }\n\n if (hasView) {\n if (!view.items.has(changeTree)) {\n view.invisible.add(changeTree);\n continue; // skip this change tree\n\n } else if (view.invisible.has(changeTree)) {\n view.invisible.delete(changeTree); // remove from invisible list\n }\n }\n\n // skip root `refId` if it's the first change tree\n if (it.offset !== initialOffset || changeTree !== rootChangeTree) {\n buffer[it.offset++] = SWITCH_TO_STRUCTURE & 255;\n encode.number(buffer, changeTree.refId, it);\n }\n\n const changesIterator = changes.entries();\n\n for (const [fieldIndex, operation] of changesIterator) {\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 (filter && !filter(ref, fieldIndex, view)) {\n // console.log(\"SKIP FIELD:\", { ref: changeTree.ref.constructor.name, fieldIndex, })\n\n // console.log(\"ADD AS INVISIBLE:\", fieldIndex, changeTree.ref.constructor.name)\n // view?.invisible.add(changeTree);\n continue;\n }\n\n // try { throw new Error(); } catch (e) {\n // // only print if not coming from Reflection.ts\n // if (!e.stack.includes(\"src/Reflection.ts\")) {\n // // console.log(\"WILL ENCODE\", {\n // // ref: changeTree.ref.constructor.name,\n // // fieldIndex,\n // // operation: OPERATION[operation],\n // // });\n // }\n // }\n\n encoder(this, buffer, changeTree, fieldIndex, operation, it, isEncodeAll, hasView);\n }\n }\n\n if (it.offset > buffer.byteLength) {\n const newSize = getNextPowerOf2(buffer.byteLength * 2);\n console.warn(\"@colyseus/schema encode buffer overflow. Current buffer size: \" + buffer.byteLength + \", encoding offset: \" + it.offset + \", new size: \" + newSize);\n\n //\n // resize buffer and re-encode (TODO: can we avoid re-encoding here?)\n //\n buffer = Buffer.allocUnsafeSlow(newSize);\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, changeTrees, isEncodeAll);\n\n } else {\n //\n // only clear changes after making sure buffer resize is not required.\n //\n if (!isEncodeAll && !hasView) {\n //\n // FIXME: avoid iterating over change trees twice.\n //\n this.onEndEncode(changeTrees);\n }\n\n return buffer.subarray(0, it.offset);\n }\n }\n\n encodeAll(it: Iterator = { offset: 0 }, buffer: Buffer = this.sharedBuffer) {\n // console.log(`encodeAll(), this.root.allChanges (${this.root.allChanges.size})`);\n\n // Array.from(this.root.allChanges.entries()).map((item) => {\n // console.log(\"->\", { ref: item[0].ref.constructor.name, refId: item[0].refId, changes: item[1].size });\n // });\n\n return this.encode(it, undefined, buffer, this.root.allChanges, true);\n }\n\n encodeAllView(view: StateView, sharedOffset: number, it: Iterator, bytes = this.sharedBuffer) {\n const viewOffset = it.offset;\n\n // console.log(`encodeAllView(), this.root.allFilteredChanges (${this.root.allFilteredChanges.size})`);\n // this.debugAllFilteredChanges();\n\n // try to encode \"filtered\" changes\n this.encode(it, view, bytes, this.root.allFilteredChanges, true);\n\n return Buffer.concat([\n bytes.subarray(0, sharedOffset),\n bytes.subarray(viewOffset, it.offset)\n ]);\n }\n\n\n debugAllFilteredChanges() {\n Array.from(this.root.allFilteredChanges.entries()).map((item) => {\n console.log(\"->\", { refId: item[0].refId, changes: item[1].size }, item[0].ref.toJSON());\n if (Array.isArray(item[0].ref.toJSON())) {\n item[1].forEach((op, key) => {\n console.log(\" ->\", { key, op: OPERATION[op] });\n })\n }\n });\n }\n\n encodeView(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, this.root.filteredChanges);\n\n // encode visibility changes (add/remove for this view)\n const viewChangesIterator = view.changes.entries();\n for (const [changeTree, changes] of viewChangesIterator) {\n if (changes.size === 0) {\n // FIXME: avoid having empty changes if no changes were made\n // console.log(\"changes.size === 0\", 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\n bytes[it.offset++] = SWITCH_TO_STRUCTURE & 255;\n encode.number(bytes, changeTree.refId, it);\n\n const changesIterator = changes.entries();\n\n for (const [fieldIndex, operation] of changesIterator) {\n // isEncodeAll = false\n // hasView = true\n encoder(this, bytes, changeTree, fieldIndex, operation, it, false, true);\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 return Buffer.concat([\n bytes.subarray(0, sharedOffset),\n bytes.subarray(viewOffset, it.offset)\n ]);\n }\n\n onEndEncode(changeTrees = this.root.changes) {\n const changeTreesIterator = changeTrees.entries();\n for (const [changeTree, _] of changeTreesIterator) {\n changeTree.endEncode();\n }\n }\n\n discardChanges() {\n // discard shared changes\n if (this.root.changes.size > 0) {\n this.onEndEncode(this.root.changes);\n this.root.changes.clear();\n }\n // discard filtered changes\n if (this.root.filteredChanges.size > 0) {\n this.onEndEncode(this.root.filteredChanges);\n this.root.filteredChanges.clear();\n }\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 (baseTypeId !== targetTypeId) {\n bytes[it.offset++] = TYPE_ID & 255;\n encode.number(bytes, targetTypeId, it);\n }\n }\n}"]}
@@ -30,12 +30,18 @@ class StateView {
30
30
  console.warn("StateView#add(), invalid object:", obj);
31
31
  return this;
32
32
  }
33
+ // FIXME: ArraySchema/MapSchema does not have metadata
34
+ const metadata = obj.constructor[Symbol.metadata];
33
35
  let changeTree = obj[symbols_1.$changes];
34
36
  this.items.add(changeTree);
35
37
  // Add children of this ChangeTree to this view
36
- changeTree.forEachChild((change, _) => this.add(change.ref, tag));
37
- // FIXME: ArraySchema/MapSchema does not have metadata
38
- const metadata = obj.constructor[Symbol.metadata];
38
+ changeTree.forEachChild((change, index) => {
39
+ // Do not ADD children that don't have the same tag
40
+ if (metadata && metadata[metadata[index]].tag !== tag) {
41
+ return;
42
+ }
43
+ this.add(change.ref, tag);
44
+ });
39
45
  // add parent ChangeTree's, if they are invisible to this view
40
46
  // TODO: REFACTOR addParent()
41
47
  this.addParent(changeTree, tag);
@@ -62,7 +68,6 @@ class StateView {
62
68
  tags = this.tags.get(changeTree);
63
69
  }
64
70
  tags.add(tag);
65
- // console.log("BY TAG:", tag);
66
71
  // Ref: add tagged properties
67
72
  metadata?.[-3]?.[tag]?.forEach((index) => {
68
73
  if (changeTree.getChange(index) !== spec_1.OPERATION.DELETE) {
@@ -1 +1 @@
1
- {"version":3,"file":"StateView.js","sourceRoot":"","sources":["../../src/encoder/StateView.ts"],"names":[],"mappings":"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","sourcesContent":["import { ChangeTree, Ref } from \"./ChangeTree\";\nimport { $changes } from \"../types/symbols\";\nimport { DEFAULT_VIEW_TAG } from \"../annotations\";\nimport { OPERATION } from \"../encoding/spec\";\nimport { Metadata } from \"../Metadata\";\nimport type { Schema } from \"../Schema\";\n\nexport function createView(root: Schema) {\n}\n\nexport class StateView {\n /**\n * List of ChangeTree's that are visible to this view\n */\n items: WeakSet<ChangeTree> = new WeakSet<ChangeTree>();\n\n /**\n * List of ChangeTree's that are invisible to this view\n */\n invisible: WeakSet<ChangeTree> = new WeakSet<ChangeTree>();\n\n tags?: WeakMap<ChangeTree, Set<number>>; // TODO: use bit manipulation instead of Set<number> ()\n\n /**\n * Manual \"ADD\" operations for changes per ChangeTree, specific to this view.\n * (This is used to force encoding a property, even if it was not changed)\n */\n changes = new Map<ChangeTree, Map<number, OPERATION>>();\n\n // TODO: allow to set multiple tags at once\n add(obj: Ref, tag: number = DEFAULT_VIEW_TAG) {\n if (!obj[$changes]) {\n console.warn(\"StateView#add(), invalid object:\", obj);\n return this;\n }\n\n let changeTree: ChangeTree = obj[$changes];\n this.items.add(changeTree);\n\n // Add children of this ChangeTree to this view\n changeTree.forEachChild((change, _) =>\n this.add(change.ref, tag));\n\n // FIXME: ArraySchema/MapSchema does not have metadata\n const metadata: Metadata = obj.constructor[Symbol.metadata];\n\n // add parent ChangeTree's, if they are invisible to this view\n // TODO: REFACTOR addParent()\n this.addParent(changeTree, tag);\n\n //\n // TODO: when adding an item of a MapSchema, the changes may not\n // be set (only the parent's changes are set)\n //\n let changes = this.changes.get(changeTree);\n if (changes === undefined) {\n changes = new Map<number, OPERATION>();\n this.changes.set(changeTree, changes)\n }\n\n // set tag\n if (tag !== DEFAULT_VIEW_TAG) {\n if (!this.tags) {\n this.tags = new WeakMap<ChangeTree, Set<number>>();\n }\n let tags: Set<number>;\n if (!this.tags.has(changeTree)) {\n tags = new Set<number>();\n this.tags.set(changeTree, tags);\n } else {\n tags = this.tags.get(changeTree);\n }\n tags.add(tag);\n\n // console.log(\"BY TAG:\", tag);\n\n // Ref: add tagged properties\n metadata?.[-3]?.[tag]?.forEach((index) => {\n if (changeTree.getChange(index) !== OPERATION.DELETE) {\n changes.set(index, OPERATION.ADD)\n }\n });\n\n } else {\n\n // console.log(\"DEFAULT TAG\", changeTree.allChanges);\n\n // // add default tag properties\n // metadata?.[-3]?.[DEFAULT_VIEW_TAG]?.forEach((index) => {\n // if (changeTree.getChange(index) !== OPERATION.DELETE) {\n // changes.set(index, OPERATION.ADD);\n // }\n // });\n\n const allChangesSet = (changeTree.isFiltered || changeTree.isPartiallyFiltered)\n ? changeTree.allFilteredChanges\n : changeTree.allChanges;\n const it = allChangesSet.keys();\n const isInvisible = this.invisible.has(changeTree);\n\n for (const index of it) {\n if (\n (isInvisible || metadata?.[metadata?.[index]].tag === tag) &&\n changeTree.getChange(index) !== OPERATION.DELETE\n ) {\n changes.set(index, OPERATION.ADD);\n }\n }\n }\n\n // TODO: avoid unnecessary iteration here\n while (\n changeTree.parent &&\n (changeTree = changeTree.parent[$changes]) &&\n (changeTree.isFiltered || changeTree.isPartiallyFiltered)\n ) {\n this.items.add(changeTree);\n }\n\n return this;\n }\n\n protected addParent(changeTree: ChangeTree, tag: number) {\n const parentRef = changeTree.parent;\n if (!parentRef) { return; }\n\n const parentChangeTree = parentRef[$changes];\n const parentIndex = changeTree.parentIndex;\n\n if (!this.invisible.has(parentChangeTree)) {\n // parent is already available, no need to add it!\n return;\n }\n\n this.addParent(parentChangeTree, tag);\n\n // add parent's tag properties\n if (parentChangeTree.getChange(parentIndex) !== OPERATION.DELETE) {\n\n let parentChanges = this.changes.get(parentChangeTree);\n if (parentChanges === undefined) {\n parentChanges = new Map<number, OPERATION>();\n this.changes.set(parentChangeTree, parentChanges);\n }\n\n // console.log(\"add parent change\", {\n // parentIndex,\n // parentChanges,\n // parentChange: (\n // parentChangeTree.getChange(parentIndex) &&\n // OPERATION[parentChangeTree.getChange(parentIndex)]\n // ),\n // })\n\n if (!this.tags) { this.tags = new WeakMap<ChangeTree, Set<number>>(); }\n let tags: Set<number>;\n if (!this.tags.has(parentChangeTree)) {\n tags = new Set<number>();\n this.tags.set(parentChangeTree, tags);\n } else {\n tags = this.tags.get(parentChangeTree);\n }\n tags.add(tag);\n\n parentChanges.set(parentIndex, OPERATION.ADD);\n }\n\n }\n\n remove(obj: Ref, tag: number = DEFAULT_VIEW_TAG) {\n const changeTree = obj[$changes];\n if (!changeTree) {\n console.warn(\"StateView#remove(), invalid object:\", obj);\n return this;\n }\n\n this.items.delete(changeTree);\n\n const ref = changeTree.ref;\n const metadata: Metadata = ref.constructor[Symbol.metadata];\n\n let changes = this.changes.get(changeTree);\n if (changes === undefined) {\n changes = new Map<number, OPERATION>();\n this.changes.set(changeTree, changes)\n }\n\n if (tag === DEFAULT_VIEW_TAG) {\n // parent is collection (Map/Array)\n const parent = changeTree.parent;\n if (!Metadata.isValidInstance(parent)) {\n const parentChangeTree = parent[$changes];\n let changes = this.changes.get(parentChangeTree);\n if (changes === undefined) {\n changes = new Map<number, OPERATION>();\n this.changes.set(parentChangeTree, changes)\n }\n // DELETE / DELETE BY REF ID\n changes.set(changeTree.parentIndex, OPERATION.DELETE);\n\n } else {\n // delete all \"tagged\" properties.\n metadata[-2].forEach((index) =>\n changes.set(index, OPERATION.DELETE));\n }\n\n\n } else {\n // delete only tagged properties\n metadata[-3][tag].forEach((index) =>\n changes.set(index, OPERATION.DELETE));\n }\n\n // remove tag\n if (this.tags && this.tags.has(changeTree)) {\n const tags = this.tags.get(changeTree);\n if (tag === undefined) {\n // delete all tags\n this.tags.delete(changeTree);\n } else {\n // delete specific tag\n tags.delete(tag);\n\n // if tag set is empty, delete it entirely\n if (tags.size === 0) {\n this.tags.delete(changeTree);\n }\n }\n }\n\n return this;\n }\n}"]}
1
+ {"version":3,"file":"StateView.js","sourceRoot":"","sources":["../../src/encoder/StateView.ts"],"names":[],"mappings":"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","sourcesContent":["import { ChangeTree, Ref } from \"./ChangeTree\";\nimport { $changes } from \"../types/symbols\";\nimport { DEFAULT_VIEW_TAG } from \"../annotations\";\nimport { OPERATION } from \"../encoding/spec\";\nimport { Metadata } from \"../Metadata\";\nimport type { Schema } from \"../Schema\";\n\nexport function createView(root: Schema) {\n}\n\nexport class StateView {\n /**\n * List of ChangeTree's that are visible to this view\n */\n items: WeakSet<ChangeTree> = new WeakSet<ChangeTree>();\n\n /**\n * List of ChangeTree's that are invisible to this view\n */\n invisible: WeakSet<ChangeTree> = new WeakSet<ChangeTree>();\n\n tags?: WeakMap<ChangeTree, Set<number>>; // TODO: use bit manipulation instead of Set<number> ()\n\n /**\n * Manual \"ADD\" operations for changes per ChangeTree, specific to this view.\n * (This is used to force encoding a property, even if it was not changed)\n */\n changes = new Map<ChangeTree, Map<number, OPERATION>>();\n\n // TODO: allow to set multiple tags at once\n add(obj: Ref, tag: number = DEFAULT_VIEW_TAG) {\n if (!obj[$changes]) {\n console.warn(\"StateView#add(), invalid object:\", obj);\n return this;\n }\n\n // FIXME: ArraySchema/MapSchema does not have metadata\n const metadata: Metadata = obj.constructor[Symbol.metadata];\n\n let changeTree: ChangeTree = obj[$changes];\n this.items.add(changeTree);\n\n // Add children of this ChangeTree to this view\n changeTree.forEachChild((change, index) => {\n // Do not ADD children that don't have the same tag\n if (metadata && metadata[metadata[index]].tag !== tag) {\n return;\n }\n this.add(change.ref, tag);\n });\n\n // add parent ChangeTree's, if they are invisible to this view\n // TODO: REFACTOR addParent()\n this.addParent(changeTree, tag);\n\n //\n // TODO: when adding an item of a MapSchema, the changes may not\n // be set (only the parent's changes are set)\n //\n let changes = this.changes.get(changeTree);\n if (changes === undefined) {\n changes = new Map<number, OPERATION>();\n this.changes.set(changeTree, changes)\n }\n\n // set tag\n if (tag !== DEFAULT_VIEW_TAG) {\n if (!this.tags) {\n this.tags = new WeakMap<ChangeTree, Set<number>>();\n }\n let tags: Set<number>;\n if (!this.tags.has(changeTree)) {\n tags = new Set<number>();\n this.tags.set(changeTree, tags);\n } else {\n tags = this.tags.get(changeTree);\n }\n tags.add(tag);\n\n // Ref: add tagged properties\n metadata?.[-3]?.[tag]?.forEach((index) => {\n if (changeTree.getChange(index) !== OPERATION.DELETE) {\n changes.set(index, OPERATION.ADD)\n }\n });\n\n } else {\n\n // console.log(\"DEFAULT TAG\", changeTree.allChanges);\n\n // // add default tag properties\n // metadata?.[-3]?.[DEFAULT_VIEW_TAG]?.forEach((index) => {\n // if (changeTree.getChange(index) !== OPERATION.DELETE) {\n // changes.set(index, OPERATION.ADD);\n // }\n // });\n\n const allChangesSet = (changeTree.isFiltered || changeTree.isPartiallyFiltered)\n ? changeTree.allFilteredChanges\n : changeTree.allChanges;\n const it = allChangesSet.keys();\n const isInvisible = this.invisible.has(changeTree);\n\n for (const index of it) {\n if (\n (isInvisible || metadata?.[metadata?.[index]].tag === tag) &&\n changeTree.getChange(index) !== OPERATION.DELETE\n ) {\n changes.set(index, OPERATION.ADD);\n }\n }\n }\n\n // TODO: avoid unnecessary iteration here\n while (\n changeTree.parent &&\n (changeTree = changeTree.parent[$changes]) &&\n (changeTree.isFiltered || changeTree.isPartiallyFiltered)\n ) {\n this.items.add(changeTree);\n }\n\n return this;\n }\n\n protected addParent(changeTree: ChangeTree, tag: number) {\n const parentRef = changeTree.parent;\n if (!parentRef) { return; }\n\n const parentChangeTree = parentRef[$changes];\n const parentIndex = changeTree.parentIndex;\n\n if (!this.invisible.has(parentChangeTree)) {\n // parent is already available, no need to add it!\n return;\n }\n\n this.addParent(parentChangeTree, tag);\n\n // add parent's tag properties\n if (parentChangeTree.getChange(parentIndex) !== OPERATION.DELETE) {\n\n let parentChanges = this.changes.get(parentChangeTree);\n if (parentChanges === undefined) {\n parentChanges = new Map<number, OPERATION>();\n this.changes.set(parentChangeTree, parentChanges);\n }\n\n // console.log(\"add parent change\", {\n // parentIndex,\n // parentChanges,\n // parentChange: (\n // parentChangeTree.getChange(parentIndex) &&\n // OPERATION[parentChangeTree.getChange(parentIndex)]\n // ),\n // })\n\n if (!this.tags) { this.tags = new WeakMap<ChangeTree, Set<number>>(); }\n let tags: Set<number>;\n if (!this.tags.has(parentChangeTree)) {\n tags = new Set<number>();\n this.tags.set(parentChangeTree, tags);\n } else {\n tags = this.tags.get(parentChangeTree);\n }\n tags.add(tag);\n\n parentChanges.set(parentIndex, OPERATION.ADD);\n }\n\n }\n\n remove(obj: Ref, tag: number = DEFAULT_VIEW_TAG) {\n const changeTree = obj[$changes];\n if (!changeTree) {\n console.warn(\"StateView#remove(), invalid object:\", obj);\n return this;\n }\n\n this.items.delete(changeTree);\n\n const ref = changeTree.ref;\n const metadata: Metadata = ref.constructor[Symbol.metadata];\n\n let changes = this.changes.get(changeTree);\n if (changes === undefined) {\n changes = new Map<number, OPERATION>();\n this.changes.set(changeTree, changes)\n }\n\n if (tag === DEFAULT_VIEW_TAG) {\n // parent is collection (Map/Array)\n const parent = changeTree.parent;\n if (!Metadata.isValidInstance(parent)) {\n const parentChangeTree = parent[$changes];\n let changes = this.changes.get(parentChangeTree);\n if (changes === undefined) {\n changes = new Map<number, OPERATION>();\n this.changes.set(parentChangeTree, changes)\n }\n // DELETE / DELETE BY REF ID\n changes.set(changeTree.parentIndex, OPERATION.DELETE);\n\n } else {\n // delete all \"tagged\" properties.\n metadata[-2].forEach((index) =>\n changes.set(index, OPERATION.DELETE));\n }\n\n\n } else {\n // delete only tagged properties\n metadata[-3][tag].forEach((index) =>\n changes.set(index, OPERATION.DELETE));\n }\n\n // remove tag\n if (this.tags && this.tags.has(changeTree)) {\n const tags = this.tags.get(changeTree);\n if (tag === undefined) {\n // delete all tags\n this.tags.delete(changeTree);\n } else {\n // delete specific tag\n tags.delete(tag);\n\n // if tag set is empty, delete it entirely\n if (tags.size === 0) {\n this.tags.delete(changeTree);\n }\n }\n }\n\n return this;\n }\n}"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@colyseus/schema",
3
- "version": "3.0.0-alpha.16",
3
+ "version": "3.0.0-alpha.18",
4
4
  "description": "Binary state serializer with delta encoding for games",
5
5
  "bin": {
6
6
  "schema-codegen": "./bin/schema-codegen"
package/src/Metadata.ts CHANGED
@@ -117,6 +117,15 @@ export const Metadata = {
117
117
  return metadata[field].deprecated === true;
118
118
  },
119
119
 
120
+ init(klass: any) {
121
+ //
122
+ // Used only to initialize an empty Schema (Encoder#constructor)
123
+ //
124
+ const metadata = {};
125
+ klass.constructor[Symbol.metadata] = metadata;
126
+ Object.defineProperty(metadata, -1, { value: 0, enumerable: false, configurable: true });
127
+ },
128
+
120
129
  isValidInstance(klass: any) {
121
130
  return (
122
131
  klass.constructor[Symbol.metadata] &&
@@ -9,6 +9,7 @@ import { OPERATION, SWITCH_TO_STRUCTURE, TYPE_ID } from '../encoding/spec';
9
9
  import { Root } from "./ChangeTree";
10
10
  import { getNextPowerOf2 } from "../utils";
11
11
  import type { StateView } from "./StateView";
12
+ import { Metadata } from "../Metadata";
12
13
 
13
14
  export class Encoder<T extends Schema = any> {
14
15
  static BUFFER_SIZE = 8 * 1024;// 8KB
@@ -37,6 +38,12 @@ export class Encoder<T extends Schema = any> {
37
38
  protected setRoot(state: T) {
38
39
  this.root = new Root();
39
40
  this.state = state;
41
+
42
+ // Workaround to allow using an empty Schema.
43
+ if (state.constructor[Symbol.metadata] === undefined) {
44
+ Metadata.init(state);
45
+ }
46
+
40
47
  state[$changes].setRoot(this.root);
41
48
  }
42
49
 
@@ -34,15 +34,20 @@ export class StateView {
34
34
  return this;
35
35
  }
36
36
 
37
+ // FIXME: ArraySchema/MapSchema does not have metadata
38
+ const metadata: Metadata = obj.constructor[Symbol.metadata];
39
+
37
40
  let changeTree: ChangeTree = obj[$changes];
38
41
  this.items.add(changeTree);
39
42
 
40
43
  // Add children of this ChangeTree to this view
41
- changeTree.forEachChild((change, _) =>
42
- this.add(change.ref, tag));
43
-
44
- // FIXME: ArraySchema/MapSchema does not have metadata
45
- const metadata: Metadata = obj.constructor[Symbol.metadata];
44
+ changeTree.forEachChild((change, index) => {
45
+ // Do not ADD children that don't have the same tag
46
+ if (metadata && metadata[metadata[index]].tag !== tag) {
47
+ return;
48
+ }
49
+ this.add(change.ref, tag);
50
+ });
46
51
 
47
52
  // add parent ChangeTree's, if they are invisible to this view
48
53
  // TODO: REFACTOR addParent()
@@ -72,8 +77,6 @@ export class StateView {
72
77
  }
73
78
  tags.add(tag);
74
79
 
75
- // console.log("BY TAG:", tag);
76
-
77
80
  // Ref: add tagged properties
78
81
  metadata?.[-3]?.[tag]?.forEach((index) => {
79
82
  if (changeTree.getChange(index) !== OPERATION.DELETE) {