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