Skip to content

Commit 2a6780d

Browse files
committed
fix 'trying to remove refId with 0 refCount' at decoding.
1 parent b8f05d6 commit 2a6780d

File tree

4 files changed

+24
-18
lines changed

4 files changed

+24
-18
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.16",
3+
"version": "3.0.17",
44
"description": "Binary state serializer with delta encoding for games",
55
"bin": {
66
"schema-codegen": "./bin/schema-codegen",

src/decoder/DecodeOperation.ts

Lines changed: 4 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -73,18 +73,6 @@ export function decodeValue(
7373
const refId = decode.number(bytes, it);
7474
value = $root.refs.get(refId);
7575

76-
if (previousValue) {
77-
const previousRefId = $root.refIds.get(previousValue);
78-
if (
79-
previousRefId &&
80-
refId !== previousRefId &&
81-
// FIXME: we may need to check for REPLACE operation as well
82-
((operation & OPERATION.DELETE) === OPERATION.DELETE)
83-
) {
84-
$root.removeRef(previousRefId);
85-
}
86-
}
87-
8876
if ((operation & OPERATION.ADD) === OPERATION.ADD) {
8977
const childType = decoder.getInstanceType(bytes, it, type);
9078
if (!value) {
@@ -101,7 +89,6 @@ export function decodeValue(
10189
);
10290
}
10391

104-
10592
} else if (typeof(type) === "string") {
10693
//
10794
// primitive value (number, string, boolean, etc)
@@ -123,8 +110,6 @@ export function decodeValue(
123110
let previousRefId = $root.refIds.get(previousValue);
124111

125112
if (previousRefId !== undefined && refId !== previousRefId) {
126-
$root.removeRef(previousRefId);
127-
128113
//
129114
// enqueue onRemove if structure has been replaced.
130115
//
@@ -153,7 +138,10 @@ export function decodeValue(
153138
}
154139
}
155140

156-
$root.addRef(refId, value, (valueRef !== previousValue));
141+
$root.addRef(refId, value, (
142+
valueRef !== previousValue ||
143+
(operation === OPERATION.DELETE_AND_ADD && valueRef === previousValue)
144+
));
157145
}
158146

159147
return { value, previousValue };

test/InstanceSharing.test.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import * as assert from "assert";
22
import { Schema, type, ArraySchema, MapSchema, Reflection } from "../src";
33
import { $changes } from "../src/types/symbols";
4-
import { assertDeepStrictEqualEncodeAll, createInstanceFromReflection, getCallbacks, getDecoder, getEncoder } from "./Schema";
4+
import { assertDeepStrictEqualEncodeAll, assertRefIdCounts, createInstanceFromReflection, getCallbacks, getDecoder, getEncoder } from "./Schema";
55

66
describe("Instance sharing", () => {
77
class Position extends Schema {
@@ -71,6 +71,8 @@ describe("Instance sharing", () => {
7171

7272
}, decodedState.toJSON());
7373

74+
assertRefIdCounts(state, decodedState);
75+
7476
assert.strictEqual(5, decoder.root.refs.size, "Player and Position structures should remain.");
7577
assertDeepStrictEqualEncodeAll(state);
7678
});
@@ -105,6 +107,7 @@ describe("Instance sharing", () => {
105107
for (let refId in decoder.root.refCounts) {
106108
assert.strictEqual(decoder.root.refCounts[refId], encoder.root.refCount[refId]);
107109
}
110+
assertRefIdCounts(state, decodedState);
108111

109112
assertDeepStrictEqualEncodeAll(state);
110113
});
@@ -454,6 +457,7 @@ describe("Instance sharing", () => {
454457

455458
decodedState.decode(state.encode());
456459
assert.deepStrictEqual(state.toJSON(), decodedState.toJSON());
460+
assertRefIdCounts(state, decodedState);
457461

458462
assertDeepStrictEqualEncodeAll(state);
459463
});

test/Schema.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,11 +33,25 @@ export function assertDeepStrictEqualEncodeAll(state: Schema) {
3333
freshDecode.decode(encodeAll);
3434
assert.deepStrictEqual(freshDecode.toJSON(), state.toJSON());
3535

36+
assertRefIdCounts(state, freshDecode);
37+
3638
// // perform a regular encode right full decode
3739
// freshDecode.decode(state.encode());
3840
// assert.deepStrictEqual(freshDecode.toJSON(), state.toJSON());
3941
}
4042

43+
export function assertRefIdCounts(source: Schema, target: Schema) {
44+
// assert ref counts
45+
const encoder = getEncoder(source);
46+
const decoder = getDecoder(target);
47+
48+
for (const refId in encoder.root.refCount) {
49+
const encoderRefCount = encoder.root.refCount[refId];
50+
const decoderRefCount = decoder.root.refCounts[refId] ?? 0;
51+
assert.strictEqual(encoderRefCount, decoderRefCount, `refCount mismatch for ${refId}`);
52+
}
53+
}
54+
4155
export function getEncoder(state: Schema) {
4256
if (!state['_encoder']) { state['_encoder'] = new Encoder(state); }
4357
return state['_encoder'] as Encoder;

0 commit comments

Comments
 (0)