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