@colyseus/schema 3.0.38 → 3.0.40

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.
@@ -3308,18 +3308,22 @@ class Schema {
3308
3308
  * @param showContents display JSON contents of the instance
3309
3309
  * @returns
3310
3310
  */
3311
- static debugRefIds(ref, showContents = false, level = 0) {
3311
+ static debugRefIds(ref, showContents = false, level = 0, decoder) {
3312
3312
  const contents = (showContents) ? ` - ${JSON.stringify(ref.toJSON())}` : "";
3313
3313
  const changeTree = ref[$changes];
3314
- const refId = changeTree.refId;
3314
+ const refId = (decoder) ? decoder.root.refIds.get(ref) : changeTree.refId;
3315
+ const root = (decoder) ? decoder.root : changeTree.root;
3315
3316
  // log reference count if > 1
3316
- const refCount = (changeTree.root?.refCount?.[refId] > 1)
3317
- ? ` [×${changeTree.root.refCount[refId]}]`
3317
+ const refCount = (root?.refCount?.[refId] > 1)
3318
+ ? ` [×${root.refCount[refId]}]`
3318
3319
  : '';
3319
3320
  let output = `${getIndent(level)}${ref.constructor.name} (refId: ${refId})${refCount}${contents}\n`;
3320
- changeTree.forEachChild((childChangeTree) => output += this.debugRefIds(childChangeTree.ref, showContents, level + 1));
3321
+ changeTree.forEachChild((childChangeTree) => output += this.debugRefIds(childChangeTree.ref, showContents, level + 1, decoder));
3321
3322
  return output;
3322
3323
  }
3324
+ static debugRefIdsDecoder(decoder) {
3325
+ return this.debugRefIds(decoder.state, false, 0, decoder);
3326
+ }
3323
3327
  /**
3324
3328
  * Return a string representation of the changes on a Schema instance.
3325
3329
  * The list of changes is cleared after each encode.
@@ -4122,7 +4126,7 @@ class ReferenceTracker {
4122
4126
  //
4123
4127
  this.refs = new Map();
4124
4128
  this.refIds = new WeakMap();
4125
- this.refCounts = {};
4129
+ this.refCount = {};
4126
4130
  this.deletedRefs = new Set();
4127
4131
  this.callbacks = {};
4128
4132
  this.nextUniqueId = 0;
@@ -4135,7 +4139,7 @@ class ReferenceTracker {
4135
4139
  this.refs.set(refId, ref);
4136
4140
  this.refIds.set(ref, refId);
4137
4141
  if (incrementCount) {
4138
- this.refCounts[refId] = (this.refCounts[refId] || 0) + 1;
4142
+ this.refCount[refId] = (this.refCount[refId] || 0) + 1;
4139
4143
  }
4140
4144
  if (this.deletedRefs.has(refId)) {
4141
4145
  this.deletedRefs.delete(refId);
@@ -4143,7 +4147,7 @@ class ReferenceTracker {
4143
4147
  }
4144
4148
  // for decoding
4145
4149
  removeRef(refId) {
4146
- const refCount = this.refCounts[refId];
4150
+ const refCount = this.refCount[refId];
4147
4151
  if (refCount === undefined) {
4148
4152
  try {
4149
4153
  throw new DecodingWarning("trying to remove refId that doesn't exist: " + refId);
@@ -4163,7 +4167,7 @@ class ReferenceTracker {
4163
4167
  }
4164
4168
  return;
4165
4169
  }
4166
- if ((this.refCounts[refId] = refCount - 1) <= 0) {
4170
+ if ((this.refCount[refId] = refCount - 1) <= 0) {
4167
4171
  this.deletedRefs.add(refId);
4168
4172
  }
4169
4173
  }
@@ -4171,7 +4175,7 @@ class ReferenceTracker {
4171
4175
  this.refs.clear();
4172
4176
  this.deletedRefs.clear();
4173
4177
  this.callbacks = {};
4174
- this.refCounts = {};
4178
+ this.refCount = {};
4175
4179
  }
4176
4180
  // for decoding
4177
4181
  garbageCollectDeletedRefs() {
@@ -4179,7 +4183,7 @@ class ReferenceTracker {
4179
4183
  //
4180
4184
  // Skip active references.
4181
4185
  //
4182
- if (this.refCounts[refId] > 0) {
4186
+ if (this.refCount[refId] > 0) {
4183
4187
  return;
4184
4188
  }
4185
4189
  const ref = this.refs.get(refId);
@@ -4208,7 +4212,7 @@ class ReferenceTracker {
4208
4212
  }
4209
4213
  }
4210
4214
  this.refs.delete(refId); // remove ref
4211
- delete this.refCounts[refId]; // remove ref count
4215
+ delete this.refCount[refId]; // remove ref count
4212
4216
  delete this.callbacks[refId]; // remove callbacks
4213
4217
  });
4214
4218
  // clear deleted refs.
@@ -4265,15 +4269,19 @@ class Decoder {
4265
4269
  //
4266
4270
  if (bytes[it.offset] == SWITCH_TO_STRUCTURE) {
4267
4271
  it.offset++;
4268
- this.currentRefId = decode.number(bytes, it);
4269
- const nextRef = $root.refs.get(this.currentRefId);
4272
+ const nextRefId = decode.number(bytes, it);
4273
+ const nextRef = $root.refs.get(nextRefId);
4270
4274
  //
4271
4275
  // Trying to access a reference that haven't been decoded yet.
4272
4276
  //
4273
4277
  if (!nextRef) {
4274
- throw new Error(`"refId" not found: ${this.currentRefId}`);
4278
+ console.error(`"refId" not found: ${nextRefId}`, { previousRef: this, previousRefId: this.currentRefId });
4279
+ console.warn("Please report this to the developers. All refIds =>");
4280
+ console.warn(Schema.debugRefIdsDecoder(this));
4281
+ this.skipCurrentStructure(bytes, it, totalBytes);
4275
4282
  }
4276
4283
  ref[$onDecodeEnd]?.();
4284
+ this.currentRefId = nextRefId;
4277
4285
  ref = nextRef;
4278
4286
  decoder = ref.constructor[$decoder];
4279
4287
  continue;
@@ -4281,20 +4289,7 @@ class Decoder {
4281
4289
  const result = decoder(this, bytes, it, ref, allChanges);
4282
4290
  if (result === DEFINITION_MISMATCH) {
4283
4291
  console.warn("@colyseus/schema: definition mismatch");
4284
- //
4285
- // keep skipping next bytes until reaches a known structure
4286
- // by local decoder.
4287
- //
4288
- const nextIterator = { offset: it.offset };
4289
- while (it.offset < totalBytes) {
4290
- if (bytes[it.offset] === SWITCH_TO_STRUCTURE) {
4291
- nextIterator.offset = it.offset + 1;
4292
- if ($root.refs.has(decode.number(bytes, nextIterator))) {
4293
- break;
4294
- }
4295
- }
4296
- it.offset++;
4297
- }
4292
+ this.skipCurrentStructure(bytes, it, totalBytes);
4298
4293
  continue;
4299
4294
  }
4300
4295
  }
@@ -4306,6 +4301,22 @@ class Decoder {
4306
4301
  $root.garbageCollectDeletedRefs();
4307
4302
  return allChanges;
4308
4303
  }
4304
+ skipCurrentStructure(bytes, it, totalBytes) {
4305
+ //
4306
+ // keep skipping next bytes until reaches a known structure
4307
+ // by local decoder.
4308
+ //
4309
+ const nextIterator = { offset: it.offset };
4310
+ while (it.offset < totalBytes) {
4311
+ if (bytes[it.offset] === SWITCH_TO_STRUCTURE) {
4312
+ nextIterator.offset = it.offset + 1;
4313
+ if (this.root.refs.has(decode.number(bytes, nextIterator))) {
4314
+ break;
4315
+ }
4316
+ }
4317
+ it.offset++;
4318
+ }
4319
+ }
4309
4320
  getInstanceType(bytes, it, defaultType) {
4310
4321
  let type;
4311
4322
  if (bytes[it.offset] === TYPE_ID) {
@@ -5008,9 +5019,7 @@ class StateView {
5008
5019
  // DELETE / DELETE BY REF ID
5009
5020
  changes[changeTree.parentIndex] = OPERATION.DELETE;
5010
5021
  // Remove child schema from visible set
5011
- changeTree.forEachChild((childChangeTree) => {
5012
- this.visible.delete(childChangeTree);
5013
- });
5022
+ this._recursiveDeleteVisibleChangeTree(changeTree);
5014
5023
  }
5015
5024
  else {
5016
5025
  // delete all "tagged" properties.
@@ -5075,6 +5084,12 @@ class StateView {
5075
5084
  }
5076
5085
  return isVisible;
5077
5086
  }
5087
+ _recursiveDeleteVisibleChangeTree(changeTree) {
5088
+ changeTree.forEachChild((childChangeTree) => {
5089
+ this.visible.delete(childChangeTree);
5090
+ this._recursiveDeleteVisibleChangeTree(childChangeTree);
5091
+ });
5092
+ }
5078
5093
  }
5079
5094
 
5080
5095
  registerType("map", { constructor: MapSchema });