@colyseus/schema 2.0.32 → 3.0.0-alpha.1
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/build/cjs/index.js +3428 -2677
- package/build/cjs/index.js.map +1 -1
- package/build/esm/index.mjs +3324 -2445
- package/build/esm/index.mjs.map +1 -1
- package/build/umd/index.js +3428 -2677
- package/lib/Decoder.d.ts +16 -0
- package/lib/Decoder.js +182 -0
- package/lib/Decoder.js.map +1 -0
- package/lib/Encoder.d.ts +13 -0
- package/lib/Encoder.js +79 -0
- package/lib/Encoder.js.map +1 -0
- package/lib/Metadata.d.ts +36 -0
- package/lib/Metadata.js +91 -0
- package/lib/Metadata.js.map +1 -0
- package/lib/Reflection.d.ts +7 -5
- package/lib/Reflection.js +62 -58
- package/lib/Reflection.js.map +1 -1
- package/lib/Schema.d.ts +39 -51
- package/lib/Schema.js +189 -731
- package/lib/Schema.js.map +1 -1
- package/lib/annotations.d.ts +26 -45
- package/lib/annotations.js +363 -194
- package/lib/annotations.js.map +1 -1
- package/lib/changes/ChangeSet.d.ts +12 -0
- package/lib/changes/ChangeSet.js +35 -0
- package/lib/changes/ChangeSet.js.map +1 -0
- package/lib/changes/DecodeOperation.d.ts +15 -0
- package/lib/changes/DecodeOperation.js +186 -0
- package/lib/changes/DecodeOperation.js.map +1 -0
- package/lib/changes/EncodeOperation.d.ts +18 -0
- package/lib/changes/EncodeOperation.js +130 -0
- package/lib/changes/EncodeOperation.js.map +1 -0
- package/lib/changes/consts.d.ts +14 -0
- package/lib/changes/consts.js +18 -0
- package/lib/changes/consts.js.map +1 -0
- package/lib/decoder/DecodeOperation.d.ts +24 -0
- package/lib/decoder/DecodeOperation.js +256 -0
- package/lib/decoder/DecodeOperation.js.map +1 -0
- package/lib/decoder/Decoder.d.ts +21 -0
- package/lib/decoder/Decoder.js +114 -0
- package/lib/decoder/Decoder.js.map +1 -0
- package/lib/decoder/ReferenceTracker.d.ts +26 -0
- package/lib/decoder/ReferenceTracker.js +131 -0
- package/lib/decoder/ReferenceTracker.js.map +1 -0
- package/lib/decoder/strategy/RawChanges.d.ts +3 -0
- package/lib/decoder/strategy/RawChanges.js +8 -0
- package/lib/decoder/strategy/RawChanges.js.map +1 -0
- package/lib/decoder/strategy/StateCallbacks.d.ts +20 -0
- package/lib/decoder/strategy/StateCallbacks.js +240 -0
- package/lib/decoder/strategy/StateCallbacks.js.map +1 -0
- package/lib/decoding/decode.d.ts +48 -0
- package/lib/decoding/decode.js +267 -0
- package/lib/decoding/decode.js.map +1 -0
- package/lib/ecs.d.ts +11 -0
- package/lib/ecs.js +160 -0
- package/lib/ecs.js.map +1 -0
- package/lib/encoder/ChangeTree.d.ts +72 -0
- package/lib/encoder/ChangeTree.js +384 -0
- package/lib/encoder/ChangeTree.js.map +1 -0
- package/lib/encoder/EncodeOperation.d.ts +25 -0
- package/lib/encoder/EncodeOperation.js +156 -0
- package/lib/encoder/EncodeOperation.js.map +1 -0
- package/lib/encoder/Encoder.d.ts +23 -0
- package/lib/encoder/Encoder.js +192 -0
- package/lib/encoder/Encoder.js.map +1 -0
- package/lib/encoder/StateView.d.ts +21 -0
- package/lib/encoder/StateView.js +196 -0
- package/lib/encoder/StateView.js.map +1 -0
- package/lib/encoding/assert.d.ts +9 -0
- package/lib/encoding/assert.js +47 -0
- package/lib/encoding/assert.js.map +1 -0
- package/lib/encoding/decode.js +1 -1
- package/lib/encoding/decode.js.map +1 -1
- package/lib/encoding/encode.d.ts +19 -16
- package/lib/encoding/encode.js +88 -81
- package/lib/encoding/encode.js.map +1 -1
- package/lib/encoding/spec.d.ts +25 -0
- package/lib/encoding/spec.js +30 -0
- package/lib/encoding/spec.js.map +1 -0
- package/lib/index.d.ts +18 -10
- package/lib/index.js +39 -17
- package/lib/index.js.map +1 -1
- package/lib/symbol.shim.d.ts +6 -0
- package/lib/symbol.shim.js +4 -0
- package/lib/symbol.shim.js.map +1 -0
- package/lib/types/ArraySchema.d.ts +1 -1
- package/lib/types/ArraySchema.js +0 -7
- package/lib/types/ArraySchema.js.map +1 -1
- package/lib/types/HelperTypes.d.ts +10 -2
- package/lib/types/HelperTypes.js.map +1 -1
- package/lib/types/custom/ArraySchema.d.ts +245 -0
- package/lib/types/custom/ArraySchema.js +659 -0
- package/lib/types/custom/ArraySchema.js.map +1 -0
- package/lib/types/custom/CollectionSchema.d.ts +42 -0
- package/lib/types/custom/CollectionSchema.js +165 -0
- package/lib/types/custom/CollectionSchema.js.map +1 -0
- package/lib/types/custom/MapSchema.d.ts +43 -0
- package/lib/types/custom/MapSchema.js +200 -0
- package/lib/types/custom/MapSchema.js.map +1 -0
- package/lib/types/custom/SetSchema.d.ts +39 -0
- package/lib/types/custom/SetSchema.js +177 -0
- package/lib/types/custom/SetSchema.js.map +1 -0
- package/lib/types/registry.d.ts +6 -0
- package/lib/types/registry.js +19 -0
- package/lib/types/registry.js.map +1 -0
- package/lib/types/symbols.d.ts +29 -0
- package/lib/types/symbols.js +33 -0
- package/lib/types/symbols.js.map +1 -0
- package/lib/types/utils.d.ts +0 -8
- package/lib/types/utils.js +1 -33
- package/lib/types/utils.js.map +1 -1
- package/lib/usage.d.ts +1 -0
- package/lib/usage.js +22 -0
- package/lib/usage.js.map +1 -0
- package/lib/utils.d.ts +13 -2
- package/lib/utils.js +36 -15
- package/lib/utils.js.map +1 -1
- package/lib/v3.d.ts +1 -0
- package/lib/v3.js +427 -0
- package/lib/v3.js.map +1 -0
- package/lib/v3_bench.d.ts +1 -0
- package/lib/v3_bench.js +130 -0
- package/lib/v3_bench.js.map +1 -0
- package/lib/v3_experiment.d.ts +1 -0
- package/lib/v3_experiment.js +407 -0
- package/lib/v3_experiment.js.map +1 -0
- package/package.json +5 -5
- package/src/Metadata.ts +135 -0
- package/src/Reflection.ts +75 -66
- package/src/Schema.ts +213 -931
- package/src/annotations.ts +430 -243
- package/src/decoder/DecodeOperation.ts +372 -0
- package/src/decoder/Decoder.ts +155 -0
- package/src/decoder/ReferenceTracker.ts +151 -0
- package/src/decoder/strategy/RawChanges.ts +9 -0
- package/src/decoder/strategy/StateCallbacks.ts +326 -0
- package/src/encoder/ChangeTree.ts +492 -0
- package/src/encoder/EncodeOperation.ts +237 -0
- package/src/encoder/Encoder.ts +246 -0
- package/src/encoder/StateView.ts +229 -0
- package/src/encoding/assert.ts +58 -0
- package/src/encoding/decode.ts +1 -1
- package/src/encoding/encode.ts +91 -82
- package/src/encoding/spec.ts +29 -0
- package/src/index.ts +22 -19
- package/src/symbol.shim.ts +12 -0
- package/src/types/HelperTypes.ts +16 -2
- package/src/types/{ArraySchema.ts → custom/ArraySchema.ts} +342 -248
- package/src/types/{CollectionSchema.ts → custom/CollectionSchema.ts} +56 -46
- package/src/types/{MapSchema.ts → custom/MapSchema.ts} +88 -115
- package/src/types/{SetSchema.ts → custom/SetSchema.ts} +58 -47
- package/src/types/{typeRegistry.ts → registry.ts} +6 -6
- package/src/types/symbols.ts +36 -0
- package/src/types/utils.ts +0 -46
- package/src/utils.ts +50 -21
- package/src/v3_bench.ts +107 -0
- package/src/changes/ChangeTree.ts +0 -295
- package/src/changes/ReferenceTracker.ts +0 -91
- package/src/filters/index.ts +0 -23
- package/src/spec.ts +0 -49
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
import { OPERATION } from "../encoding/spec";
|
|
3
|
+
import { Schema } from "../Schema";
|
|
4
|
+
import type { Ref } from "../encoder/ChangeTree";
|
|
5
|
+
import type { Decoder } from "./Decoder";
|
|
6
|
+
import * as decode from "../encoding/decode";
|
|
7
|
+
export interface DataChange<T = any, F = string> {
|
|
8
|
+
ref: Ref;
|
|
9
|
+
refId: number;
|
|
10
|
+
op: OPERATION;
|
|
11
|
+
field: F;
|
|
12
|
+
dynamicIndex?: number | string;
|
|
13
|
+
value: T;
|
|
14
|
+
previousValue: T;
|
|
15
|
+
}
|
|
16
|
+
export declare const DEFINITION_MISMATCH = -1;
|
|
17
|
+
export type DecodeOperation<T extends Schema = any> = (decoder: Decoder<T>, bytes: Buffer, it: decode.Iterator, ref: Ref, allChanges: DataChange[]) => number | void;
|
|
18
|
+
export declare function decodeValue(decoder: Decoder, operation: OPERATION, ref: Ref, index: number, type: any, bytes: Buffer, it: decode.Iterator, allChanges: DataChange[]): {
|
|
19
|
+
value: any;
|
|
20
|
+
previousValue: any;
|
|
21
|
+
};
|
|
22
|
+
export declare const decodeSchemaOperation: DecodeOperation;
|
|
23
|
+
export declare const decodeKeyValueOperation: DecodeOperation;
|
|
24
|
+
export declare const decodeArray: DecodeOperation;
|
|
@@ -0,0 +1,256 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.decodeArray = exports.decodeKeyValueOperation = exports.decodeSchemaOperation = exports.decodeValue = exports.DEFINITION_MISMATCH = void 0;
|
|
4
|
+
const spec_1 = require("../encoding/spec");
|
|
5
|
+
const Schema_1 = require("../Schema");
|
|
6
|
+
const decode = require("../encoding/decode");
|
|
7
|
+
const symbols_1 = require("../types/symbols");
|
|
8
|
+
const registry_1 = require("../types/registry");
|
|
9
|
+
exports.DEFINITION_MISMATCH = -1;
|
|
10
|
+
function decodeValue(decoder, operation, ref, index, type, bytes, it, allChanges) {
|
|
11
|
+
const $root = decoder.$root;
|
|
12
|
+
const previousValue = ref[symbols_1.$getByIndex](index);
|
|
13
|
+
let value;
|
|
14
|
+
if ((operation & spec_1.OPERATION.DELETE) === spec_1.OPERATION.DELETE) {
|
|
15
|
+
// Flag `refId` for garbage collection.
|
|
16
|
+
const previousRefId = $root.refIds.get(previousValue);
|
|
17
|
+
if (previousRefId !== undefined) {
|
|
18
|
+
$root.removeRef(previousRefId);
|
|
19
|
+
}
|
|
20
|
+
//
|
|
21
|
+
// Delete operations
|
|
22
|
+
//
|
|
23
|
+
if (operation !== spec_1.OPERATION.DELETE_AND_ADD) {
|
|
24
|
+
ref[symbols_1.$deleteByIndex](index);
|
|
25
|
+
// //
|
|
26
|
+
// // FIXME: is this in the correct place?
|
|
27
|
+
// // (This is sounding like a workaround just for ArraySchema, see
|
|
28
|
+
// // "should splice and move" test on ArraySchema.test.ts)
|
|
29
|
+
// //
|
|
30
|
+
// allChanges.push({
|
|
31
|
+
// ref,
|
|
32
|
+
// refId: decoder.currentRefId,
|
|
33
|
+
// op: OPERATION.DELETE,
|
|
34
|
+
// field: index as unknown as string,
|
|
35
|
+
// value: undefined,
|
|
36
|
+
// previousValue,
|
|
37
|
+
// });
|
|
38
|
+
}
|
|
39
|
+
value = null;
|
|
40
|
+
}
|
|
41
|
+
if (operation === spec_1.OPERATION.DELETE) {
|
|
42
|
+
//
|
|
43
|
+
// Don't do anything
|
|
44
|
+
//
|
|
45
|
+
}
|
|
46
|
+
else if (Schema_1.Schema.is(type)) {
|
|
47
|
+
const refId = decode.number(bytes, it);
|
|
48
|
+
value = $root.refs.get(refId);
|
|
49
|
+
if (previousValue) {
|
|
50
|
+
const previousRefId = $root.refIds.get(previousValue);
|
|
51
|
+
if (previousRefId &&
|
|
52
|
+
refId !== previousRefId &&
|
|
53
|
+
// FIXME: we may need to check for REPLACE operation as well
|
|
54
|
+
((operation & spec_1.OPERATION.DELETE) === spec_1.OPERATION.DELETE)) {
|
|
55
|
+
$root.removeRef(previousRefId);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
if ((operation & spec_1.OPERATION.ADD) === spec_1.OPERATION.ADD) {
|
|
59
|
+
const childType = decoder.getInstanceType(bytes, it, type);
|
|
60
|
+
if (!value) {
|
|
61
|
+
value = decoder.createInstanceOfType(childType);
|
|
62
|
+
}
|
|
63
|
+
$root.addRef(refId, value, (value !== previousValue));
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
else if (typeof (type) === "string") {
|
|
67
|
+
//
|
|
68
|
+
// primitive value (number, string, boolean, etc)
|
|
69
|
+
//
|
|
70
|
+
value = decode[type](bytes, it);
|
|
71
|
+
}
|
|
72
|
+
else {
|
|
73
|
+
const typeDef = (0, registry_1.getType)(Object.keys(type)[0]);
|
|
74
|
+
const refId = decode.number(bytes, it);
|
|
75
|
+
const valueRef = ($root.refs.has(refId))
|
|
76
|
+
? previousValue || $root.refs.get(refId)
|
|
77
|
+
: new typeDef.constructor();
|
|
78
|
+
value = valueRef.clone(true);
|
|
79
|
+
value[symbols_1.$childType] = Object.values(type)[0]; // cache childType for ArraySchema and MapSchema
|
|
80
|
+
if (previousValue) {
|
|
81
|
+
let previousRefId = $root.refIds.get(previousValue);
|
|
82
|
+
if (previousRefId !== undefined && refId !== previousRefId) {
|
|
83
|
+
$root.removeRef(previousRefId);
|
|
84
|
+
//
|
|
85
|
+
// enqueue onRemove if structure has been replaced.
|
|
86
|
+
//
|
|
87
|
+
const entries = previousValue.entries();
|
|
88
|
+
let iter;
|
|
89
|
+
while ((iter = entries.next()) && !iter.done) {
|
|
90
|
+
const [key, value] = iter.value;
|
|
91
|
+
// if value is a schema, remove its reference
|
|
92
|
+
// FIXME: not sure if this is necessary, add more tests to confirm
|
|
93
|
+
if (typeof (value) === "object") {
|
|
94
|
+
previousRefId = $root.refIds.get(value);
|
|
95
|
+
$root.removeRef(previousRefId);
|
|
96
|
+
}
|
|
97
|
+
allChanges.push({
|
|
98
|
+
ref: previousValue,
|
|
99
|
+
refId: previousRefId,
|
|
100
|
+
op: spec_1.OPERATION.DELETE,
|
|
101
|
+
field: key,
|
|
102
|
+
value: undefined,
|
|
103
|
+
previousValue: value,
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
$root.addRef(refId, value, (valueRef !== previousValue));
|
|
109
|
+
}
|
|
110
|
+
return { value, previousValue };
|
|
111
|
+
}
|
|
112
|
+
exports.decodeValue = decodeValue;
|
|
113
|
+
const decodeSchemaOperation = function (decoder, bytes, it, ref, allChanges) {
|
|
114
|
+
const first_byte = bytes[it.offset++];
|
|
115
|
+
const metadata = ref['constructor'][Symbol.metadata];
|
|
116
|
+
// "compressed" index + operation
|
|
117
|
+
const operation = (first_byte >> 6) << 6;
|
|
118
|
+
const index = first_byte % (operation || 255);
|
|
119
|
+
// skip early if field is not defined
|
|
120
|
+
const field = metadata[index];
|
|
121
|
+
if (field === undefined) {
|
|
122
|
+
return exports.DEFINITION_MISMATCH;
|
|
123
|
+
}
|
|
124
|
+
const { value, previousValue } = decodeValue(decoder, operation, ref, index, metadata[field].type, bytes, it, allChanges);
|
|
125
|
+
if (value !== null && value !== undefined) {
|
|
126
|
+
ref[field] = value;
|
|
127
|
+
}
|
|
128
|
+
// add change
|
|
129
|
+
if (previousValue !== value) {
|
|
130
|
+
allChanges.push({
|
|
131
|
+
ref,
|
|
132
|
+
refId: decoder.currentRefId,
|
|
133
|
+
op: operation,
|
|
134
|
+
field: field,
|
|
135
|
+
value,
|
|
136
|
+
previousValue,
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
};
|
|
140
|
+
exports.decodeSchemaOperation = decodeSchemaOperation;
|
|
141
|
+
const decodeKeyValueOperation = function (decoder, bytes, it, ref, allChanges) {
|
|
142
|
+
// "uncompressed" index + operation (array/map items)
|
|
143
|
+
const operation = bytes[it.offset++];
|
|
144
|
+
if (operation === spec_1.OPERATION.CLEAR) {
|
|
145
|
+
//
|
|
146
|
+
// When decoding:
|
|
147
|
+
// - enqueue items for DELETE callback.
|
|
148
|
+
// - flag child items for garbage collection.
|
|
149
|
+
//
|
|
150
|
+
decoder.removeChildRefs(ref, allChanges);
|
|
151
|
+
ref.clear();
|
|
152
|
+
return;
|
|
153
|
+
}
|
|
154
|
+
const index = decode.number(bytes, it);
|
|
155
|
+
const type = ref[symbols_1.$childType];
|
|
156
|
+
let dynamicIndex;
|
|
157
|
+
if ((operation & spec_1.OPERATION.ADD) === spec_1.OPERATION.ADD) { // ADD or DELETE_AND_ADD
|
|
158
|
+
if (typeof (ref['set']) === "function") {
|
|
159
|
+
dynamicIndex = decode.string(bytes, it); // MapSchema
|
|
160
|
+
ref['setIndex'](index, dynamicIndex);
|
|
161
|
+
}
|
|
162
|
+
else {
|
|
163
|
+
dynamicIndex = index; // ArraySchema
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
else {
|
|
167
|
+
// get dynamic index from "ref"
|
|
168
|
+
dynamicIndex = ref['getIndex'](index);
|
|
169
|
+
}
|
|
170
|
+
const { value, previousValue } = decodeValue(decoder, operation, ref, index, type, bytes, it, allChanges);
|
|
171
|
+
if (value !== null && value !== undefined) {
|
|
172
|
+
if (typeof (ref['set']) === "function") {
|
|
173
|
+
// MapSchema
|
|
174
|
+
ref['$items'].set(dynamicIndex, value);
|
|
175
|
+
}
|
|
176
|
+
else if (typeof (ref['$setAt']) === "function") {
|
|
177
|
+
// ArraySchema
|
|
178
|
+
ref['$setAt'](index, value, operation);
|
|
179
|
+
}
|
|
180
|
+
else if (typeof (ref['add']) === "function") {
|
|
181
|
+
// CollectionSchema && SetSchema
|
|
182
|
+
const index = ref.add(value);
|
|
183
|
+
if (typeof (index) === "number") {
|
|
184
|
+
ref['setIndex'](index, index);
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
// add change
|
|
189
|
+
if (previousValue !== value) {
|
|
190
|
+
allChanges.push({
|
|
191
|
+
ref,
|
|
192
|
+
refId: decoder.currentRefId,
|
|
193
|
+
op: operation,
|
|
194
|
+
field: "", // FIXME: remove this
|
|
195
|
+
dynamicIndex,
|
|
196
|
+
value,
|
|
197
|
+
previousValue,
|
|
198
|
+
});
|
|
199
|
+
}
|
|
200
|
+
};
|
|
201
|
+
exports.decodeKeyValueOperation = decodeKeyValueOperation;
|
|
202
|
+
const decodeArray = function (decoder, bytes, it, ref, allChanges) {
|
|
203
|
+
// "uncompressed" index + operation (array/map items)
|
|
204
|
+
const operation = bytes[it.offset++];
|
|
205
|
+
if (operation === spec_1.OPERATION.CLEAR) {
|
|
206
|
+
//
|
|
207
|
+
// When decoding:
|
|
208
|
+
// - enqueue items for DELETE callback.
|
|
209
|
+
// - flag child items for garbage collection.
|
|
210
|
+
//
|
|
211
|
+
decoder.removeChildRefs(ref, allChanges);
|
|
212
|
+
ref.clear();
|
|
213
|
+
return;
|
|
214
|
+
}
|
|
215
|
+
else if (operation === spec_1.OPERATION.DELETE_BY_REFID) {
|
|
216
|
+
// TODO: refactor here, try to follow same flow as below
|
|
217
|
+
const refId = decode.number(bytes, it);
|
|
218
|
+
const previousValue = decoder.$root.refs.get(refId);
|
|
219
|
+
const index = ref.findIndex((value) => value === previousValue);
|
|
220
|
+
ref[symbols_1.$deleteByIndex](index);
|
|
221
|
+
allChanges.push({
|
|
222
|
+
ref,
|
|
223
|
+
refId: decoder.currentRefId,
|
|
224
|
+
op: spec_1.OPERATION.DELETE,
|
|
225
|
+
field: "", // FIXME: remove this
|
|
226
|
+
dynamicIndex: index,
|
|
227
|
+
value: undefined,
|
|
228
|
+
previousValue,
|
|
229
|
+
});
|
|
230
|
+
return;
|
|
231
|
+
}
|
|
232
|
+
const index = decode.number(bytes, it);
|
|
233
|
+
const type = ref[symbols_1.$childType];
|
|
234
|
+
let dynamicIndex = index;
|
|
235
|
+
const { value, previousValue } = decodeValue(decoder, operation, ref, index, type, bytes, it, allChanges);
|
|
236
|
+
if (value !== null && value !== undefined &&
|
|
237
|
+
value !== previousValue // avoid setting same value twice (if index === 0 it will result in a "unshift" for ArraySchema)
|
|
238
|
+
) {
|
|
239
|
+
// ArraySchema
|
|
240
|
+
ref['$setAt'](index, value, operation);
|
|
241
|
+
}
|
|
242
|
+
// add change
|
|
243
|
+
if (previousValue !== value) {
|
|
244
|
+
allChanges.push({
|
|
245
|
+
ref,
|
|
246
|
+
refId: decoder.currentRefId,
|
|
247
|
+
op: operation,
|
|
248
|
+
field: "", // FIXME: remove this
|
|
249
|
+
dynamicIndex,
|
|
250
|
+
value,
|
|
251
|
+
previousValue,
|
|
252
|
+
});
|
|
253
|
+
}
|
|
254
|
+
};
|
|
255
|
+
exports.decodeArray = decodeArray;
|
|
256
|
+
//# sourceMappingURL=DecodeOperation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DecodeOperation.js","sourceRoot":"","sources":["../../src/decoder/DecodeOperation.ts"],"names":[],"mappings":"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","sourcesContent":["import { OPERATION } from \"../encoding/spec\";\nimport { Metadata } from \"../Metadata\";\nimport { Schema } from \"../Schema\";\nimport type { Ref } from \"../encoder/ChangeTree\";\nimport type { Decoder } from \"./Decoder\";\nimport * as decode from \"../encoding/decode\";\nimport { $changes, $childType, $deleteByIndex, $getByIndex } from \"../types/symbols\";\n\nimport type { MapSchema } from \"../types/custom/MapSchema\";\nimport type { ArraySchema } from \"../types/custom/ArraySchema\";\nimport type { CollectionSchema } from \"../types/custom/CollectionSchema\";\n\nimport { getType } from \"../types/registry\";\nimport { Collection } from \"../types/HelperTypes\";\n\nexport interface DataChange<T = any, F = string> {\n ref: Ref,\n refId: number,\n op: OPERATION,\n field: F;\n dynamicIndex?: number | string;\n value: T;\n previousValue: T;\n}\n\nexport const DEFINITION_MISMATCH = -1;\n\nexport type DecodeOperation<T extends Schema = any> = (\n decoder: Decoder<T>,\n bytes: Buffer,\n it: decode.Iterator,\n ref: Ref,\n allChanges: DataChange[],\n) => number | void;\n\nexport function decodeValue(\n decoder: Decoder,\n operation: OPERATION,\n ref: Ref,\n index: number,\n type: any,\n bytes: Buffer,\n it: decode.Iterator,\n allChanges: DataChange[],\n) {\n const $root = decoder.$root;\n const previousValue = ref[$getByIndex](index);\n\n let value: any;\n\n if ((operation & OPERATION.DELETE) === OPERATION.DELETE)\n {\n // Flag `refId` for garbage collection.\n const previousRefId = $root.refIds.get(previousValue);\n if (previousRefId !== undefined) { $root.removeRef(previousRefId); }\n\n //\n // Delete operations\n //\n if (operation !== OPERATION.DELETE_AND_ADD) {\n ref[$deleteByIndex](index);\n\n // //\n // // FIXME: is this in the correct place?\n // // (This is sounding like a workaround just for ArraySchema, see\n // // \"should splice and move\" test on ArraySchema.test.ts)\n // //\n // allChanges.push({\n // ref,\n // refId: decoder.currentRefId,\n // op: OPERATION.DELETE,\n // field: index as unknown as string,\n // value: undefined,\n // previousValue,\n // });\n }\n\n value = null;\n }\n\n if (operation === OPERATION.DELETE) {\n //\n // Don't do anything\n //\n\n } else if (Schema.is(type)) {\n const refId = decode.number(bytes, it);\n value = $root.refs.get(refId);\n\n if (previousValue) {\n const previousRefId = $root.refIds.get(previousValue);\n if (\n previousRefId &&\n refId !== previousRefId &&\n // FIXME: we may need to check for REPLACE operation as well\n ((operation & OPERATION.DELETE) === OPERATION.DELETE)\n ) {\n $root.removeRef(previousRefId);\n }\n }\n\n if ((operation & OPERATION.ADD) === OPERATION.ADD) {\n const childType = decoder.getInstanceType(bytes, it, type);\n if (!value) {\n value = decoder.createInstanceOfType(childType);\n }\n\n $root.addRef(refId, value, (value !== previousValue));\n }\n\n\n } else if (typeof(type) === \"string\") {\n //\n // primitive value (number, string, boolean, etc)\n //\n value = decode[type as string](bytes, it);\n\n } else {\n const typeDef = getType(Object.keys(type)[0]);\n const refId = decode.number(bytes, it);\n\n const valueRef: Ref = ($root.refs.has(refId))\n ? previousValue || $root.refs.get(refId)\n : new typeDef.constructor();\n\n value = valueRef.clone(true);\n value[$childType] = Object.values(type)[0]; // cache childType for ArraySchema and MapSchema\n\n if (previousValue) {\n let previousRefId = $root.refIds.get(previousValue);\n\n if (previousRefId !== undefined && refId !== previousRefId) {\n $root.removeRef(previousRefId);\n\n //\n // enqueue onRemove if structure has been replaced.\n //\n const entries: IterableIterator<[any, any]> = previousValue.entries();\n let iter: IteratorResult<[any, any]>;\n while ((iter = entries.next()) && !iter.done) {\n const [key, value] = iter.value;\n\n // if value is a schema, remove its reference\n // FIXME: not sure if this is necessary, add more tests to confirm\n if (typeof(value) === \"object\") {\n previousRefId = $root.refIds.get(value);\n $root.removeRef(previousRefId);\n }\n\n allChanges.push({\n ref: previousValue,\n refId: previousRefId,\n op: OPERATION.DELETE,\n field: key,\n value: undefined,\n previousValue: value,\n });\n }\n\n }\n }\n\n $root.addRef(refId, value, (valueRef !== previousValue));\n }\n\n return { value, previousValue };\n}\n\nexport const decodeSchemaOperation: DecodeOperation = function (\n decoder: Decoder<any>,\n bytes: Buffer,\n it: decode.Iterator,\n ref: Ref,\n allChanges: DataChange[],\n) {\n const first_byte = bytes[it.offset++];\n const metadata: Metadata = ref['constructor'][Symbol.metadata];\n\n // \"compressed\" index + operation\n const operation = (first_byte >> 6) << 6\n const index = first_byte % (operation || 255);\n\n // skip early if field is not defined\n const field = metadata[index];\n if (field === undefined) { return DEFINITION_MISMATCH; }\n\n const { value, previousValue } = decodeValue(\n decoder,\n operation,\n ref,\n index,\n metadata[field].type,\n bytes,\n it,\n allChanges,\n );\n\n if (value !== null && value !== undefined) {\n ref[field] = value;\n }\n\n // add change\n if (previousValue !== value) {\n allChanges.push({\n ref,\n refId: decoder.currentRefId,\n op: operation,\n field: field,\n value,\n previousValue,\n });\n }\n}\n\nexport const decodeKeyValueOperation: DecodeOperation = function (\n decoder: Decoder<any>,\n bytes: Buffer,\n it: decode.Iterator,\n ref: Ref,\n allChanges: DataChange[]\n) {\n // \"uncompressed\" index + operation (array/map items)\n const operation = bytes[it.offset++];\n\n if (operation === OPERATION.CLEAR) {\n //\n // When decoding:\n // - enqueue items for DELETE callback.\n // - flag child items for garbage collection.\n //\n decoder.removeChildRefs(ref as unknown as Collection, allChanges);\n\n (ref as any).clear();\n return;\n }\n\n const index = decode.number(bytes, it);\n const type = ref[$childType];\n\n let dynamicIndex: number | string;\n\n if ((operation & OPERATION.ADD) === OPERATION.ADD) { // ADD or DELETE_AND_ADD\n if (typeof(ref['set']) === \"function\") {\n dynamicIndex = decode.string(bytes, it); // MapSchema\n ref['setIndex'](index, dynamicIndex);\n } else {\n dynamicIndex = index; // ArraySchema\n }\n } else {\n // get dynamic index from \"ref\"\n dynamicIndex = ref['getIndex'](index);\n }\n\n const { value, previousValue } = decodeValue(\n decoder,\n operation,\n ref,\n index,\n type,\n bytes,\n it,\n allChanges,\n );\n\n if (value !== null && value !== undefined) {\n if (typeof(ref['set']) === \"function\") {\n // MapSchema\n (ref as MapSchema)['$items'].set(dynamicIndex as string, value);\n\n } else if (typeof(ref['$setAt']) === \"function\") {\n // ArraySchema\n (ref as ArraySchema)['$setAt'](index, value, operation);\n\n } else if (typeof(ref['add']) === \"function\") {\n // CollectionSchema && SetSchema\n const index = (ref as CollectionSchema).add(value);\n\n if (typeof(index) === \"number\") {\n ref['setIndex'](index, index);\n }\n }\n }\n\n // add change\n if (previousValue !== value) {\n allChanges.push({\n ref,\n refId: decoder.currentRefId,\n op: operation,\n field: \"\", // FIXME: remove this\n dynamicIndex,\n value,\n previousValue,\n });\n }\n}\n\nexport const decodeArray: DecodeOperation = function (\n decoder: Decoder<any>,\n bytes: Buffer,\n it: decode.Iterator,\n ref: ArraySchema,\n allChanges: DataChange[]\n) {\n // \"uncompressed\" index + operation (array/map items)\n const operation = bytes[it.offset++];\n\n if (operation === OPERATION.CLEAR) {\n //\n // When decoding:\n // - enqueue items for DELETE callback.\n // - flag child items for garbage collection.\n //\n decoder.removeChildRefs(ref as unknown as Collection, allChanges);\n (ref as ArraySchema).clear();\n return;\n\n } else if (operation === OPERATION.DELETE_BY_REFID) {\n // TODO: refactor here, try to follow same flow as below\n const refId = decode.number(bytes, it);\n const previousValue = decoder.$root.refs.get(refId);\n const index = ref.findIndex((value) => value === previousValue);\n ref[$deleteByIndex](index);\n allChanges.push({\n ref,\n refId: decoder.currentRefId,\n op: OPERATION.DELETE,\n field: \"\", // FIXME: remove this\n dynamicIndex: index,\n value: undefined,\n previousValue,\n });\n return;\n }\n\n const index = decode.number(bytes, it);\n const type = ref[$childType];\n\n let dynamicIndex: number | string = index;\n\n const { value, previousValue } = decodeValue(\n decoder,\n operation,\n ref,\n index,\n type,\n bytes,\n it,\n allChanges,\n );\n\n if (\n value !== null && value !== undefined &&\n value !== previousValue // avoid setting same value twice (if index === 0 it will result in a \"unshift\" for ArraySchema)\n ) {\n // ArraySchema\n (ref as ArraySchema)['$setAt'](index, value, operation);\n }\n\n // add change\n if (previousValue !== value) {\n allChanges.push({\n ref,\n refId: decoder.currentRefId,\n op: operation,\n field: \"\", // FIXME: remove this\n dynamicIndex,\n value,\n previousValue,\n });\n }\n}"]}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/// <reference types="node" />
|
|
2
|
+
import { TypeContext } from "../annotations";
|
|
3
|
+
import { Schema } from "../Schema";
|
|
4
|
+
import { Ref } from "../encoder/ChangeTree";
|
|
5
|
+
import { Iterator } from "../encoding/decode";
|
|
6
|
+
import { ReferenceTracker } from "./ReferenceTracker";
|
|
7
|
+
import { DataChange } from "./DecodeOperation";
|
|
8
|
+
import { Collection } from "../types/HelperTypes";
|
|
9
|
+
export declare class Decoder<T extends Schema = any> {
|
|
10
|
+
context: TypeContext;
|
|
11
|
+
state: T;
|
|
12
|
+
$root: ReferenceTracker;
|
|
13
|
+
currentRefId: number;
|
|
14
|
+
triggerChanges?: (allChanges: DataChange[]) => void;
|
|
15
|
+
constructor(root: T, context?: TypeContext);
|
|
16
|
+
protected setRoot(root: T): void;
|
|
17
|
+
decode(bytes: Buffer, it?: Iterator, ref?: Ref): DataChange<any, string>[];
|
|
18
|
+
getInstanceType(bytes: Buffer, it: Iterator, defaultType: typeof Schema): typeof Schema;
|
|
19
|
+
createInstanceOfType(type: typeof Schema): Schema;
|
|
20
|
+
removeChildRefs(ref: Collection, allChanges: DataChange[]): void;
|
|
21
|
+
}
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Decoder = void 0;
|
|
4
|
+
const annotations_1 = require("../annotations");
|
|
5
|
+
const symbols_1 = require("../types/symbols");
|
|
6
|
+
const decode = require("../encoding/decode");
|
|
7
|
+
const spec_1 = require("../encoding/spec");
|
|
8
|
+
const ReferenceTracker_1 = require("./ReferenceTracker");
|
|
9
|
+
const DecodeOperation_1 = require("./DecodeOperation");
|
|
10
|
+
class Decoder {
|
|
11
|
+
constructor(root, context) {
|
|
12
|
+
this.currentRefId = 0;
|
|
13
|
+
this.setRoot(root);
|
|
14
|
+
this.context = context || new annotations_1.TypeContext(root.constructor);
|
|
15
|
+
// console.log(">>>>>>>>>>>>>>>> Decoder types");
|
|
16
|
+
// this.context.schemas.forEach((id, schema) => {
|
|
17
|
+
// console.log("type:", id, schema.name, Object.keys(schema[Symbol.metadata]));
|
|
18
|
+
// });
|
|
19
|
+
}
|
|
20
|
+
setRoot(root) {
|
|
21
|
+
this.state = root;
|
|
22
|
+
this.$root = new ReferenceTracker_1.ReferenceTracker();
|
|
23
|
+
this.$root.addRef(0, root);
|
|
24
|
+
}
|
|
25
|
+
decode(bytes, it = { offset: 0 }, ref = this.state) {
|
|
26
|
+
const allChanges = [];
|
|
27
|
+
const $root = this.$root;
|
|
28
|
+
const totalBytes = bytes.byteLength;
|
|
29
|
+
let decoder = ref['constructor'][symbols_1.$decoder];
|
|
30
|
+
this.currentRefId = 0;
|
|
31
|
+
while (it.offset < totalBytes) {
|
|
32
|
+
//
|
|
33
|
+
// Peek ahead, check if it's a switch to a different structure
|
|
34
|
+
//
|
|
35
|
+
if (bytes[it.offset] == spec_1.SWITCH_TO_STRUCTURE) {
|
|
36
|
+
it.offset++;
|
|
37
|
+
this.currentRefId = decode.number(bytes, it);
|
|
38
|
+
const nextRef = $root.refs.get(this.currentRefId);
|
|
39
|
+
//
|
|
40
|
+
// Trying to access a reference that haven't been decoded yet.
|
|
41
|
+
//
|
|
42
|
+
if (!nextRef) {
|
|
43
|
+
throw new Error(`"refId" not found: ${this.currentRefId}`);
|
|
44
|
+
}
|
|
45
|
+
ref[symbols_1.$onDecodeEnd]?.();
|
|
46
|
+
ref = nextRef;
|
|
47
|
+
decoder = ref['constructor'][symbols_1.$decoder];
|
|
48
|
+
continue;
|
|
49
|
+
}
|
|
50
|
+
const result = decoder(this, bytes, it, ref, allChanges);
|
|
51
|
+
if (result === DecodeOperation_1.DEFINITION_MISMATCH) {
|
|
52
|
+
console.warn("@colyseus/schema: definition mismatch");
|
|
53
|
+
//
|
|
54
|
+
// keep skipping next bytes until reaches a known structure
|
|
55
|
+
// by local decoder.
|
|
56
|
+
//
|
|
57
|
+
const nextIterator = { offset: it.offset };
|
|
58
|
+
while (it.offset < totalBytes) {
|
|
59
|
+
if (decode.switchStructureCheck(bytes, it)) {
|
|
60
|
+
nextIterator.offset = it.offset + 1;
|
|
61
|
+
if ($root.refs.has(decode.number(bytes, nextIterator))) {
|
|
62
|
+
break;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
it.offset++;
|
|
66
|
+
}
|
|
67
|
+
continue;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
// FIXME: DRY with SWITCH_TO_STRUCTURE block.
|
|
71
|
+
ref[symbols_1.$onDecodeEnd]?.();
|
|
72
|
+
// trigger changes
|
|
73
|
+
this.triggerChanges?.(allChanges);
|
|
74
|
+
// drop references of unused schemas
|
|
75
|
+
$root.garbageCollectDeletedRefs();
|
|
76
|
+
return allChanges;
|
|
77
|
+
}
|
|
78
|
+
getInstanceType(bytes, it, defaultType) {
|
|
79
|
+
let type;
|
|
80
|
+
if (bytes[it.offset] === spec_1.TYPE_ID) {
|
|
81
|
+
it.offset++;
|
|
82
|
+
const type_id = decode.number(bytes, it);
|
|
83
|
+
type = this.context.get(type_id);
|
|
84
|
+
}
|
|
85
|
+
return type || defaultType;
|
|
86
|
+
}
|
|
87
|
+
createInstanceOfType(type) {
|
|
88
|
+
// let instance: Schema = new (type as any)();
|
|
89
|
+
// // assign root on $changes
|
|
90
|
+
// instance[$changes].root = this.root[$changes].root;
|
|
91
|
+
// return instance;
|
|
92
|
+
return new type();
|
|
93
|
+
}
|
|
94
|
+
removeChildRefs(ref, allChanges) {
|
|
95
|
+
const changeTree = ref[symbols_1.$changes];
|
|
96
|
+
const needRemoveRef = typeof (ref[symbols_1.$childType]) !== "string";
|
|
97
|
+
const refId = changeTree.refId;
|
|
98
|
+
ref.forEach((value, key) => {
|
|
99
|
+
allChanges.push({
|
|
100
|
+
ref: value,
|
|
101
|
+
refId,
|
|
102
|
+
op: spec_1.OPERATION.DELETE,
|
|
103
|
+
field: key,
|
|
104
|
+
value: undefined,
|
|
105
|
+
previousValue: value
|
|
106
|
+
});
|
|
107
|
+
if (needRemoveRef) {
|
|
108
|
+
this.$root.removeRef(this.$root.refIds.get(value));
|
|
109
|
+
}
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
exports.Decoder = Decoder;
|
|
114
|
+
//# sourceMappingURL=Decoder.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Decoder.js","sourceRoot":"","sources":["../../src/decoder/Decoder.ts"],"names":[],"mappings":"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","sourcesContent":["import { TypeContext } from \"../annotations\";\nimport { $changes, $childType, $decoder, $onDecodeEnd } from \"../types/symbols\";\nimport { Schema } from \"../Schema\";\n\nimport * as decode from \"../encoding/decode\";\nimport { OPERATION, SWITCH_TO_STRUCTURE, TYPE_ID } from '../encoding/spec';\nimport { Ref } from \"../encoder/ChangeTree\";\nimport { Iterator } from \"../encoding/decode\";\nimport { ReferenceTracker } from \"./ReferenceTracker\";\nimport { DEFINITION_MISMATCH, DataChange, DecodeOperation } from \"./DecodeOperation\";\nimport { Collection } from \"../types/HelperTypes\";\n\nexport class Decoder<T extends Schema = any> {\n context: TypeContext;\n\n state: T;\n $root: ReferenceTracker;\n\n currentRefId: number = 0;\n\n triggerChanges?: (allChanges: DataChange[]) => void;\n\n constructor(root: T, context?: TypeContext) {\n this.setRoot(root);\n this.context = context || new TypeContext(root.constructor as typeof Schema);\n\n // console.log(\">>>>>>>>>>>>>>>> Decoder types\");\n // this.context.schemas.forEach((id, schema) => {\n // console.log(\"type:\", id, schema.name, Object.keys(schema[Symbol.metadata]));\n // });\n }\n\n protected setRoot(root: T) {\n this.state = root;\n this.$root = new ReferenceTracker();\n this.$root.addRef(0, root);\n }\n\n decode(\n bytes: Buffer,\n it: Iterator = { offset: 0 },\n ref: Ref = this.state,\n ) {\n const allChanges: DataChange[] = [];\n\n const $root = this.$root;\n const totalBytes = bytes.byteLength;\n\n let decoder: DecodeOperation = ref['constructor'][$decoder];\n\n this.currentRefId = 0;\n\n while (it.offset < totalBytes) {\n //\n // Peek ahead, check if it's a switch to a different structure\n //\n if (bytes[it.offset] == SWITCH_TO_STRUCTURE) {\n it.offset++;\n\n this.currentRefId = decode.number(bytes, it);\n const nextRef = $root.refs.get(this.currentRefId) as Schema;\n\n //\n // Trying to access a reference that haven't been decoded yet.\n //\n if (!nextRef) { throw new Error(`\"refId\" not found: ${this.currentRefId}`); }\n ref[$onDecodeEnd]?.()\n ref = nextRef;\n decoder = ref['constructor'][$decoder];\n\n continue;\n }\n\n const result = decoder(this, bytes, it, ref, allChanges);\n\n if (result === DEFINITION_MISMATCH) {\n console.warn(\"@colyseus/schema: definition mismatch\");\n\n //\n // keep skipping next bytes until reaches a known structure\n // by local decoder.\n //\n const nextIterator: decode.Iterator = { offset: it.offset };\n while (it.offset < totalBytes) {\n if (decode.switchStructureCheck(bytes, it)) {\n nextIterator.offset = it.offset + 1;\n if ($root.refs.has(decode.number(bytes, nextIterator))) {\n break;\n }\n }\n\n it.offset++;\n }\n continue;\n }\n }\n\n // FIXME: DRY with SWITCH_TO_STRUCTURE block.\n ref[$onDecodeEnd]?.()\n\n // trigger changes\n this.triggerChanges?.(allChanges);\n\n // drop references of unused schemas\n $root.garbageCollectDeletedRefs();\n\n return allChanges;\n }\n\n getInstanceType(bytes: Buffer, it: Iterator, defaultType: typeof Schema): typeof Schema {\n let type: typeof Schema;\n\n if (bytes[it.offset] === TYPE_ID) {\n it.offset++;\n const type_id = decode.number(bytes, it);\n type = this.context.get(type_id);\n }\n\n return type || defaultType;\n }\n\n createInstanceOfType (type: typeof Schema): Schema {\n // let instance: Schema = new (type as any)();\n\n // // assign root on $changes\n // instance[$changes].root = this.root[$changes].root;\n\n // return instance;\n return new (type as any)();\n }\n\n removeChildRefs(ref: Collection, allChanges: DataChange[]) {\n const changeTree = ref[$changes];\n\n const needRemoveRef = typeof (ref[$childType]) !== \"string\";\n const refId = changeTree.refId;\n\n ref.forEach((value: any, key: any) => {\n allChanges.push({\n ref: value,\n refId,\n op: OPERATION.DELETE,\n field: key,\n value: undefined,\n previousValue: value\n });\n\n if (needRemoveRef) {\n this.$root.removeRef(this.$root.refIds.get(value));\n }\n });\n }\n\n}\n\n"]}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { Ref } from "../encoder/ChangeTree";
|
|
2
|
+
/**
|
|
3
|
+
* Used for decoding only.
|
|
4
|
+
*/
|
|
5
|
+
export type SchemaCallbacks = {
|
|
6
|
+
[field: string | number]: Function[];
|
|
7
|
+
};
|
|
8
|
+
export declare class ReferenceTracker {
|
|
9
|
+
refs: Map<number, Ref>;
|
|
10
|
+
refIds: WeakMap<Ref, number>;
|
|
11
|
+
refCounts: {
|
|
12
|
+
[refId: number]: number;
|
|
13
|
+
};
|
|
14
|
+
deletedRefs: Set<number>;
|
|
15
|
+
callbacks: {
|
|
16
|
+
[refId: number]: SchemaCallbacks;
|
|
17
|
+
};
|
|
18
|
+
protected nextUniqueId: number;
|
|
19
|
+
getNextUniqueId(): number;
|
|
20
|
+
addRef(refId: number, ref: Ref, incrementCount?: boolean): void;
|
|
21
|
+
removeRef(refId: number): void;
|
|
22
|
+
clearRefs(): void;
|
|
23
|
+
garbageCollectDeletedRefs(): void;
|
|
24
|
+
addCallback(refId: number, fieldOrOperation: string | number, callback: Function): () => void;
|
|
25
|
+
removeCallback(refId: number, field: string | number, callback: Function): void;
|
|
26
|
+
}
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ReferenceTracker = void 0;
|
|
4
|
+
const Metadata_1 = require("../Metadata");
|
|
5
|
+
const symbols_1 = require("../types/symbols");
|
|
6
|
+
const utils_1 = require("../types/utils");
|
|
7
|
+
const spec_1 = require("../encoding/spec");
|
|
8
|
+
class DecodingWarning extends Error {
|
|
9
|
+
constructor(message) {
|
|
10
|
+
super(message);
|
|
11
|
+
this.name = "DecodingWarning";
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
class ReferenceTracker {
|
|
15
|
+
constructor() {
|
|
16
|
+
//
|
|
17
|
+
// Relation of refId => Schema structure
|
|
18
|
+
// For direct access of structures during decoding time.
|
|
19
|
+
//
|
|
20
|
+
this.refs = new Map();
|
|
21
|
+
this.refIds = new WeakMap();
|
|
22
|
+
this.refCounts = {};
|
|
23
|
+
this.deletedRefs = new Set();
|
|
24
|
+
this.callbacks = {};
|
|
25
|
+
this.nextUniqueId = 0;
|
|
26
|
+
}
|
|
27
|
+
getNextUniqueId() {
|
|
28
|
+
return this.nextUniqueId++;
|
|
29
|
+
}
|
|
30
|
+
// for decoding
|
|
31
|
+
addRef(refId, ref, incrementCount = true) {
|
|
32
|
+
this.refs.set(refId, ref);
|
|
33
|
+
this.refIds.set(ref, refId);
|
|
34
|
+
if (incrementCount) {
|
|
35
|
+
this.refCounts[refId] = (this.refCounts[refId] || 0) + 1;
|
|
36
|
+
}
|
|
37
|
+
if (this.deletedRefs.has(refId)) {
|
|
38
|
+
this.deletedRefs.delete(refId);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
// for decoding
|
|
42
|
+
removeRef(refId) {
|
|
43
|
+
const refCount = this.refCounts[refId];
|
|
44
|
+
if (refCount === undefined) {
|
|
45
|
+
try {
|
|
46
|
+
throw new DecodingWarning("trying to remove refId that doesn't exist");
|
|
47
|
+
}
|
|
48
|
+
catch (e) {
|
|
49
|
+
console.warn(e);
|
|
50
|
+
}
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
if (refCount === 0) {
|
|
54
|
+
try {
|
|
55
|
+
const ref = this.refs.get(refId);
|
|
56
|
+
throw new DecodingWarning(`trying to remove refId '${refId}' with 0 refCount (${ref.constructor.name}: ${JSON.stringify(ref)})`);
|
|
57
|
+
}
|
|
58
|
+
catch (e) {
|
|
59
|
+
console.warn(e);
|
|
60
|
+
}
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
if ((this.refCounts[refId] = refCount - 1) <= 0) {
|
|
64
|
+
this.deletedRefs.add(refId);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
clearRefs() {
|
|
68
|
+
this.refs.clear();
|
|
69
|
+
this.deletedRefs.clear();
|
|
70
|
+
this.refCounts = {};
|
|
71
|
+
}
|
|
72
|
+
// for decoding
|
|
73
|
+
garbageCollectDeletedRefs() {
|
|
74
|
+
this.deletedRefs.forEach((refId) => {
|
|
75
|
+
//
|
|
76
|
+
// Skip active references.
|
|
77
|
+
//
|
|
78
|
+
if (this.refCounts[refId] > 0) {
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
const ref = this.refs.get(refId);
|
|
82
|
+
//
|
|
83
|
+
// Ensure child schema instances have their references removed as well.
|
|
84
|
+
//
|
|
85
|
+
if (Metadata_1.Metadata.isValidInstance(ref)) {
|
|
86
|
+
const metadata = ref['constructor'][Symbol.metadata];
|
|
87
|
+
for (const field in metadata) {
|
|
88
|
+
const childRefId = typeof (ref[field]) === "object" && this.refIds.get(ref[field]);
|
|
89
|
+
if (childRefId) {
|
|
90
|
+
this.removeRef(childRefId);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
else {
|
|
95
|
+
if (typeof (Object.values(ref[symbols_1.$childType])[0]) === "function") {
|
|
96
|
+
Array.from(ref.values())
|
|
97
|
+
.forEach((child) => this.removeRef(this.refIds.get(child)));
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
this.refs.delete(refId); // remove ref
|
|
101
|
+
delete this.refCounts[refId]; // remove ref count
|
|
102
|
+
delete this.callbacks[refId]; // remove callbacks
|
|
103
|
+
});
|
|
104
|
+
// clear deleted refs.
|
|
105
|
+
this.deletedRefs.clear();
|
|
106
|
+
}
|
|
107
|
+
addCallback(refId, fieldOrOperation, callback) {
|
|
108
|
+
if (refId === undefined) {
|
|
109
|
+
const name = (typeof (fieldOrOperation) === "number")
|
|
110
|
+
? spec_1.OPERATION[fieldOrOperation]
|
|
111
|
+
: fieldOrOperation;
|
|
112
|
+
throw new Error(`Can't addCallback on '${name}' (refId is undefined)`);
|
|
113
|
+
}
|
|
114
|
+
if (!this.callbacks[refId]) {
|
|
115
|
+
this.callbacks[refId] = {};
|
|
116
|
+
}
|
|
117
|
+
if (!this.callbacks[refId][fieldOrOperation]) {
|
|
118
|
+
this.callbacks[refId][fieldOrOperation] = [];
|
|
119
|
+
}
|
|
120
|
+
this.callbacks[refId][fieldOrOperation].push(callback);
|
|
121
|
+
return () => this.removeCallback(refId, fieldOrOperation, callback);
|
|
122
|
+
}
|
|
123
|
+
removeCallback(refId, field, callback) {
|
|
124
|
+
const index = this.callbacks?.[refId]?.[field]?.indexOf(callback);
|
|
125
|
+
if (index !== -1) {
|
|
126
|
+
(0, utils_1.spliceOne)(this.callbacks[refId][field], index);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
exports.ReferenceTracker = ReferenceTracker;
|
|
131
|
+
//# sourceMappingURL=ReferenceTracker.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ReferenceTracker.js","sourceRoot":"","sources":["../../src/decoder/ReferenceTracker.ts"],"names":[],"mappings":"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","sourcesContent":["import { Metadata } from \"../Metadata\";\nimport { $childType } from \"../types/symbols\";\nimport { Ref } from \"../encoder/ChangeTree\";\nimport { spliceOne } from \"../types/utils\";\nimport type { MapSchema } from \"../types/custom/MapSchema\";\nimport { OPERATION } from \"../encoding/spec\";\n\nclass DecodingWarning extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"DecodingWarning\";\n }\n}\n\n/**\n * Used for decoding only.\n */\n\nexport type SchemaCallbacks = { [field: string | number]: Function[] };\n\nexport class ReferenceTracker {\n //\n // Relation of refId => Schema structure\n // For direct access of structures during decoding time.\n //\n public refs = new Map<number, Ref>();\n public refIds = new WeakMap<Ref, number>();\n\n public refCounts: { [refId: number]: number; } = {};\n public deletedRefs = new Set<number>();\n\n public callbacks: { [refId: number]: SchemaCallbacks } = {};\n protected nextUniqueId: number = 0;\n\n getNextUniqueId() {\n return this.nextUniqueId++;\n }\n\n // for decoding\n addRef(refId: number, ref: Ref, incrementCount: boolean = true) {\n this.refs.set(refId, ref);\n this.refIds.set(ref, refId);\n\n if (incrementCount) {\n this.refCounts[refId] = (this.refCounts[refId] || 0) + 1;\n }\n\n if (this.deletedRefs.has(refId)) {\n this.deletedRefs.delete(refId);\n }\n }\n\n // for decoding\n removeRef(refId: number) {\n const refCount = this.refCounts[refId];\n\n if (refCount === undefined) {\n try {\n throw new DecodingWarning(\"trying to remove refId that doesn't exist\");\n } catch (e) {\n console.warn(e);\n }\n return;\n }\n\n if (refCount === 0) {\n try {\n const ref = this.refs.get(refId);\n throw new DecodingWarning(`trying to remove refId '${refId}' with 0 refCount (${ref.constructor.name}: ${JSON.stringify(ref)})`);\n } catch (e) {\n console.warn(e);\n }\n return;\n }\n\n if ((this.refCounts[refId] = refCount - 1) <= 0) {\n this.deletedRefs.add(refId);\n }\n }\n\n clearRefs() {\n this.refs.clear();\n this.deletedRefs.clear();\n this.refCounts = {};\n }\n\n // for decoding\n garbageCollectDeletedRefs() {\n this.deletedRefs.forEach((refId) => {\n //\n // Skip active references.\n //\n if (this.refCounts[refId] > 0) { return; }\n\n const ref = this.refs.get(refId);\n\n //\n // Ensure child schema instances have their references removed as well.\n //\n if (Metadata.isValidInstance(ref)) {\n const metadata: Metadata = ref['constructor'][Symbol.metadata];\n for (const field in metadata) {\n const childRefId = typeof(ref[field]) === \"object\" && this.refIds.get(ref[field]);\n if (childRefId) {\n this.removeRef(childRefId);\n }\n }\n\n } else {\n if (typeof (Object.values(ref[$childType])[0]) === \"function\") {\n Array.from((ref as MapSchema).values())\n .forEach((child) => this.removeRef(this.refIds.get(child)));\n }\n }\n\n this.refs.delete(refId); // remove ref\n delete this.refCounts[refId]; // remove ref count\n delete this.callbacks[refId]; // remove callbacks\n });\n\n // clear deleted refs.\n this.deletedRefs.clear();\n }\n\n addCallback(refId: number, fieldOrOperation: string | number, callback: Function) {\n if (refId === undefined) {\n const name = (typeof(fieldOrOperation) === \"number\")\n ? OPERATION[fieldOrOperation]\n : fieldOrOperation\n throw new Error(\n `Can't addCallback on '${name}' (refId is undefined)`\n );\n }\n if (!this.callbacks[refId]) {\n this.callbacks[refId] = {};\n }\n if (!this.callbacks[refId][fieldOrOperation]) {\n this.callbacks[refId][fieldOrOperation] = [];\n }\n this.callbacks[refId][fieldOrOperation].push(callback);\n return () => this.removeCallback(refId, fieldOrOperation, callback);\n }\n\n removeCallback(refId: number, field: string | number, callback: Function) {\n const index = this.callbacks?.[refId]?.[field]?.indexOf(callback);\n if (index !== -1) {\n spliceOne(this.callbacks[refId][field], index);\n }\n }\n\n}"]}
|