@colyseus/schema 3.0.22 → 3.0.24

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.
@@ -1831,7 +1831,7 @@ class ArraySchema {
1831
1831
  return (!view ||
1832
1832
  typeof (ref[$childType]) === "string" ||
1833
1833
  // view.items.has(ref[$getByIndex](index)[$changes])
1834
- view.items.has(ref['tmpItems'][index]?.[$changes]));
1834
+ view.visible.has(ref['tmpItems'][index]?.[$changes]));
1835
1835
  }
1836
1836
  static is(type) {
1837
1837
  return (
@@ -2487,7 +2487,7 @@ class MapSchema {
2487
2487
  static [(_a$3 = $encoder, _b$3 = $decoder, $filter)](ref, index, view) {
2488
2488
  return (!view ||
2489
2489
  typeof (ref[$childType]) === "string" ||
2490
- view.items.has((ref[$getByIndex](index) ?? ref.deletedItems[index])[$changes]));
2490
+ view.visible.has((ref[$getByIndex](index) ?? ref.deletedItems[index])[$changes]));
2491
2491
  }
2492
2492
  static is(type) {
2493
2493
  return type['map'] !== undefined;
@@ -3104,7 +3104,7 @@ class Schema {
3104
3104
  }
3105
3105
  else if (tag === DEFAULT_VIEW_TAG) {
3106
3106
  // view pass: default tag
3107
- return view.items.has(ref[$changes]);
3107
+ return view.visible.has(ref[$changes]);
3108
3108
  }
3109
3109
  else {
3110
3110
  // view pass: custom tag
@@ -3317,7 +3317,7 @@ class CollectionSchema {
3317
3317
  static [(_a$1 = $encoder, _b$1 = $decoder, $filter)](ref, index, view) {
3318
3318
  return (!view ||
3319
3319
  typeof (ref[$childType]) === "string" ||
3320
- view.items.has((ref[$getByIndex](index) ?? ref.deletedItems[index])[$changes]));
3320
+ view.visible.has((ref[$getByIndex](index) ?? ref.deletedItems[index])[$changes]));
3321
3321
  }
3322
3322
  static is(type) {
3323
3323
  return type['collection'] !== undefined;
@@ -3477,7 +3477,7 @@ class SetSchema {
3477
3477
  static [(_a = $encoder, _b = $decoder, $filter)](ref, index, view) {
3478
3478
  return (!view ||
3479
3479
  typeof (ref[$childType]) === "string" ||
3480
- view.items.has((ref[$getByIndex](index) ?? ref.deletedItems[index])[$changes]));
3480
+ view.visible.has((ref[$getByIndex](index) ?? ref.deletedItems[index])[$changes]));
3481
3481
  }
3482
3482
  static is(type) {
3483
3483
  return type['set'] !== undefined;
@@ -3797,7 +3797,7 @@ class Encoder {
3797
3797
  for (let i = 0, numChangeTrees = changeTrees.length; i < numChangeTrees; i++) {
3798
3798
  const changeTree = changeTrees[i];
3799
3799
  if (hasView) {
3800
- if (!view.items.has(changeTree)) {
3800
+ if (!view.visible.has(changeTree)) {
3801
3801
  view.invisible.add(changeTree);
3802
3802
  continue; // skip this change tree
3803
3803
  }
@@ -4713,11 +4713,12 @@ function getRawChangesCallback(decoder, callback) {
4713
4713
  }
4714
4714
 
4715
4715
  class StateView {
4716
- constructor() {
4716
+ constructor(iterable = false) {
4717
+ this.iterable = iterable;
4717
4718
  /**
4718
4719
  * List of ChangeTree's that are visible to this view
4719
4720
  */
4720
- this.items = new WeakSet();
4721
+ this.visible = new WeakSet();
4721
4722
  /**
4722
4723
  * List of ChangeTree's that are invisible to this view
4723
4724
  */
@@ -4727,17 +4728,36 @@ class StateView {
4727
4728
  * (This is used to force encoding a property, even if it was not changed)
4728
4729
  */
4729
4730
  this.changes = new Map();
4731
+ if (iterable) {
4732
+ this.items = [];
4733
+ }
4730
4734
  }
4731
4735
  // TODO: allow to set multiple tags at once
4732
4736
  add(obj, tag = DEFAULT_VIEW_TAG, checkIncludeParent = true) {
4733
- if (!obj?.[$changes]) {
4737
+ const changeTree = obj?.[$changes];
4738
+ if (!changeTree) {
4734
4739
  console.warn("StateView#add(), invalid object:", obj);
4735
4740
  return this;
4736
4741
  }
4742
+ else if (!changeTree.parent &&
4743
+ changeTree.refId !== 0 // allow root object
4744
+ ) {
4745
+ /**
4746
+ * TODO: can we avoid this?
4747
+ *
4748
+ * When the "parent" structure has the @view() tag, it is currently
4749
+ * not possible to identify it has to be added to the view as well
4750
+ * (this.addParentOf() is not called).
4751
+ */
4752
+ throw new Error(`Cannot add a detached instance to the StateView. Make sure to assign the "${changeTree.ref.constructor.name}" instance to the state before calling view.add()`);
4753
+ }
4737
4754
  // FIXME: ArraySchema/MapSchema do not have metadata
4738
4755
  const metadata = obj.constructor[Symbol.metadata];
4739
- const changeTree = obj[$changes];
4740
- this.items.add(changeTree);
4756
+ this.visible.add(changeTree);
4757
+ // add to iterable list (only the explicitly added items)
4758
+ if (this.iterable && checkIncludeParent) {
4759
+ this.items.push(obj);
4760
+ }
4741
4761
  // add parent ChangeTree's
4742
4762
  // - if it was invisible to this view
4743
4763
  // - if it were previously filtered out
@@ -4811,9 +4831,9 @@ class StateView {
4811
4831
  addParentOf(childChangeTree, tag) {
4812
4832
  const changeTree = childChangeTree.parent[$changes];
4813
4833
  const parentIndex = childChangeTree.parentIndex;
4814
- if (!this.items.has(changeTree)) {
4834
+ if (!this.visible.has(changeTree)) {
4815
4835
  // view must have all "changeTree" parent tree
4816
- this.items.add(changeTree);
4836
+ this.visible.add(changeTree);
4817
4837
  // add parent's parent
4818
4838
  const parentChangeTree = changeTree.parent?.[$changes];
4819
4839
  if (parentChangeTree && (parentChangeTree.filteredChanges !== undefined)) {
@@ -4844,13 +4864,19 @@ class StateView {
4844
4864
  changes[parentIndex] = exports.OPERATION.ADD;
4845
4865
  }
4846
4866
  }
4847
- remove(obj, tag = DEFAULT_VIEW_TAG) {
4867
+ remove(obj, tag = DEFAULT_VIEW_TAG, _isClear = false) {
4848
4868
  const changeTree = obj[$changes];
4849
4869
  if (!changeTree) {
4850
4870
  console.warn("StateView#remove(), invalid object:", obj);
4851
4871
  return this;
4852
4872
  }
4853
- this.items.delete(changeTree);
4873
+ this.visible.delete(changeTree);
4874
+ // remove from iterable list
4875
+ if (this.iterable &&
4876
+ !_isClear // no need to remove during clear(), as it will be cleared entirely
4877
+ ) {
4878
+ spliceOne(this.items, this.items.indexOf(obj));
4879
+ }
4854
4880
  const ref = changeTree.ref;
4855
4881
  const metadata = ref.constructor[Symbol.metadata]; // ArraySchema/MapSchema do not have metadata
4856
4882
  let changes = this.changes.get(changeTree.refId);
@@ -4899,12 +4925,22 @@ class StateView {
4899
4925
  return this;
4900
4926
  }
4901
4927
  has(obj) {
4902
- return this.items.has(obj[$changes]);
4928
+ return this.visible.has(obj[$changes]);
4903
4929
  }
4904
4930
  hasTag(ob, tag = DEFAULT_VIEW_TAG) {
4905
4931
  const tags = this.tags?.get(ob[$changes]);
4906
4932
  return tags?.has(tag) ?? false;
4907
4933
  }
4934
+ clear() {
4935
+ if (!this.iterable) {
4936
+ throw new Error("StateView#clear() is only available for iterable StateView's. Use StateView(iterable: true) constructor.");
4937
+ }
4938
+ for (let i = 0, l = this.items.length; i < l; i++) {
4939
+ this.remove(this.items[i], DEFAULT_VIEW_TAG, true);
4940
+ }
4941
+ // clear items array
4942
+ this.items.length = 0;
4943
+ }
4908
4944
  }
4909
4945
 
4910
4946
  registerType("map", { constructor: MapSchema });