Skip to content

Commit 937bc7c

Browse files
committed
fix 'Decode warning: trying to remove refId' when removing array items.
1 parent 9e6b63c commit 937bc7c

File tree

5 files changed

+46
-48
lines changed

5 files changed

+46
-48
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@colyseus/schema",
3-
"version": "3.0.9",
3+
"version": "3.0.10",
44
"description": "Binary state serializer with delta encoding for games",
55
"bin": {
66
"schema-codegen": "./bin/schema-codegen",

src/Schema.ts

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,6 @@ export class Schema {
1919
static [$encoder] = encodeSchemaOperation;
2020
static [$decoder] = decodeSchemaOperation;
2121

22-
// public [$changes]: ChangeTree;
23-
2422
/**
2523
* Assign the property descriptors required to track changes on this instance.
2624
* @param instance
@@ -177,18 +175,18 @@ export class Schema {
177175
/**
178176
* Inspect the `refId` of all Schema instances in the tree. Optionally display the contents of the instance.
179177
*
180-
* @param instance Schema instance
178+
* @param ref Schema instance
181179
* @param showContents display JSON contents of the instance
182180
* @returns
183181
*/
184-
static debugRefIds(instance: Ref, showContents: boolean = false, level: number = 0) {
185-
const ref = instance;
186-
const changeTree = ref[$changes];
187-
182+
static debugRefIds(ref: Ref, showContents: boolean = false, level: number = 0) {
188183
const contents = (showContents) ? ` - ${JSON.stringify(ref.toJSON())}` : "";
189184

185+
const changeTree: ChangeTree = ref[$changes];
186+
const refId = changeTree.refId;
187+
190188
let output = "";
191-
output += `${getIndent(level)}${ref.constructor.name} (refId: ${ref[$changes].refId})${contents}\n`;
189+
output += `${getIndent(level)}${ref.constructor.name} (refId: ${refId})${contents}\n`;
192190

193191
changeTree.forEachChild((childChangeTree) =>
194192
output += this.debugRefIds(childChangeTree.ref, showContents, level + 1));

src/decoder/ReferenceTracker.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ export class ReferenceTracker {
5656

5757
if (refCount === undefined) {
5858
try {
59-
throw new DecodingWarning("trying to remove refId that doesn't exist");
59+
throw new DecodingWarning("trying to remove refId that doesn't exist: " + refId);
6060
} catch (e) {
6161
console.warn(e);
6262
}

src/types/custom/ArraySchema.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,6 @@ export class ArraySchema<V = any> implements Array<V>, Collection<number, V> {
3838
* - Then, the encoder iterates over all "owned" properties per instance and encodes them.
3939
*/
4040
static [$filter] (ref: ArraySchema, index: number, view: StateView) {
41-
// console.log("ArraSchema[$filter] VIEW??", !view)
4241
return (
4342
!view ||
4443
typeof (ref[$childType]) === "string" ||
@@ -767,6 +766,7 @@ export class ArraySchema<V = any> implements Array<V>, Collection<number, V> {
767766

768767
protected [$deleteByIndex](index: number) {
769768
this.items[index] = undefined;
769+
this.tmpItems[index] = undefined; // TODO: do not try to get "tmpItems" at decoding time.
770770
}
771771

772772
protected [$onEncodeEnd]() {
@@ -776,6 +776,7 @@ export class ArraySchema<V = any> implements Array<V>, Collection<number, V> {
776776

777777
protected [$onDecodeEnd]() {
778778
this.items = this.items.filter((item) => item !== undefined);
779+
this.tmpItems = this.items.slice(); // TODO: do no use "tmpItems" at decoding time.
779780
}
780781

781782
toArray() {

test/ArraySchema.test.ts

Lines changed: 36 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1245,43 +1245,6 @@ describe("ArraySchema Tests", () => {
12451245
assertDeepStrictEqualEncodeAll(state);
12461246
});
12471247

1248-
xit("TODO: fix 'Decode warning: trying to remove refId that doesn't exist'", () => {
1249-
class Item extends Schema {
1250-
@type("string") name: string;
1251-
constructor(name) {
1252-
super();
1253-
this.name = name;
1254-
}
1255-
}
1256-
class Player extends Schema {
1257-
@type([Item]) items = new ArraySchema<Item>();
1258-
}
1259-
class State extends Schema {
1260-
@type(Player) player = new Player();
1261-
}
1262-
1263-
const state = new State();
1264-
const decodedState = new State();
1265-
state.player.items.push(new Item("Item 1"));
1266-
state.player.items.push(new Item("Item 2"));
1267-
decodedState.decode(state.encodeAll());
1268-
1269-
decodedState.decode(state.encode());
1270-
assert.deepStrictEqual(state.toJSON(), decodedState.toJSON());
1271-
1272-
// Remove Item 1
1273-
state.player.items.splice(0, 1);
1274-
decodedState.decode(state.encode());
1275-
1276-
assert.deepStrictEqual(state.toJSON(), decodedState.toJSON());
1277-
state.player.items.splice(0, 1);
1278-
decodedState.decode(state.encode());
1279-
1280-
assert.deepStrictEqual(state.toJSON(), decodedState.toJSON());
1281-
1282-
assertDeepStrictEqualEncodeAll(state);
1283-
});
1284-
12851248
it("should allow to transfer object between ArraySchema", () => {
12861249
class Item extends Schema {
12871250
@type("uint8") id: number;
@@ -1976,6 +1939,42 @@ describe("ArraySchema Tests", () => {
19761939
assert.strictEqual(50, copy[0]);
19771940
assert.strictEqual(100, copy[1]);
19781941
});
1942+
1943+
it("fix 'Decode warning: trying to remove refId that doesn't exist'", () => {
1944+
/**
1945+
* This test was triggering "Decode warning: trying to remove refId that doesn't exist"
1946+
* when removing items from an ArraySchema.
1947+
*
1948+
* The issue was caused by ArraySchema using `tmpItems` during `$getByIndex`.
1949+
* TODO: need to avoid using `tmpItems` during decoding.
1950+
*/
1951+
class Item extends Schema {
1952+
@type("string") name: string;
1953+
}
1954+
class Player extends Schema {
1955+
@type([Item]) items = new ArraySchema<Item>();
1956+
}
1957+
class State extends Schema {
1958+
@type(Player) player = new Player();
1959+
}
1960+
1961+
const state = new State();
1962+
const decodedState = new State();
1963+
state.player.items.push(new Item().assign({ name: "Item 1" }));
1964+
state.player.items.push(new Item().assign({ name: "Item 2" }));
1965+
decodedState.decode(state.encodeAll());
1966+
1967+
decodedState.decode(state.encode());
1968+
1969+
state.player.items.splice(0, 1);
1970+
decodedState.decode(state.encode());
1971+
1972+
state.player.items.splice(0, 1);
1973+
decodedState.decode(state.encode());
1974+
1975+
assert.deepStrictEqual(state.toJSON(), decodedState.toJSON());
1976+
assertDeepStrictEqualEncodeAll(state);
1977+
});
19791978
});
19801979

19811980
});

0 commit comments

Comments
 (0)