@colyseus/schema 3.0.20 → 3.0.22
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 +91 -56
- package/build/cjs/index.js.map +1 -1
- package/build/esm/index.mjs +91 -56
- package/build/esm/index.mjs.map +1 -1
- package/build/umd/index.js +91 -56
- package/lib/Reflection.js +69 -41
- package/lib/Reflection.js.map +1 -1
- package/lib/decoder/ReferenceTracker.js +2 -3
- package/lib/decoder/ReferenceTracker.js.map +1 -1
- package/lib/encoder/Encoder.js +7 -4
- package/lib/encoder/Encoder.js.map +1 -1
- package/lib/encoder/StateView.js +4 -4
- package/lib/encoder/StateView.js.map +1 -1
- package/lib/types/TypeContext.d.ts +2 -0
- package/lib/types/TypeContext.js +9 -5
- package/lib/types/TypeContext.js.map +1 -1
- package/package.json +1 -1
- package/src/Reflection.ts +79 -46
- package/src/decoder/ReferenceTracker.ts +2 -2
- package/src/encoder/Encoder.ts +7 -4
- package/src/encoder/StateView.ts +5 -5
- package/src/types/TypeContext.ts +10 -5
package/build/umd/index.js
CHANGED
|
@@ -604,6 +604,7 @@
|
|
|
604
604
|
* Keeps track of which classes extends which. (parent -> children)
|
|
605
605
|
*/
|
|
606
606
|
static { this.inheritedTypes = new Map(); }
|
|
607
|
+
static { this.cachedContexts = new Map(); }
|
|
607
608
|
static register(target) {
|
|
608
609
|
const parent = Object.getPrototypeOf(target);
|
|
609
610
|
if (parent !== Schema) {
|
|
@@ -615,17 +616,20 @@
|
|
|
615
616
|
inherits.add(target);
|
|
616
617
|
}
|
|
617
618
|
}
|
|
619
|
+
static cache(rootClass) {
|
|
620
|
+
let context = TypeContext.cachedContexts.get(rootClass);
|
|
621
|
+
if (!context) {
|
|
622
|
+
context = new TypeContext(rootClass);
|
|
623
|
+
TypeContext.cachedContexts.set(rootClass, context);
|
|
624
|
+
}
|
|
625
|
+
return context;
|
|
626
|
+
}
|
|
618
627
|
constructor(rootClass) {
|
|
619
628
|
this.types = {};
|
|
620
629
|
this.schemas = new Map();
|
|
621
630
|
this.hasFilters = false;
|
|
622
631
|
this.parentFiltered = {};
|
|
623
632
|
if (rootClass) {
|
|
624
|
-
//
|
|
625
|
-
// TODO:
|
|
626
|
-
// cache "discoverTypes" results for each rootClass
|
|
627
|
-
// to avoid re-discovering types for each new context/room
|
|
628
|
-
//
|
|
629
633
|
this.discoverTypes(rootClass);
|
|
630
634
|
}
|
|
631
635
|
}
|
|
@@ -3771,10 +3775,12 @@
|
|
|
3771
3775
|
constructor(state) {
|
|
3772
3776
|
this.sharedBuffer = Buffer.allocUnsafe(Encoder.BUFFER_SIZE);
|
|
3773
3777
|
//
|
|
3774
|
-
//
|
|
3775
|
-
//
|
|
3778
|
+
// Use .cache() here to avoid re-creating a new context for every new room instance.
|
|
3779
|
+
//
|
|
3780
|
+
// We may need to make this optional in case of dynamically created
|
|
3781
|
+
// schemas - which would lead to memory leaks
|
|
3776
3782
|
//
|
|
3777
|
-
this.context =
|
|
3783
|
+
this.context = TypeContext.cache(state.constructor);
|
|
3778
3784
|
this.root = new Root(this.context);
|
|
3779
3785
|
this.setState(state);
|
|
3780
3786
|
// console.log(">>>>>>>>>>>>>>>> Encoder types");
|
|
@@ -3921,13 +3927,14 @@
|
|
|
3921
3927
|
const changeTree = this.root.changeTrees[refId];
|
|
3922
3928
|
if (changeTree === undefined) {
|
|
3923
3929
|
// detached instance, remove from view and skip.
|
|
3930
|
+
// console.log("detached instance, remove from view and skip.", refId);
|
|
3924
3931
|
view.changes.delete(refId);
|
|
3925
3932
|
continue;
|
|
3926
3933
|
}
|
|
3927
3934
|
const keys = Object.keys(changes);
|
|
3928
3935
|
if (keys.length === 0) {
|
|
3929
3936
|
// FIXME: avoid having empty changes if no changes were made
|
|
3930
|
-
// console.log("changes.size === 0, skip", changeTree.ref.constructor.name);
|
|
3937
|
+
// console.log("changes.size === 0, skip", refId, changeTree.ref.constructor.name);
|
|
3931
3938
|
continue;
|
|
3932
3939
|
}
|
|
3933
3940
|
const ref = changeTree.ref;
|
|
@@ -4073,7 +4080,7 @@
|
|
|
4073
4080
|
//
|
|
4074
4081
|
// Ensure child schema instances have their references removed as well.
|
|
4075
4082
|
//
|
|
4076
|
-
if (
|
|
4083
|
+
if (ref.constructor[Symbol.metadata] !== undefined) {
|
|
4077
4084
|
const metadata = ref.constructor[Symbol.metadata];
|
|
4078
4085
|
for (const index in metadata) {
|
|
4079
4086
|
const field = metadata[index].name;
|
|
@@ -4084,7 +4091,7 @@
|
|
|
4084
4091
|
}
|
|
4085
4092
|
}
|
|
4086
4093
|
else {
|
|
4087
|
-
if (typeof (
|
|
4094
|
+
if (typeof (ref[$childType]) === "function") {
|
|
4088
4095
|
Array.from(ref.values())
|
|
4089
4096
|
.forEach((child) => {
|
|
4090
4097
|
const childRefId = this.refIds.get(child);
|
|
@@ -4279,50 +4286,28 @@
|
|
|
4279
4286
|
if (rootType > 0) {
|
|
4280
4287
|
reflection.rootType = rootType;
|
|
4281
4288
|
}
|
|
4282
|
-
const
|
|
4283
|
-
|
|
4284
|
-
|
|
4285
|
-
|
|
4286
|
-
|
|
4287
|
-
|
|
4288
|
-
|
|
4289
|
-
|
|
4290
|
-
const
|
|
4291
|
-
|
|
4292
|
-
|
|
4293
|
-
|
|
4294
|
-
if (typeof (type) === "string") {
|
|
4295
|
-
fieldType = type;
|
|
4289
|
+
const includedTypeIds = new Set();
|
|
4290
|
+
const pendingReflectionTypes = {};
|
|
4291
|
+
// add type to reflection in a way that respects inheritance
|
|
4292
|
+
// (parent types should be added before their children)
|
|
4293
|
+
const addType = (type) => {
|
|
4294
|
+
if (type.extendsId === undefined || includedTypeIds.has(type.extendsId)) {
|
|
4295
|
+
includedTypeIds.add(type.id);
|
|
4296
|
+
reflection.types.push(type);
|
|
4297
|
+
const deps = pendingReflectionTypes[type.id];
|
|
4298
|
+
if (deps !== undefined) {
|
|
4299
|
+
delete pendingReflectionTypes[type.id];
|
|
4300
|
+
deps.forEach((childType) => addType(childType));
|
|
4296
4301
|
}
|
|
4297
|
-
|
|
4298
|
-
|
|
4299
|
-
|
|
4300
|
-
|
|
4301
|
-
//
|
|
4302
|
-
if (Schema.is(type)) {
|
|
4303
|
-
fieldType = "ref";
|
|
4304
|
-
childTypeSchema = type;
|
|
4305
|
-
}
|
|
4306
|
-
else {
|
|
4307
|
-
fieldType = Object.keys(type)[0];
|
|
4308
|
-
if (typeof (type[fieldType]) === "string") {
|
|
4309
|
-
fieldType += ":" + type[fieldType]; // array:string
|
|
4310
|
-
}
|
|
4311
|
-
else {
|
|
4312
|
-
childTypeSchema = type[fieldType];
|
|
4313
|
-
}
|
|
4314
|
-
}
|
|
4315
|
-
field.referencedType = (childTypeSchema)
|
|
4316
|
-
? context.getTypeId(childTypeSchema)
|
|
4317
|
-
: -1;
|
|
4302
|
+
}
|
|
4303
|
+
else {
|
|
4304
|
+
if (pendingReflectionTypes[type.extendsId] === undefined) {
|
|
4305
|
+
pendingReflectionTypes[type.extendsId] = [];
|
|
4318
4306
|
}
|
|
4319
|
-
|
|
4320
|
-
currentType.fields.push(field);
|
|
4307
|
+
pendingReflectionTypes[type.extendsId].push(type);
|
|
4321
4308
|
}
|
|
4322
|
-
reflection.types.push(currentType);
|
|
4323
4309
|
};
|
|
4324
|
-
|
|
4325
|
-
const klass = context.types[typeid];
|
|
4310
|
+
context.schemas.forEach((typeid, klass) => {
|
|
4326
4311
|
const type = new ReflectionType();
|
|
4327
4312
|
type.id = Number(typeid);
|
|
4328
4313
|
// support inheritance
|
|
@@ -4330,7 +4315,57 @@
|
|
|
4330
4315
|
if (inheritFrom !== Schema) {
|
|
4331
4316
|
type.extendsId = context.schemas.get(inheritFrom);
|
|
4332
4317
|
}
|
|
4333
|
-
|
|
4318
|
+
const metadata = klass[Symbol.metadata];
|
|
4319
|
+
//
|
|
4320
|
+
// FIXME: this is a workaround for inherited types without additional fields
|
|
4321
|
+
// if metadata is the same reference as the parent class - it means the class has no own metadata
|
|
4322
|
+
//
|
|
4323
|
+
if (metadata !== inheritFrom[Symbol.metadata]) {
|
|
4324
|
+
for (const fieldIndex in metadata) {
|
|
4325
|
+
const index = Number(fieldIndex);
|
|
4326
|
+
const fieldName = metadata[index].name;
|
|
4327
|
+
// skip fields from parent classes
|
|
4328
|
+
if (!Object.prototype.hasOwnProperty.call(metadata, fieldName)) {
|
|
4329
|
+
continue;
|
|
4330
|
+
}
|
|
4331
|
+
const reflectionField = new ReflectionField();
|
|
4332
|
+
reflectionField.name = fieldName;
|
|
4333
|
+
let fieldType;
|
|
4334
|
+
const field = metadata[index];
|
|
4335
|
+
if (typeof (field.type) === "string") {
|
|
4336
|
+
fieldType = field.type;
|
|
4337
|
+
}
|
|
4338
|
+
else {
|
|
4339
|
+
let childTypeSchema;
|
|
4340
|
+
//
|
|
4341
|
+
// TODO: refactor below.
|
|
4342
|
+
//
|
|
4343
|
+
if (Schema.is(field.type)) {
|
|
4344
|
+
fieldType = "ref";
|
|
4345
|
+
childTypeSchema = field.type;
|
|
4346
|
+
}
|
|
4347
|
+
else {
|
|
4348
|
+
fieldType = Object.keys(field.type)[0];
|
|
4349
|
+
if (typeof (field.type[fieldType]) === "string") {
|
|
4350
|
+
fieldType += ":" + field.type[fieldType]; // array:string
|
|
4351
|
+
}
|
|
4352
|
+
else {
|
|
4353
|
+
childTypeSchema = field.type[fieldType];
|
|
4354
|
+
}
|
|
4355
|
+
}
|
|
4356
|
+
reflectionField.referencedType = (childTypeSchema)
|
|
4357
|
+
? context.getTypeId(childTypeSchema)
|
|
4358
|
+
: -1;
|
|
4359
|
+
}
|
|
4360
|
+
reflectionField.type = fieldType;
|
|
4361
|
+
type.fields.push(reflectionField);
|
|
4362
|
+
}
|
|
4363
|
+
}
|
|
4364
|
+
addType(type);
|
|
4365
|
+
});
|
|
4366
|
+
// in case there are types that were not added due to inheritance
|
|
4367
|
+
for (const typeid in pendingReflectionTypes) {
|
|
4368
|
+
pendingReflectionTypes[typeid].forEach((type) => reflection.types.push(type));
|
|
4334
4369
|
}
|
|
4335
4370
|
const buf = reflectionEncoder.encodeAll(it);
|
|
4336
4371
|
return Buffer.from(buf, 0, it.offset);
|
|
@@ -4699,7 +4734,7 @@
|
|
|
4699
4734
|
}
|
|
4700
4735
|
// TODO: allow to set multiple tags at once
|
|
4701
4736
|
add(obj, tag = DEFAULT_VIEW_TAG, checkIncludeParent = true) {
|
|
4702
|
-
if (!obj[$changes]) {
|
|
4737
|
+
if (!obj?.[$changes]) {
|
|
4703
4738
|
console.warn("StateView#add(), invalid object:", obj);
|
|
4704
4739
|
return this;
|
|
4705
4740
|
}
|
|
@@ -4821,7 +4856,7 @@
|
|
|
4821
4856
|
}
|
|
4822
4857
|
this.items.delete(changeTree);
|
|
4823
4858
|
const ref = changeTree.ref;
|
|
4824
|
-
const metadata = ref.constructor[Symbol.metadata];
|
|
4859
|
+
const metadata = ref.constructor[Symbol.metadata]; // ArraySchema/MapSchema do not have metadata
|
|
4825
4860
|
let changes = this.changes.get(changeTree.refId);
|
|
4826
4861
|
if (changes === undefined) {
|
|
4827
4862
|
changes = {};
|
|
@@ -4842,12 +4877,12 @@
|
|
|
4842
4877
|
}
|
|
4843
4878
|
else {
|
|
4844
4879
|
// delete all "tagged" properties.
|
|
4845
|
-
metadata[$viewFieldIndexes].forEach((index) => changes[index] = exports.OPERATION.DELETE);
|
|
4880
|
+
metadata?.[$viewFieldIndexes].forEach((index) => changes[index] = exports.OPERATION.DELETE);
|
|
4846
4881
|
}
|
|
4847
4882
|
}
|
|
4848
4883
|
else {
|
|
4849
4884
|
// delete only tagged properties
|
|
4850
|
-
metadata[$fieldIndexesByViewTag][tag].forEach((index) => changes[index] = exports.OPERATION.DELETE);
|
|
4885
|
+
metadata?.[$fieldIndexesByViewTag][tag].forEach((index) => changes[index] = exports.OPERATION.DELETE);
|
|
4851
4886
|
}
|
|
4852
4887
|
// remove tag
|
|
4853
4888
|
if (this.tags && this.tags.has(changeTree)) {
|
package/lib/Reflection.js
CHANGED
|
@@ -67,50 +67,28 @@ class Reflection extends Schema_1.Schema {
|
|
|
67
67
|
if (rootType > 0) {
|
|
68
68
|
reflection.rootType = rootType;
|
|
69
69
|
}
|
|
70
|
-
const
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
70
|
+
const includedTypeIds = new Set();
|
|
71
|
+
const pendingReflectionTypes = {};
|
|
72
|
+
// add type to reflection in a way that respects inheritance
|
|
73
|
+
// (parent types should be added before their children)
|
|
74
|
+
const addType = (type) => {
|
|
75
|
+
if (type.extendsId === undefined || includedTypeIds.has(type.extendsId)) {
|
|
76
|
+
includedTypeIds.add(type.id);
|
|
77
|
+
reflection.types.push(type);
|
|
78
|
+
const deps = pendingReflectionTypes[type.id];
|
|
79
|
+
if (deps !== undefined) {
|
|
80
|
+
delete pendingReflectionTypes[type.id];
|
|
81
|
+
deps.forEach((childType) => addType(childType));
|
|
77
82
|
}
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
if (typeof (type) === "string") {
|
|
83
|
-
fieldType = type;
|
|
84
|
-
}
|
|
85
|
-
else {
|
|
86
|
-
let childTypeSchema;
|
|
87
|
-
//
|
|
88
|
-
// TODO: refactor below.
|
|
89
|
-
//
|
|
90
|
-
if (Schema_1.Schema.is(type)) {
|
|
91
|
-
fieldType = "ref";
|
|
92
|
-
childTypeSchema = type;
|
|
93
|
-
}
|
|
94
|
-
else {
|
|
95
|
-
fieldType = Object.keys(type)[0];
|
|
96
|
-
if (typeof (type[fieldType]) === "string") {
|
|
97
|
-
fieldType += ":" + type[fieldType]; // array:string
|
|
98
|
-
}
|
|
99
|
-
else {
|
|
100
|
-
childTypeSchema = type[fieldType];
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
field.referencedType = (childTypeSchema)
|
|
104
|
-
? context.getTypeId(childTypeSchema)
|
|
105
|
-
: -1;
|
|
83
|
+
}
|
|
84
|
+
else {
|
|
85
|
+
if (pendingReflectionTypes[type.extendsId] === undefined) {
|
|
86
|
+
pendingReflectionTypes[type.extendsId] = [];
|
|
106
87
|
}
|
|
107
|
-
|
|
108
|
-
currentType.fields.push(field);
|
|
88
|
+
pendingReflectionTypes[type.extendsId].push(type);
|
|
109
89
|
}
|
|
110
|
-
reflection.types.push(currentType);
|
|
111
90
|
};
|
|
112
|
-
|
|
113
|
-
const klass = context.types[typeid];
|
|
91
|
+
context.schemas.forEach((typeid, klass) => {
|
|
114
92
|
const type = new ReflectionType();
|
|
115
93
|
type.id = Number(typeid);
|
|
116
94
|
// support inheritance
|
|
@@ -118,7 +96,57 @@ class Reflection extends Schema_1.Schema {
|
|
|
118
96
|
if (inheritFrom !== Schema_1.Schema) {
|
|
119
97
|
type.extendsId = context.schemas.get(inheritFrom);
|
|
120
98
|
}
|
|
121
|
-
|
|
99
|
+
const metadata = klass[Symbol.metadata];
|
|
100
|
+
//
|
|
101
|
+
// FIXME: this is a workaround for inherited types without additional fields
|
|
102
|
+
// if metadata is the same reference as the parent class - it means the class has no own metadata
|
|
103
|
+
//
|
|
104
|
+
if (metadata !== inheritFrom[Symbol.metadata]) {
|
|
105
|
+
for (const fieldIndex in metadata) {
|
|
106
|
+
const index = Number(fieldIndex);
|
|
107
|
+
const fieldName = metadata[index].name;
|
|
108
|
+
// skip fields from parent classes
|
|
109
|
+
if (!Object.prototype.hasOwnProperty.call(metadata, fieldName)) {
|
|
110
|
+
continue;
|
|
111
|
+
}
|
|
112
|
+
const reflectionField = new ReflectionField();
|
|
113
|
+
reflectionField.name = fieldName;
|
|
114
|
+
let fieldType;
|
|
115
|
+
const field = metadata[index];
|
|
116
|
+
if (typeof (field.type) === "string") {
|
|
117
|
+
fieldType = field.type;
|
|
118
|
+
}
|
|
119
|
+
else {
|
|
120
|
+
let childTypeSchema;
|
|
121
|
+
//
|
|
122
|
+
// TODO: refactor below.
|
|
123
|
+
//
|
|
124
|
+
if (Schema_1.Schema.is(field.type)) {
|
|
125
|
+
fieldType = "ref";
|
|
126
|
+
childTypeSchema = field.type;
|
|
127
|
+
}
|
|
128
|
+
else {
|
|
129
|
+
fieldType = Object.keys(field.type)[0];
|
|
130
|
+
if (typeof (field.type[fieldType]) === "string") {
|
|
131
|
+
fieldType += ":" + field.type[fieldType]; // array:string
|
|
132
|
+
}
|
|
133
|
+
else {
|
|
134
|
+
childTypeSchema = field.type[fieldType];
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
reflectionField.referencedType = (childTypeSchema)
|
|
138
|
+
? context.getTypeId(childTypeSchema)
|
|
139
|
+
: -1;
|
|
140
|
+
}
|
|
141
|
+
reflectionField.type = fieldType;
|
|
142
|
+
type.fields.push(reflectionField);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
addType(type);
|
|
146
|
+
});
|
|
147
|
+
// in case there are types that were not added due to inheritance
|
|
148
|
+
for (const typeid in pendingReflectionTypes) {
|
|
149
|
+
pendingReflectionTypes[typeid].forEach((type) => reflection.types.push(type));
|
|
122
150
|
}
|
|
123
151
|
const buf = reflectionEncoder.encodeAll(it);
|
|
124
152
|
return Buffer.from(buf, 0, it.offset);
|
package/lib/Reflection.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Reflection.js","sourceRoot":"","sources":["../src/Reflection.ts"],"names":[],"mappings":"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","sourcesContent":["import { type, PrimitiveType } from \"./annotations\";\nimport { TypeContext } from \"./types/TypeContext\";\nimport { Metadata } from \"./Metadata\";\nimport { ArraySchema } from \"./types/custom/ArraySchema\";\nimport { Iterator } from \"./encoding/decode\";\nimport { Encoder } from \"./encoder/Encoder\";\nimport { Decoder } from \"./decoder/Decoder\";\nimport { Schema } from \"./Schema\";\n\n/**\n * Reflection\n */\nexport class ReflectionField extends Schema {\n @type(\"string\") name: string;\n @type(\"string\") type: string;\n @type(\"number\") referencedType: number;\n}\n\nexport class ReflectionType extends Schema {\n @type(\"number\") id: number;\n @type(\"number\") extendsId: number;\n @type([ ReflectionField ]) fields = new ArraySchema<ReflectionField>();\n}\n\nexport class Reflection extends Schema {\n @type([ReflectionType]) types: ArraySchema<ReflectionType> = new ArraySchema<ReflectionType>();\n @type(\"number\") rootType: number;\n\n /**\n * Encodes the TypeContext of an Encoder into a buffer.\n *\n * @param encoder Encoder instance\n * @param it\n * @returns\n */\n static encode(encoder: Encoder, it: Iterator = { offset: 0 }) {\n const context = encoder.context;\n\n const reflection = new Reflection();\n const reflectionEncoder = new Encoder(reflection);\n\n // rootType is usually the first schema passed to the Encoder\n // (unless it inherits from another schema)\n const rootType = context.schemas.get(encoder.state.constructor);\n if (rootType > 0) { reflection.rootType = rootType; }\n\n const buildType = (currentType: ReflectionType, metadata: Metadata) => {\n for (const fieldIndex in metadata) {\n const index = Number(fieldIndex);\n const fieldName = metadata[index].name;\n\n // skip fields from parent classes\n if (!Object.prototype.hasOwnProperty.call(metadata, fieldName)) {\n continue;\n }\n\n const field = new ReflectionField();\n field.name = fieldName;\n\n let fieldType: string;\n\n const type = metadata[index].type;\n\n if (typeof (type) === \"string\") {\n fieldType = type;\n\n } else {\n let childTypeSchema: typeof Schema;\n\n //\n // TODO: refactor below.\n //\n if (Schema.is(type)) {\n fieldType = \"ref\";\n childTypeSchema = type as typeof Schema;\n\n } else {\n fieldType = Object.keys(type)[0];\n\n if (typeof(type[fieldType]) === \"string\") {\n fieldType += \":\" + type[fieldType]; // array:string\n\n } else {\n childTypeSchema = type[fieldType];\n }\n }\n\n field.referencedType = (childTypeSchema)\n ? context.getTypeId(childTypeSchema)\n : -1;\n }\n\n field.type = fieldType;\n currentType.fields.push(field);\n }\n\n reflection.types.push(currentType);\n }\n\n for (let typeid in context.types) {\n const klass = context.types[typeid];\n const type = new ReflectionType();\n type.id = Number(typeid);\n\n // support inheritance\n const inheritFrom = Object.getPrototypeOf(klass);\n if (inheritFrom !== Schema) {\n type.extendsId = context.schemas.get(inheritFrom);\n }\n\n buildType(type, klass[Symbol.metadata]);\n }\n\n const buf = reflectionEncoder.encodeAll(it);\n return Buffer.from(buf, 0, it.offset);\n }\n\n /**\n * Decodes the TypeContext from a buffer into a Decoder instance.\n *\n * @param bytes Reflection.encode() output\n * @param it\n * @returns Decoder instance\n */\n static decode<T extends Schema = Schema>(bytes: Buffer, it?: Iterator): Decoder<T> {\n const reflection = new Reflection();\n\n const reflectionDecoder = new Decoder(reflection);\n reflectionDecoder.decode(bytes, it);\n\n const typeContext = new TypeContext();\n\n // 1st pass, initialize metadata + inheritance\n reflection.types.forEach((reflectionType) => {\n const parentClass: typeof Schema = typeContext.get(reflectionType.extendsId) ?? Schema;\n const schema: typeof Schema = class _ extends parentClass {};\n\n // register for inheritance support\n TypeContext.register(schema);\n\n // // for inheritance support\n // Metadata.initialize(schema);\n\n typeContext.add(schema, reflectionType.id);\n }, {});\n\n // define fields\n const addFields = (metadata: Metadata, reflectionType: ReflectionType, parentFieldIndex: number) => {\n reflectionType.fields.forEach((field, i) => {\n const fieldIndex = parentFieldIndex + i;\n\n if (field.referencedType !== undefined) {\n let fieldType = field.type;\n let refType: PrimitiveType = typeContext.get(field.referencedType);\n\n // map or array of primitive type (-1)\n if (!refType) {\n const typeInfo = field.type.split(\":\");\n fieldType = typeInfo[0];\n refType = typeInfo[1] as PrimitiveType; // string\n }\n\n if (fieldType === \"ref\") {\n Metadata.addField(metadata, fieldIndex, field.name, refType);\n\n } else {\n Metadata.addField(metadata, fieldIndex, field.name, { [fieldType]: refType });\n }\n\n } else {\n Metadata.addField(metadata, fieldIndex, field.name, field.type as PrimitiveType);\n }\n });\n };\n\n // 2nd pass, set fields\n reflection.types.forEach((reflectionType) => {\n const schema = typeContext.get(reflectionType.id);\n\n // for inheritance support\n const metadata = Metadata.initialize(schema);\n\n const inheritedTypes: ReflectionType[] = [];\n\n let parentType: ReflectionType = reflectionType;\n do {\n inheritedTypes.push(parentType);\n parentType = reflection.types.find((t) => t.id === parentType.extendsId);\n } while (parentType);\n\n let parentFieldIndex = 0;\n\n inheritedTypes.reverse().forEach((reflectionType) => {\n // add fields from all inherited classes\n // TODO: refactor this to avoid adding fields from parent classes\n addFields(metadata, reflectionType, parentFieldIndex);\n parentFieldIndex += reflectionType.fields.length;\n });\n });\n\n const state: T = new (typeContext.get(reflection.rootType || 0) as unknown as any)();\n\n return new Decoder<T>(state, typeContext);\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"Reflection.js","sourceRoot":"","sources":["../src/Reflection.ts"],"names":[],"mappings":"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","sourcesContent":["import { type, PrimitiveType } from \"./annotations\";\nimport { TypeContext } from \"./types/TypeContext\";\nimport { Metadata } from \"./Metadata\";\nimport { ArraySchema } from \"./types/custom/ArraySchema\";\nimport { Iterator } from \"./encoding/decode\";\nimport { Encoder } from \"./encoder/Encoder\";\nimport { Decoder } from \"./decoder/Decoder\";\nimport { Schema } from \"./Schema\";\n\n/**\n * Reflection\n */\nexport class ReflectionField extends Schema {\n @type(\"string\") name: string;\n @type(\"string\") type: string;\n @type(\"number\") referencedType: number;\n}\n\nexport class ReflectionType extends Schema {\n @type(\"number\") id: number;\n @type(\"number\") extendsId: number;\n @type([ ReflectionField ]) fields = new ArraySchema<ReflectionField>();\n}\n\nexport class Reflection extends Schema {\n @type([ReflectionType]) types: ArraySchema<ReflectionType> = new ArraySchema<ReflectionType>();\n @type(\"number\") rootType: number;\n\n /**\n * Encodes the TypeContext of an Encoder into a buffer.\n *\n * @param encoder Encoder instance\n * @param it\n * @returns\n */\n static encode(encoder: Encoder, it: Iterator = { offset: 0 }) {\n const context = encoder.context;\n\n const reflection = new Reflection();\n const reflectionEncoder = new Encoder(reflection);\n\n // rootType is usually the first schema passed to the Encoder\n // (unless it inherits from another schema)\n const rootType = context.schemas.get(encoder.state.constructor);\n if (rootType > 0) { reflection.rootType = rootType; }\n\n const includedTypeIds = new Set<number>();\n const pendingReflectionTypes: { [typeid: number]: ReflectionType[] } = {};\n\n // add type to reflection in a way that respects inheritance\n // (parent types should be added before their children)\n const addType = (type: ReflectionType) => {\n if (type.extendsId === undefined || includedTypeIds.has(type.extendsId)) {\n includedTypeIds.add(type.id);\n\n reflection.types.push(type);\n\n const deps = pendingReflectionTypes[type.id];\n if (deps !== undefined) {\n delete pendingReflectionTypes[type.id];\n deps.forEach((childType) => addType(childType));\n }\n } else {\n if (pendingReflectionTypes[type.extendsId] === undefined) {\n pendingReflectionTypes[type.extendsId] = [];\n }\n pendingReflectionTypes[type.extendsId].push(type);\n }\n };\n\n context.schemas.forEach((typeid, klass) => {\n const type = new ReflectionType();\n type.id = Number(typeid);\n\n // support inheritance\n const inheritFrom = Object.getPrototypeOf(klass);\n if (inheritFrom !== Schema) {\n type.extendsId = context.schemas.get(inheritFrom);\n }\n\n const metadata = klass[Symbol.metadata];\n\n //\n // FIXME: this is a workaround for inherited types without additional fields\n // if metadata is the same reference as the parent class - it means the class has no own metadata\n //\n if (metadata !== inheritFrom[Symbol.metadata]) {\n for (const fieldIndex in metadata) {\n const index = Number(fieldIndex);\n const fieldName = metadata[index].name;\n\n // skip fields from parent classes\n if (!Object.prototype.hasOwnProperty.call(metadata, fieldName)) {\n continue;\n }\n\n const reflectionField = new ReflectionField();\n reflectionField.name = fieldName;\n\n let fieldType: string;\n\n const field = metadata[index];\n\n if (typeof (field.type) === \"string\") {\n fieldType = field.type;\n\n } else {\n let childTypeSchema: typeof Schema;\n\n //\n // TODO: refactor below.\n //\n if (Schema.is(field.type)) {\n fieldType = \"ref\";\n childTypeSchema = field.type as typeof Schema;\n\n } else {\n fieldType = Object.keys(field.type)[0];\n\n if (typeof (field.type[fieldType]) === \"string\") {\n fieldType += \":\" + field.type[fieldType]; // array:string\n\n } else {\n childTypeSchema = field.type[fieldType];\n }\n }\n\n reflectionField.referencedType = (childTypeSchema)\n ? context.getTypeId(childTypeSchema)\n : -1;\n }\n\n reflectionField.type = fieldType;\n type.fields.push(reflectionField);\n }\n }\n\n addType(type);\n });\n\n // in case there are types that were not added due to inheritance\n for (const typeid in pendingReflectionTypes) {\n pendingReflectionTypes[typeid].forEach((type) =>\n reflection.types.push(type))\n }\n\n const buf = reflectionEncoder.encodeAll(it);\n return Buffer.from(buf, 0, it.offset);\n }\n\n /**\n * Decodes the TypeContext from a buffer into a Decoder instance.\n *\n * @param bytes Reflection.encode() output\n * @param it\n * @returns Decoder instance\n */\n static decode<T extends Schema = Schema>(bytes: Buffer, it?: Iterator): Decoder<T> {\n const reflection = new Reflection();\n\n const reflectionDecoder = new Decoder(reflection);\n reflectionDecoder.decode(bytes, it);\n\n const typeContext = new TypeContext();\n\n // 1st pass, initialize metadata + inheritance\n reflection.types.forEach((reflectionType) => {\n const parentClass: typeof Schema = typeContext.get(reflectionType.extendsId) ?? Schema;\n const schema: typeof Schema = class _ extends parentClass {};\n\n // register for inheritance support\n TypeContext.register(schema);\n\n // // for inheritance support\n // Metadata.initialize(schema);\n\n typeContext.add(schema, reflectionType.id);\n }, {});\n\n // define fields\n const addFields = (metadata: Metadata, reflectionType: ReflectionType, parentFieldIndex: number) => {\n reflectionType.fields.forEach((field, i) => {\n const fieldIndex = parentFieldIndex + i;\n\n if (field.referencedType !== undefined) {\n let fieldType = field.type;\n let refType: PrimitiveType = typeContext.get(field.referencedType);\n\n // map or array of primitive type (-1)\n if (!refType) {\n const typeInfo = field.type.split(\":\");\n fieldType = typeInfo[0];\n refType = typeInfo[1] as PrimitiveType; // string\n }\n\n if (fieldType === \"ref\") {\n Metadata.addField(metadata, fieldIndex, field.name, refType);\n\n } else {\n Metadata.addField(metadata, fieldIndex, field.name, { [fieldType]: refType });\n }\n\n } else {\n Metadata.addField(metadata, fieldIndex, field.name, field.type as PrimitiveType);\n }\n });\n };\n\n // 2nd pass, set fields\n reflection.types.forEach((reflectionType) => {\n const schema = typeContext.get(reflectionType.id);\n\n // for inheritance support\n const metadata = Metadata.initialize(schema);\n\n const inheritedTypes: ReflectionType[] = [];\n\n let parentType: ReflectionType = reflectionType;\n do {\n inheritedTypes.push(parentType);\n parentType = reflection.types.find((t) => t.id === parentType.extendsId);\n } while (parentType);\n\n let parentFieldIndex = 0;\n\n inheritedTypes.reverse().forEach((reflectionType) => {\n // add fields from all inherited classes\n // TODO: refactor this to avoid adding fields from parent classes\n addFields(metadata, reflectionType, parentFieldIndex);\n parentFieldIndex += reflectionType.fields.length;\n });\n });\n\n const state: T = new (typeContext.get(reflection.rootType || 0) as unknown as any)();\n\n return new Decoder<T>(state, typeContext);\n }\n}\n"]}
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.ReferenceTracker = void 0;
|
|
4
|
-
const Metadata_1 = require("../Metadata");
|
|
5
4
|
const symbols_1 = require("../types/symbols");
|
|
6
5
|
const utils_1 = require("../types/utils");
|
|
7
6
|
const spec_1 = require("../encoding/spec");
|
|
@@ -83,7 +82,7 @@ class ReferenceTracker {
|
|
|
83
82
|
//
|
|
84
83
|
// Ensure child schema instances have their references removed as well.
|
|
85
84
|
//
|
|
86
|
-
if (
|
|
85
|
+
if (ref.constructor[Symbol.metadata] !== undefined) {
|
|
87
86
|
const metadata = ref.constructor[Symbol.metadata];
|
|
88
87
|
for (const index in metadata) {
|
|
89
88
|
const field = metadata[index].name;
|
|
@@ -94,7 +93,7 @@ class ReferenceTracker {
|
|
|
94
93
|
}
|
|
95
94
|
}
|
|
96
95
|
else {
|
|
97
|
-
if (typeof (
|
|
96
|
+
if (typeof (ref[symbols_1.$childType]) === "function") {
|
|
98
97
|
Array.from(ref.values())
|
|
99
98
|
.forEach((child) => {
|
|
100
99
|
const childRefId = this.refIds.get(child);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ReferenceTracker.js","sourceRoot":"","sources":["../../src/decoder/ReferenceTracker.ts"],"names":[],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"ReferenceTracker.js","sourceRoot":"","sources":["../../src/decoder/ReferenceTracker.ts"],"names":[],"mappings":"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","sourcesContent":["import { Metadata } from \"../Metadata\";\nimport { $childType } from \"../types/symbols\";\nimport { Ref } from \"../encoder/ChangeTree\";\nimport { spliceOne } from \"../types/utils\";\nimport type { MapSchema } from \"../types/custom/MapSchema\";\nimport { OPERATION } from \"../encoding/spec\";\n\nclass DecodingWarning extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"DecodingWarning\";\n }\n}\n\n/**\n * Used for decoding only.\n */\n\nexport type SchemaCallbacks = { [field: string | number]: Function[] };\n\nexport class ReferenceTracker {\n //\n // Relation of refId => Schema structure\n // For direct access of structures during decoding time.\n //\n public refs = new Map<number, Ref>();\n public refIds = new WeakMap<Ref, number>();\n\n public refCounts: { [refId: number]: number; } = {};\n public deletedRefs = new Set<number>();\n\n public callbacks: { [refId: number]: SchemaCallbacks } = {};\n protected nextUniqueId: number = 0;\n\n getNextUniqueId() {\n return this.nextUniqueId++;\n }\n\n // for decoding\n addRef(refId: number, ref: Ref, incrementCount: boolean = true) {\n this.refs.set(refId, ref);\n this.refIds.set(ref, refId);\n\n if (incrementCount) {\n this.refCounts[refId] = (this.refCounts[refId] || 0) + 1;\n }\n\n if (this.deletedRefs.has(refId)) {\n this.deletedRefs.delete(refId);\n }\n }\n\n // for decoding\n removeRef(refId: number) {\n const refCount = this.refCounts[refId];\n\n if (refCount === undefined) {\n try {\n throw new DecodingWarning(\"trying to remove refId that doesn't exist: \" + refId);\n } catch (e) {\n console.warn(e);\n }\n return;\n }\n\n if (refCount === 0) {\n try {\n const ref = this.refs.get(refId);\n throw new DecodingWarning(`trying to remove refId '${refId}' with 0 refCount (${ref.constructor.name}: ${JSON.stringify(ref)})`);\n } catch (e) {\n console.warn(e);\n }\n return;\n }\n\n if ((this.refCounts[refId] = refCount - 1) <= 0) {\n this.deletedRefs.add(refId);\n }\n }\n\n clearRefs() {\n this.refs.clear();\n this.deletedRefs.clear();\n this.callbacks = {};\n this.refCounts = {};\n }\n\n // for decoding\n garbageCollectDeletedRefs() {\n this.deletedRefs.forEach((refId) => {\n //\n // Skip active references.\n //\n if (this.refCounts[refId] > 0) { return; }\n\n const ref = this.refs.get(refId);\n\n //\n // Ensure child schema instances have their references removed as well.\n //\n if (ref.constructor[Symbol.metadata] !== undefined) {\n const metadata: Metadata = ref.constructor[Symbol.metadata];\n for (const index in metadata) {\n const field = metadata[index as any as number].name;\n const childRefId = typeof(ref[field]) === \"object\" && this.refIds.get(ref[field]);\n if (childRefId && !this.deletedRefs.has(childRefId)) {\n this.removeRef(childRefId);\n }\n }\n\n } else {\n if (typeof (ref[$childType]) === \"function\") {\n Array.from((ref as MapSchema).values())\n .forEach((child) => {\n const childRefId = this.refIds.get(child);\n if (!this.deletedRefs.has(childRefId)) {\n this.removeRef(childRefId);\n }\n });\n }\n }\n\n this.refs.delete(refId); // remove ref\n delete this.refCounts[refId]; // remove ref count\n delete this.callbacks[refId]; // remove callbacks\n });\n\n // clear deleted refs.\n this.deletedRefs.clear();\n }\n\n addCallback(refId: number, fieldOrOperation: string | number, callback: Function) {\n if (refId === undefined) {\n const name = (typeof(fieldOrOperation) === \"number\")\n ? OPERATION[fieldOrOperation]\n : fieldOrOperation\n throw new Error(\n `Can't addCallback on '${name}' (refId is undefined)`\n );\n }\n if (!this.callbacks[refId]) {\n this.callbacks[refId] = {};\n }\n if (!this.callbacks[refId][fieldOrOperation]) {\n this.callbacks[refId][fieldOrOperation] = [];\n }\n this.callbacks[refId][fieldOrOperation].push(callback);\n return () => this.removeCallback(refId, fieldOrOperation, callback);\n }\n\n removeCallback(refId: number, field: string | number, callback: Function) {\n const index = this.callbacks?.[refId]?.[field]?.indexOf(callback);\n if (index !== -1) {\n spliceOne(this.callbacks[refId][field], index);\n }\n }\n\n}\n"]}
|
package/lib/encoder/Encoder.js
CHANGED
|
@@ -11,10 +11,12 @@ class Encoder {
|
|
|
11
11
|
constructor(state) {
|
|
12
12
|
this.sharedBuffer = Buffer.allocUnsafe(Encoder.BUFFER_SIZE);
|
|
13
13
|
//
|
|
14
|
-
//
|
|
15
|
-
// (to avoid creating a new context for every new room)
|
|
14
|
+
// Use .cache() here to avoid re-creating a new context for every new room instance.
|
|
16
15
|
//
|
|
17
|
-
this
|
|
16
|
+
// We may need to make this optional in case of dynamically created
|
|
17
|
+
// schemas - which would lead to memory leaks
|
|
18
|
+
//
|
|
19
|
+
this.context = TypeContext_1.TypeContext.cache(state.constructor);
|
|
18
20
|
this.root = new Root_1.Root(this.context);
|
|
19
21
|
this.setState(state);
|
|
20
22
|
// console.log(">>>>>>>>>>>>>>>> Encoder types");
|
|
@@ -161,13 +163,14 @@ class Encoder {
|
|
|
161
163
|
const changeTree = this.root.changeTrees[refId];
|
|
162
164
|
if (changeTree === undefined) {
|
|
163
165
|
// detached instance, remove from view and skip.
|
|
166
|
+
// console.log("detached instance, remove from view and skip.", refId);
|
|
164
167
|
view.changes.delete(refId);
|
|
165
168
|
continue;
|
|
166
169
|
}
|
|
167
170
|
const keys = Object.keys(changes);
|
|
168
171
|
if (keys.length === 0) {
|
|
169
172
|
// FIXME: avoid having empty changes if no changes were made
|
|
170
|
-
// console.log("changes.size === 0, skip", changeTree.ref.constructor.name);
|
|
173
|
+
// console.log("changes.size === 0, skip", refId, changeTree.ref.constructor.name);
|
|
171
174
|
continue;
|
|
172
175
|
}
|
|
173
176
|
const ref = changeTree.ref;
|