@colyseus/schema 3.0.0-alpha.4 → 3.0.0-alpha.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.
- package/README.md +131 -61
- package/bin/schema-debug +94 -0
- package/build/cjs/index.js +1521 -809
- package/build/cjs/index.js.map +1 -1
- package/build/esm/index.mjs +1519 -808
- package/build/esm/index.mjs.map +1 -1
- package/build/umd/index.js +1528 -816
- package/lib/Metadata.d.ts +21 -9
- package/lib/Metadata.js +169 -32
- package/lib/Metadata.js.map +1 -1
- package/lib/Reflection.d.ts +19 -4
- package/lib/Reflection.js +66 -32
- package/lib/Reflection.js.map +1 -1
- package/lib/Schema.d.ts +4 -4
- package/lib/Schema.js +44 -50
- package/lib/Schema.js.map +1 -1
- package/lib/annotations.d.ts +31 -34
- package/lib/annotations.js +110 -160
- package/lib/annotations.js.map +1 -1
- package/lib/bench_encode.d.ts +1 -0
- package/lib/bench_encode.js +130 -0
- package/lib/bench_encode.js.map +1 -0
- package/lib/codegen/api.js +1 -2
- package/lib/codegen/api.js.map +1 -1
- package/lib/codegen/languages/cpp.js +1 -2
- package/lib/codegen/languages/cpp.js.map +1 -1
- package/lib/codegen/languages/csharp.js +1 -2
- package/lib/codegen/languages/csharp.js.map +1 -1
- package/lib/codegen/languages/haxe.js +1 -2
- package/lib/codegen/languages/haxe.js.map +1 -1
- package/lib/codegen/languages/java.js +1 -2
- package/lib/codegen/languages/java.js.map +1 -1
- package/lib/codegen/languages/js.js +1 -2
- package/lib/codegen/languages/js.js.map +1 -1
- package/lib/codegen/languages/lua.js +1 -2
- package/lib/codegen/languages/lua.js.map +1 -1
- package/lib/codegen/languages/ts.js +1 -2
- package/lib/codegen/languages/ts.js.map +1 -1
- package/lib/codegen/parser.js +85 -3
- package/lib/codegen/parser.js.map +1 -1
- package/lib/codegen/types.js +6 -3
- package/lib/codegen/types.js.map +1 -1
- package/lib/debug.d.ts +1 -0
- package/lib/debug.js +51 -0
- package/lib/debug.js.map +1 -0
- package/lib/decoder/DecodeOperation.d.ts +0 -1
- package/lib/decoder/DecodeOperation.js +30 -12
- package/lib/decoder/DecodeOperation.js.map +1 -1
- package/lib/decoder/Decoder.d.ts +6 -7
- package/lib/decoder/Decoder.js +9 -9
- package/lib/decoder/Decoder.js.map +1 -1
- package/lib/decoder/ReferenceTracker.js +3 -2
- package/lib/decoder/ReferenceTracker.js.map +1 -1
- package/lib/decoder/strategy/RawChanges.js +1 -2
- package/lib/decoder/strategy/RawChanges.js.map +1 -1
- package/lib/decoder/strategy/StateCallbacks.d.ts +44 -11
- package/lib/decoder/strategy/StateCallbacks.js +75 -65
- package/lib/decoder/strategy/StateCallbacks.js.map +1 -1
- package/lib/encoder/ChangeTree.d.ts +27 -21
- package/lib/encoder/ChangeTree.js +246 -186
- package/lib/encoder/ChangeTree.js.map +1 -1
- package/lib/encoder/EncodeOperation.d.ts +3 -6
- package/lib/encoder/EncodeOperation.js +47 -61
- package/lib/encoder/EncodeOperation.js.map +1 -1
- package/lib/encoder/Encoder.d.ts +9 -8
- package/lib/encoder/Encoder.js +165 -88
- package/lib/encoder/Encoder.js.map +1 -1
- package/lib/encoder/Root.d.ts +22 -0
- package/lib/encoder/Root.js +81 -0
- package/lib/encoder/Root.js.map +1 -0
- package/lib/encoder/StateView.d.ts +7 -7
- package/lib/encoder/StateView.js +70 -74
- package/lib/encoder/StateView.js.map +1 -1
- package/lib/encoding/assert.d.ts +2 -1
- package/lib/encoding/assert.js +5 -5
- package/lib/encoding/assert.js.map +1 -1
- package/lib/encoding/decode.js +20 -21
- package/lib/encoding/decode.js.map +1 -1
- package/lib/encoding/encode.d.ts +2 -2
- package/lib/encoding/encode.js +52 -48
- package/lib/encoding/encode.js.map +1 -1
- package/lib/encoding/spec.d.ts +2 -1
- package/lib/encoding/spec.js +1 -0
- package/lib/encoding/spec.js.map +1 -1
- package/lib/index.d.ts +6 -3
- package/lib/index.js +19 -13
- package/lib/index.js.map +1 -1
- package/lib/types/HelperTypes.d.ts +34 -2
- package/lib/types/HelperTypes.js.map +1 -1
- package/lib/types/TypeContext.d.ts +23 -0
- package/lib/types/TypeContext.js +111 -0
- package/lib/types/TypeContext.js.map +1 -0
- package/lib/types/custom/ArraySchema.d.ts +2 -2
- package/lib/types/custom/ArraySchema.js +33 -22
- package/lib/types/custom/ArraySchema.js.map +1 -1
- package/lib/types/custom/CollectionSchema.js +1 -0
- package/lib/types/custom/CollectionSchema.js.map +1 -1
- package/lib/types/custom/MapSchema.d.ts +3 -1
- package/lib/types/custom/MapSchema.js +12 -4
- package/lib/types/custom/MapSchema.js.map +1 -1
- package/lib/types/custom/SetSchema.js +1 -0
- package/lib/types/custom/SetSchema.js.map +1 -1
- package/lib/types/registry.js +3 -4
- package/lib/types/registry.js.map +1 -1
- package/lib/types/symbols.d.ts +8 -5
- package/lib/types/symbols.js +9 -6
- package/lib/types/symbols.js.map +1 -1
- package/lib/types/utils.js +1 -2
- package/lib/types/utils.js.map +1 -1
- package/lib/utils.js +9 -7
- package/lib/utils.js.map +1 -1
- package/package.json +7 -6
- package/src/Metadata.ts +190 -42
- package/src/Reflection.ts +77 -39
- package/src/Schema.ts +59 -64
- package/src/annotations.ts +155 -203
- package/src/bench_encode.ts +108 -0
- package/src/codegen/parser.ts +107 -0
- package/src/codegen/types.ts +1 -0
- package/src/debug.ts +55 -0
- package/src/decoder/DecodeOperation.ts +40 -12
- package/src/decoder/Decoder.ts +14 -12
- package/src/decoder/ReferenceTracker.ts +3 -2
- package/src/decoder/strategy/StateCallbacks.ts +153 -82
- package/src/encoder/ChangeTree.ts +286 -202
- package/src/encoder/EncodeOperation.ts +77 -77
- package/src/encoder/Encoder.ts +201 -96
- package/src/encoder/Root.ts +93 -0
- package/src/encoder/StateView.ts +76 -88
- package/src/encoding/assert.ts +4 -3
- package/src/encoding/encode.ts +37 -31
- package/src/encoding/spec.ts +1 -0
- package/src/index.ts +8 -14
- package/src/types/HelperTypes.ts +54 -2
- package/src/types/TypeContext.ts +133 -0
- package/src/types/custom/ArraySchema.ts +49 -19
- package/src/types/custom/CollectionSchema.ts +1 -0
- package/src/types/custom/MapSchema.ts +18 -5
- package/src/types/custom/SetSchema.ts +1 -0
- package/src/types/symbols.ts +10 -7
- package/src/utils.ts +7 -3
package/src/codegen/parser.ts
CHANGED
|
@@ -148,6 +148,49 @@ function inspectNode(node: ts.Node, context: Context, decoratorName: string) {
|
|
|
148
148
|
defineProperty(property, typeArgument);
|
|
149
149
|
}
|
|
150
150
|
|
|
151
|
+
} else if (
|
|
152
|
+
node.getText() === "setFields" &&
|
|
153
|
+
(
|
|
154
|
+
node.parent.kind === ts.SyntaxKind.CallExpression ||
|
|
155
|
+
node.parent.kind === ts.SyntaxKind.PropertyAccessExpression
|
|
156
|
+
)
|
|
157
|
+
) {
|
|
158
|
+
/**
|
|
159
|
+
* Metadata.setFields(klassName, { ... })
|
|
160
|
+
*/
|
|
161
|
+
const callExpression = (node.parent.kind === ts.SyntaxKind.PropertyAccessExpression)
|
|
162
|
+
? node.parent.parent as ts.CallExpression
|
|
163
|
+
: node.parent as ts.CallExpression;
|
|
164
|
+
|
|
165
|
+
if (callExpression.kind !== ts.SyntaxKind.CallExpression) {
|
|
166
|
+
break;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
const classNameNode = callExpression.arguments[0];
|
|
170
|
+
const className = ts.isClassExpression(classNameNode)
|
|
171
|
+
? classNameNode.name?.escapedText.toString()
|
|
172
|
+
: classNameNode.getText();
|
|
173
|
+
|
|
174
|
+
// skip if no className is provided
|
|
175
|
+
if (!className) { break; }
|
|
176
|
+
|
|
177
|
+
if (currentStructure.name !== className) {
|
|
178
|
+
currentStructure = new Class();
|
|
179
|
+
}
|
|
180
|
+
context.addStructure(currentStructure);
|
|
181
|
+
(currentStructure as Class).extends = "Schema"; // force extends to Schema
|
|
182
|
+
currentStructure.name = className;
|
|
183
|
+
|
|
184
|
+
const types = callExpression.arguments[1] as any;
|
|
185
|
+
for (let i = 0; i < types.properties.length; i++) {
|
|
186
|
+
const prop = types.properties[i];
|
|
187
|
+
|
|
188
|
+
const property = currentProperty || new Property();
|
|
189
|
+
property.name = prop.name.escapedText;
|
|
190
|
+
|
|
191
|
+
currentStructure.addProperty(property);
|
|
192
|
+
defineProperty(property, prop.initializer);
|
|
193
|
+
}
|
|
151
194
|
|
|
152
195
|
} else if (
|
|
153
196
|
node.getText() === "defineTypes" &&
|
|
@@ -192,6 +235,70 @@ function inspectNode(node: ts.Node, context: Context, decoratorName: string) {
|
|
|
192
235
|
|
|
193
236
|
break;
|
|
194
237
|
|
|
238
|
+
case ts.SyntaxKind.CallExpression:
|
|
239
|
+
/**
|
|
240
|
+
* Defining schema via `schema.schema({ ... })`
|
|
241
|
+
* - schema.schema({})
|
|
242
|
+
* - schema({})
|
|
243
|
+
* - ClassName.extends({})
|
|
244
|
+
*/
|
|
245
|
+
if (
|
|
246
|
+
(
|
|
247
|
+
(
|
|
248
|
+
(node as ts.CallExpression).expression?.getText() === "schema.schema" ||
|
|
249
|
+
(node as ts.CallExpression).expression?.getText() === "schema"
|
|
250
|
+
) ||
|
|
251
|
+
(
|
|
252
|
+
(node as ts.CallExpression).expression?.getText().indexOf(".extends") !== -1
|
|
253
|
+
)
|
|
254
|
+
) &&
|
|
255
|
+
(node as ts.CallExpression).arguments[0].kind === ts.SyntaxKind.ObjectLiteralExpression
|
|
256
|
+
) {
|
|
257
|
+
const callExpression = node as ts.CallExpression;
|
|
258
|
+
|
|
259
|
+
let className = callExpression.arguments[1]?.getText();
|
|
260
|
+
|
|
261
|
+
if (!className && callExpression.parent.kind === ts.SyntaxKind.VariableDeclaration) {
|
|
262
|
+
className = (callExpression.parent as ts.VariableDeclaration).name?.getText();
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
// skip if no className is provided
|
|
266
|
+
if (!className) { break; }
|
|
267
|
+
|
|
268
|
+
if (currentStructure.name !== className) {
|
|
269
|
+
currentStructure = new Class();
|
|
270
|
+
context.addStructure(currentStructure);
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
if ((node as ts.CallExpression).expression?.getText().indexOf(".extends") !== -1) {
|
|
274
|
+
// if it's using `.extends({})`
|
|
275
|
+
const extendsClass = (node as any).expression?.expression?.escapedText;
|
|
276
|
+
|
|
277
|
+
// skip if no extendsClass is provided
|
|
278
|
+
if (!extendsClass) { break; }
|
|
279
|
+
(currentStructure as Class).extends = extendsClass;
|
|
280
|
+
|
|
281
|
+
} else {
|
|
282
|
+
// if it's using `schema({})`
|
|
283
|
+
(currentStructure as Class).extends = "Schema"; // force extends to Schema
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
currentStructure.name = className;
|
|
287
|
+
|
|
288
|
+
const types = callExpression.arguments[0] as any;
|
|
289
|
+
for (let i = 0; i < types.properties.length; i++) {
|
|
290
|
+
const prop = types.properties[i];
|
|
291
|
+
|
|
292
|
+
const property = currentProperty || new Property();
|
|
293
|
+
property.name = prop.name.escapedText;
|
|
294
|
+
|
|
295
|
+
currentStructure.addProperty(property);
|
|
296
|
+
defineProperty(property, prop.initializer);
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
break;
|
|
301
|
+
|
|
195
302
|
case ts.SyntaxKind.EnumMember:
|
|
196
303
|
if (currentStructure instanceof Enum) {
|
|
197
304
|
const initializer = (node as any).initializer?.text;
|
package/src/codegen/types.ts
CHANGED
package/src/debug.ts
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import * as fs from "fs";
|
|
2
|
+
import { Reflection, Decoder } from "./index";
|
|
3
|
+
|
|
4
|
+
const contents = fs.readFileSync("/Users/endel/Projects/colyseus/clients/bubbits/project/@bubbits/backend/schema-debug.txt", { encoding: "utf8" }).toString();
|
|
5
|
+
|
|
6
|
+
let isCommentBlock = false;
|
|
7
|
+
let lastComment = "";
|
|
8
|
+
|
|
9
|
+
let decoder: Decoder;
|
|
10
|
+
|
|
11
|
+
function getBuffer(line: string) {
|
|
12
|
+
const start = line.lastIndexOf(":");
|
|
13
|
+
const buffer = Buffer.from(new Uint8Array(line.substring(start + 1).split(",").map(n => Number(n))));
|
|
14
|
+
console.log(`(${buffer.byteLength}) ${Array.from(buffer).join(",")}`)
|
|
15
|
+
// console.log("");
|
|
16
|
+
// console.log("");
|
|
17
|
+
// console.log("> ", line);
|
|
18
|
+
// console.log("> substring:", line.substring(start + 1))
|
|
19
|
+
return buffer;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function decode(buffer: Buffer) {
|
|
23
|
+
try {
|
|
24
|
+
decoder.decode(buffer);
|
|
25
|
+
} catch (e) {
|
|
26
|
+
console.error(e);
|
|
27
|
+
console.log("Last log:\n\n")
|
|
28
|
+
console.log(lastComment);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
contents.split("\n").forEach((line) => {
|
|
33
|
+
if (line.startsWith("#")) {
|
|
34
|
+
// reset last comment.
|
|
35
|
+
if (isCommentBlock === false) { lastComment = ""; }
|
|
36
|
+
|
|
37
|
+
isCommentBlock = true;
|
|
38
|
+
lastComment += line.substring(line.indexOf(":") + 1) + "\n";
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
isCommentBlock = false;
|
|
43
|
+
|
|
44
|
+
if (line.startsWith("handshake:") && !decoder) {
|
|
45
|
+
decoder = Reflection.decode(getBuffer(line));
|
|
46
|
+
|
|
47
|
+
} else if (line.startsWith("state:")) {
|
|
48
|
+
decode(getBuffer(line));
|
|
49
|
+
|
|
50
|
+
} else if (line.startsWith("patch:")) {
|
|
51
|
+
decode(getBuffer(line));
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
console.log(decoder.state.toJSON());
|
|
@@ -4,7 +4,7 @@ import { Schema } from "../Schema";
|
|
|
4
4
|
import type { Ref } from "../encoder/ChangeTree";
|
|
5
5
|
import type { Decoder } from "./Decoder";
|
|
6
6
|
import * as decode from "../encoding/decode";
|
|
7
|
-
import { $
|
|
7
|
+
import { $childType, $deleteByIndex, $getByIndex } from "../types/symbols";
|
|
8
8
|
|
|
9
9
|
import type { MapSchema } from "../types/custom/MapSchema";
|
|
10
10
|
import type { ArraySchema } from "../types/custom/ArraySchema";
|
|
@@ -43,7 +43,7 @@ export function decodeValue(
|
|
|
43
43
|
it: decode.Iterator,
|
|
44
44
|
allChanges: DataChange[],
|
|
45
45
|
) {
|
|
46
|
-
const $root = decoder
|
|
46
|
+
const $root = decoder.root;
|
|
47
47
|
const previousValue = ref[$getByIndex](index);
|
|
48
48
|
|
|
49
49
|
let value: any;
|
|
@@ -105,7 +105,14 @@ export function decodeValue(
|
|
|
105
105
|
value = decoder.createInstanceOfType(childType);
|
|
106
106
|
}
|
|
107
107
|
|
|
108
|
-
$root.addRef(
|
|
108
|
+
$root.addRef(
|
|
109
|
+
refId,
|
|
110
|
+
value,
|
|
111
|
+
(
|
|
112
|
+
value !== previousValue || // increment ref count if value has changed
|
|
113
|
+
(operation === OPERATION.DELETE_AND_ADD && value === previousValue) // increment ref count if the same instance is being added again
|
|
114
|
+
)
|
|
115
|
+
);
|
|
109
116
|
}
|
|
110
117
|
|
|
111
118
|
|
|
@@ -174,7 +181,7 @@ export const decodeSchemaOperation: DecodeOperation = function (
|
|
|
174
181
|
allChanges: DataChange[],
|
|
175
182
|
) {
|
|
176
183
|
const first_byte = bytes[it.offset++];
|
|
177
|
-
const metadata: Metadata = ref
|
|
184
|
+
const metadata: Metadata = ref.constructor[Symbol.metadata];
|
|
178
185
|
|
|
179
186
|
// "compressed" index + operation
|
|
180
187
|
const operation = (first_byte >> 6) << 6
|
|
@@ -182,21 +189,24 @@ export const decodeSchemaOperation: DecodeOperation = function (
|
|
|
182
189
|
|
|
183
190
|
// skip early if field is not defined
|
|
184
191
|
const field = metadata[index];
|
|
185
|
-
if (field === undefined) {
|
|
192
|
+
if (field === undefined) {
|
|
193
|
+
console.warn("@colyseus/schema: field not defined at", { index, ref: ref.constructor.name, metadata });
|
|
194
|
+
return DEFINITION_MISMATCH;
|
|
195
|
+
}
|
|
186
196
|
|
|
187
197
|
const { value, previousValue } = decodeValue(
|
|
188
198
|
decoder,
|
|
189
199
|
operation,
|
|
190
200
|
ref,
|
|
191
201
|
index,
|
|
192
|
-
|
|
202
|
+
field.type,
|
|
193
203
|
bytes,
|
|
194
204
|
it,
|
|
195
205
|
allChanges,
|
|
196
206
|
);
|
|
197
207
|
|
|
198
208
|
if (value !== null && value !== undefined) {
|
|
199
|
-
ref[field] = value;
|
|
209
|
+
ref[field.name] = value;
|
|
200
210
|
}
|
|
201
211
|
|
|
202
212
|
// add change
|
|
@@ -205,7 +215,7 @@ export const decodeSchemaOperation: DecodeOperation = function (
|
|
|
205
215
|
ref,
|
|
206
216
|
refId: decoder.currentRefId,
|
|
207
217
|
op: operation,
|
|
208
|
-
field: field,
|
|
218
|
+
field: field.name,
|
|
209
219
|
value,
|
|
210
220
|
previousValue,
|
|
211
221
|
});
|
|
@@ -251,6 +261,7 @@ export const decodeKeyValueOperation: DecodeOperation = function (
|
|
|
251
261
|
dynamicIndex = ref['getIndex'](index);
|
|
252
262
|
}
|
|
253
263
|
|
|
264
|
+
|
|
254
265
|
const { value, previousValue } = decodeValue(
|
|
255
266
|
decoder,
|
|
256
267
|
operation,
|
|
@@ -303,7 +314,8 @@ export const decodeArray: DecodeOperation = function (
|
|
|
303
314
|
allChanges: DataChange[]
|
|
304
315
|
) {
|
|
305
316
|
// "uncompressed" index + operation (array/map items)
|
|
306
|
-
|
|
317
|
+
let operation = bytes[it.offset++];
|
|
318
|
+
let index: number;
|
|
307
319
|
|
|
308
320
|
if (operation === OPERATION.CLEAR) {
|
|
309
321
|
//
|
|
@@ -315,11 +327,15 @@ export const decodeArray: DecodeOperation = function (
|
|
|
315
327
|
(ref as ArraySchema).clear();
|
|
316
328
|
return;
|
|
317
329
|
|
|
330
|
+
} else if (operation === OPERATION.REVERSE) {
|
|
331
|
+
(ref as ArraySchema).reverse();
|
|
332
|
+
return;
|
|
333
|
+
|
|
318
334
|
} else if (operation === OPERATION.DELETE_BY_REFID) {
|
|
319
335
|
// TODO: refactor here, try to follow same flow as below
|
|
320
336
|
const refId = decode.number(bytes, it);
|
|
321
|
-
const previousValue = decoder
|
|
322
|
-
|
|
337
|
+
const previousValue = decoder.root.refs.get(refId);
|
|
338
|
+
index = ref.findIndex((value) => value === previousValue);
|
|
323
339
|
ref[$deleteByIndex](index);
|
|
324
340
|
allChanges.push({
|
|
325
341
|
ref,
|
|
@@ -330,10 +346,22 @@ export const decodeArray: DecodeOperation = function (
|
|
|
330
346
|
value: undefined,
|
|
331
347
|
previousValue,
|
|
332
348
|
});
|
|
349
|
+
|
|
333
350
|
return;
|
|
351
|
+
|
|
352
|
+
} else if (operation === OPERATION.ADD_BY_REFID) {
|
|
353
|
+
const refId = decode.number(bytes, it);
|
|
354
|
+
const itemByRefId = decoder.root.refs.get(refId);
|
|
355
|
+
|
|
356
|
+
// use existing index, or push new value
|
|
357
|
+
index = (itemByRefId)
|
|
358
|
+
? ref.findIndex((value) => value === itemByRefId)
|
|
359
|
+
: ref.length;
|
|
360
|
+
|
|
361
|
+
} else {
|
|
362
|
+
index = decode.number(bytes, it);
|
|
334
363
|
}
|
|
335
364
|
|
|
336
|
-
const index = decode.number(bytes, it);
|
|
337
365
|
const type = ref[$childType];
|
|
338
366
|
|
|
339
367
|
let dynamicIndex: number | string = index;
|
package/src/decoder/Decoder.ts
CHANGED
|
@@ -1,27 +1,28 @@
|
|
|
1
|
-
import { TypeContext } from "../
|
|
1
|
+
import { TypeContext } from "../types/TypeContext";
|
|
2
2
|
import { $changes, $childType, $decoder, $onDecodeEnd } from "../types/symbols";
|
|
3
3
|
import { Schema } from "../Schema";
|
|
4
4
|
|
|
5
5
|
import * as decode from "../encoding/decode";
|
|
6
6
|
import { OPERATION, SWITCH_TO_STRUCTURE, TYPE_ID } from '../encoding/spec';
|
|
7
|
-
import { Ref } from "../encoder/ChangeTree";
|
|
8
|
-
import { Iterator } from "../encoding/decode";
|
|
7
|
+
import type { Ref } from "../encoder/ChangeTree";
|
|
8
|
+
import type { Iterator } from "../encoding/decode";
|
|
9
9
|
import { ReferenceTracker } from "./ReferenceTracker";
|
|
10
|
-
import { DEFINITION_MISMATCH, DataChange, DecodeOperation } from "./DecodeOperation";
|
|
10
|
+
import { DEFINITION_MISMATCH, type DataChange, type DecodeOperation } from "./DecodeOperation";
|
|
11
11
|
import { Collection } from "../types/HelperTypes";
|
|
12
12
|
|
|
13
13
|
export class Decoder<T extends Schema = any> {
|
|
14
14
|
context: TypeContext;
|
|
15
15
|
|
|
16
16
|
state: T;
|
|
17
|
-
|
|
17
|
+
root: ReferenceTracker;
|
|
18
18
|
|
|
19
19
|
currentRefId: number = 0;
|
|
20
20
|
|
|
21
21
|
triggerChanges?: (allChanges: DataChange[]) => void;
|
|
22
22
|
|
|
23
23
|
constructor(root: T, context?: TypeContext) {
|
|
24
|
-
this.
|
|
24
|
+
this.setState(root);
|
|
25
|
+
|
|
25
26
|
this.context = context || new TypeContext(root.constructor as typeof Schema);
|
|
26
27
|
|
|
27
28
|
// console.log(">>>>>>>>>>>>>>>> Decoder types");
|
|
@@ -30,10 +31,10 @@ export class Decoder<T extends Schema = any> {
|
|
|
30
31
|
// });
|
|
31
32
|
}
|
|
32
33
|
|
|
33
|
-
protected
|
|
34
|
+
protected setState(root: T) {
|
|
34
35
|
this.state = root;
|
|
35
|
-
this
|
|
36
|
-
this
|
|
36
|
+
this.root = new ReferenceTracker();
|
|
37
|
+
this.root.addRef(0, root);
|
|
37
38
|
}
|
|
38
39
|
|
|
39
40
|
decode(
|
|
@@ -43,7 +44,7 @@ export class Decoder<T extends Schema = any> {
|
|
|
43
44
|
) {
|
|
44
45
|
const allChanges: DataChange[] = [];
|
|
45
46
|
|
|
46
|
-
const $root = this
|
|
47
|
+
const $root = this.root;
|
|
47
48
|
const totalBytes = bytes.byteLength;
|
|
48
49
|
|
|
49
50
|
let decoder: DecodeOperation = ref['constructor'][$decoder];
|
|
@@ -66,7 +67,8 @@ export class Decoder<T extends Schema = any> {
|
|
|
66
67
|
if (!nextRef) { throw new Error(`"refId" not found: ${this.currentRefId}`); }
|
|
67
68
|
ref[$onDecodeEnd]?.()
|
|
68
69
|
ref = nextRef;
|
|
69
|
-
|
|
70
|
+
|
|
71
|
+
decoder = ref.constructor[$decoder];
|
|
70
72
|
|
|
71
73
|
continue;
|
|
72
74
|
}
|
|
@@ -146,7 +148,7 @@ export class Decoder<T extends Schema = any> {
|
|
|
146
148
|
});
|
|
147
149
|
|
|
148
150
|
if (needRemoveRef) {
|
|
149
|
-
this
|
|
151
|
+
this.root.removeRef(this.root.refIds.get(value));
|
|
150
152
|
}
|
|
151
153
|
});
|
|
152
154
|
}
|
|
@@ -98,8 +98,9 @@ export class ReferenceTracker {
|
|
|
98
98
|
// Ensure child schema instances have their references removed as well.
|
|
99
99
|
//
|
|
100
100
|
if (Metadata.isValidInstance(ref)) {
|
|
101
|
-
const metadata: Metadata = ref
|
|
102
|
-
for (const
|
|
101
|
+
const metadata: Metadata = ref.constructor[Symbol.metadata];
|
|
102
|
+
for (const index in metadata) {
|
|
103
|
+
const field = metadata[index as any as number].name;
|
|
103
104
|
const childRefId = typeof(ref[field]) === "object" && this.refIds.get(ref[field]);
|
|
104
105
|
if (childRefId) {
|
|
105
106
|
this.removeRef(childRefId);
|