@colyseus/schema 3.0.20 → 3.0.21
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 +83 -49
- package/build/cjs/index.js.map +1 -1
- package/build/esm/index.mjs +83 -49
- package/build/esm/index.mjs.map +1 -1
- package/build/umd/index.js +83 -49
- package/lib/Reflection.js +69 -41
- package/lib/Reflection.js.map +1 -1
- package/lib/encoder/Encoder.js +5 -3
- package/lib/encoder/Encoder.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/encoder/Encoder.ts +5 -3
- package/src/types/TypeContext.ts +10 -5
package/build/cjs/index.js
CHANGED
|
@@ -600,6 +600,7 @@ class TypeContext {
|
|
|
600
600
|
* Keeps track of which classes extends which. (parent -> children)
|
|
601
601
|
*/
|
|
602
602
|
static { this.inheritedTypes = new Map(); }
|
|
603
|
+
static { this.cachedContexts = new Map(); }
|
|
603
604
|
static register(target) {
|
|
604
605
|
const parent = Object.getPrototypeOf(target);
|
|
605
606
|
if (parent !== Schema) {
|
|
@@ -611,17 +612,20 @@ class TypeContext {
|
|
|
611
612
|
inherits.add(target);
|
|
612
613
|
}
|
|
613
614
|
}
|
|
615
|
+
static cache(rootClass) {
|
|
616
|
+
let context = TypeContext.cachedContexts.get(rootClass);
|
|
617
|
+
if (!context) {
|
|
618
|
+
context = new TypeContext(rootClass);
|
|
619
|
+
TypeContext.cachedContexts.set(rootClass, context);
|
|
620
|
+
}
|
|
621
|
+
return context;
|
|
622
|
+
}
|
|
614
623
|
constructor(rootClass) {
|
|
615
624
|
this.types = {};
|
|
616
625
|
this.schemas = new Map();
|
|
617
626
|
this.hasFilters = false;
|
|
618
627
|
this.parentFiltered = {};
|
|
619
628
|
if (rootClass) {
|
|
620
|
-
//
|
|
621
|
-
// TODO:
|
|
622
|
-
// cache "discoverTypes" results for each rootClass
|
|
623
|
-
// to avoid re-discovering types for each new context/room
|
|
624
|
-
//
|
|
625
629
|
this.discoverTypes(rootClass);
|
|
626
630
|
}
|
|
627
631
|
}
|
|
@@ -3767,10 +3771,12 @@ class Encoder {
|
|
|
3767
3771
|
constructor(state) {
|
|
3768
3772
|
this.sharedBuffer = Buffer.allocUnsafe(Encoder.BUFFER_SIZE);
|
|
3769
3773
|
//
|
|
3770
|
-
//
|
|
3771
|
-
//
|
|
3774
|
+
// Use .cache() here to avoid re-creating a new context for every new room instance.
|
|
3775
|
+
//
|
|
3776
|
+
// We may need to make this optional in case of dynamically created
|
|
3777
|
+
// schemas - which would lead to memory leaks
|
|
3772
3778
|
//
|
|
3773
|
-
this.context =
|
|
3779
|
+
this.context = TypeContext.cache(state.constructor);
|
|
3774
3780
|
this.root = new Root(this.context);
|
|
3775
3781
|
this.setState(state);
|
|
3776
3782
|
// console.log(">>>>>>>>>>>>>>>> Encoder types");
|
|
@@ -4275,50 +4281,28 @@ class Reflection extends Schema {
|
|
|
4275
4281
|
if (rootType > 0) {
|
|
4276
4282
|
reflection.rootType = rootType;
|
|
4277
4283
|
}
|
|
4278
|
-
const
|
|
4279
|
-
|
|
4280
|
-
|
|
4281
|
-
|
|
4282
|
-
|
|
4283
|
-
|
|
4284
|
-
|
|
4285
|
-
|
|
4286
|
-
const
|
|
4287
|
-
|
|
4288
|
-
|
|
4289
|
-
|
|
4290
|
-
if (typeof (type) === "string") {
|
|
4291
|
-
fieldType = type;
|
|
4284
|
+
const includedTypeIds = new Set();
|
|
4285
|
+
const pendingReflectionTypes = {};
|
|
4286
|
+
// add type to reflection in a way that respects inheritance
|
|
4287
|
+
// (parent types should be added before their children)
|
|
4288
|
+
const addType = (type) => {
|
|
4289
|
+
if (type.extendsId === undefined || includedTypeIds.has(type.extendsId)) {
|
|
4290
|
+
includedTypeIds.add(type.id);
|
|
4291
|
+
reflection.types.push(type);
|
|
4292
|
+
const deps = pendingReflectionTypes[type.id];
|
|
4293
|
+
if (deps !== undefined) {
|
|
4294
|
+
delete pendingReflectionTypes[type.id];
|
|
4295
|
+
deps.forEach((childType) => addType(childType));
|
|
4292
4296
|
}
|
|
4293
|
-
|
|
4294
|
-
|
|
4295
|
-
|
|
4296
|
-
|
|
4297
|
-
//
|
|
4298
|
-
if (Schema.is(type)) {
|
|
4299
|
-
fieldType = "ref";
|
|
4300
|
-
childTypeSchema = type;
|
|
4301
|
-
}
|
|
4302
|
-
else {
|
|
4303
|
-
fieldType = Object.keys(type)[0];
|
|
4304
|
-
if (typeof (type[fieldType]) === "string") {
|
|
4305
|
-
fieldType += ":" + type[fieldType]; // array:string
|
|
4306
|
-
}
|
|
4307
|
-
else {
|
|
4308
|
-
childTypeSchema = type[fieldType];
|
|
4309
|
-
}
|
|
4310
|
-
}
|
|
4311
|
-
field.referencedType = (childTypeSchema)
|
|
4312
|
-
? context.getTypeId(childTypeSchema)
|
|
4313
|
-
: -1;
|
|
4297
|
+
}
|
|
4298
|
+
else {
|
|
4299
|
+
if (pendingReflectionTypes[type.extendsId] === undefined) {
|
|
4300
|
+
pendingReflectionTypes[type.extendsId] = [];
|
|
4314
4301
|
}
|
|
4315
|
-
|
|
4316
|
-
currentType.fields.push(field);
|
|
4302
|
+
pendingReflectionTypes[type.extendsId].push(type);
|
|
4317
4303
|
}
|
|
4318
|
-
reflection.types.push(currentType);
|
|
4319
4304
|
};
|
|
4320
|
-
|
|
4321
|
-
const klass = context.types[typeid];
|
|
4305
|
+
context.schemas.forEach((typeid, klass) => {
|
|
4322
4306
|
const type = new ReflectionType();
|
|
4323
4307
|
type.id = Number(typeid);
|
|
4324
4308
|
// support inheritance
|
|
@@ -4326,7 +4310,57 @@ class Reflection extends Schema {
|
|
|
4326
4310
|
if (inheritFrom !== Schema) {
|
|
4327
4311
|
type.extendsId = context.schemas.get(inheritFrom);
|
|
4328
4312
|
}
|
|
4329
|
-
|
|
4313
|
+
const metadata = klass[Symbol.metadata];
|
|
4314
|
+
//
|
|
4315
|
+
// FIXME: this is a workaround for inherited types without additional fields
|
|
4316
|
+
// if metadata is the same reference as the parent class - it means the class has no own metadata
|
|
4317
|
+
//
|
|
4318
|
+
if (metadata !== inheritFrom[Symbol.metadata]) {
|
|
4319
|
+
for (const fieldIndex in metadata) {
|
|
4320
|
+
const index = Number(fieldIndex);
|
|
4321
|
+
const fieldName = metadata[index].name;
|
|
4322
|
+
// skip fields from parent classes
|
|
4323
|
+
if (!Object.prototype.hasOwnProperty.call(metadata, fieldName)) {
|
|
4324
|
+
continue;
|
|
4325
|
+
}
|
|
4326
|
+
const reflectionField = new ReflectionField();
|
|
4327
|
+
reflectionField.name = fieldName;
|
|
4328
|
+
let fieldType;
|
|
4329
|
+
const field = metadata[index];
|
|
4330
|
+
if (typeof (field.type) === "string") {
|
|
4331
|
+
fieldType = field.type;
|
|
4332
|
+
}
|
|
4333
|
+
else {
|
|
4334
|
+
let childTypeSchema;
|
|
4335
|
+
//
|
|
4336
|
+
// TODO: refactor below.
|
|
4337
|
+
//
|
|
4338
|
+
if (Schema.is(field.type)) {
|
|
4339
|
+
fieldType = "ref";
|
|
4340
|
+
childTypeSchema = field.type;
|
|
4341
|
+
}
|
|
4342
|
+
else {
|
|
4343
|
+
fieldType = Object.keys(field.type)[0];
|
|
4344
|
+
if (typeof (field.type[fieldType]) === "string") {
|
|
4345
|
+
fieldType += ":" + field.type[fieldType]; // array:string
|
|
4346
|
+
}
|
|
4347
|
+
else {
|
|
4348
|
+
childTypeSchema = field.type[fieldType];
|
|
4349
|
+
}
|
|
4350
|
+
}
|
|
4351
|
+
reflectionField.referencedType = (childTypeSchema)
|
|
4352
|
+
? context.getTypeId(childTypeSchema)
|
|
4353
|
+
: -1;
|
|
4354
|
+
}
|
|
4355
|
+
reflectionField.type = fieldType;
|
|
4356
|
+
type.fields.push(reflectionField);
|
|
4357
|
+
}
|
|
4358
|
+
}
|
|
4359
|
+
addType(type);
|
|
4360
|
+
});
|
|
4361
|
+
// in case there are types that were not added due to inheritance
|
|
4362
|
+
for (const typeid in pendingReflectionTypes) {
|
|
4363
|
+
pendingReflectionTypes[typeid].forEach((type) => reflection.types.push(type));
|
|
4330
4364
|
}
|
|
4331
4365
|
const buf = reflectionEncoder.encodeAll(it);
|
|
4332
4366
|
return Buffer.from(buf, 0, it.offset);
|