@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
|
@@ -1,8 +1,13 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
1
|
+
import { $changes, $childType, $decoder, $deleteByIndex, $onEncodeEnd, $encoder, $filter, $getByIndex, $onDecodeEnd, $isNew } from "../symbols";
|
|
2
|
+
import type { Schema } from "../../Schema";
|
|
3
|
+
import { ChangeTree } from "../../encoder/ChangeTree";
|
|
4
|
+
import { OPERATION } from "../../encoding/spec";
|
|
5
|
+
import { registerType } from "../registry";
|
|
6
|
+
import { Collection } from "../HelperTypes";
|
|
7
|
+
|
|
8
|
+
import { encodeArray } from "../../encoder/EncodeOperation";
|
|
9
|
+
import { decodeArray } from "../../decoder/DecodeOperation";
|
|
10
|
+
import type { StateView } from "../../encoder/StateView";
|
|
6
11
|
|
|
7
12
|
const DEFAULT_SORT = (a: any, b: any) => {
|
|
8
13
|
const A = a.toString();
|
|
@@ -12,100 +17,34 @@ const DEFAULT_SORT = (a: any, b: any) => {
|
|
|
12
17
|
else return 0
|
|
13
18
|
}
|
|
14
19
|
|
|
15
|
-
export
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
//
|
|
19
|
-
// compatibility with @colyseus/schema 0.5.x
|
|
20
|
-
// - allow `map["key"]`
|
|
21
|
-
// - allow `map["key"] = "xxx"`
|
|
22
|
-
// - allow `delete map["key"]`
|
|
23
|
-
//
|
|
24
|
-
value = new Proxy(value, {
|
|
25
|
-
get: (obj, prop) => {
|
|
26
|
-
if (
|
|
27
|
-
typeof (prop) !== "symbol" &&
|
|
28
|
-
!isNaN(prop as any) // https://stackoverflow.com/a/175787/892698
|
|
29
|
-
) {
|
|
30
|
-
return obj.at(prop as unknown as number);
|
|
31
|
-
|
|
32
|
-
} else {
|
|
33
|
-
return obj[prop];
|
|
34
|
-
}
|
|
35
|
-
},
|
|
36
|
-
|
|
37
|
-
set: (obj, prop, setValue) => {
|
|
38
|
-
if (
|
|
39
|
-
typeof (prop) !== "symbol" &&
|
|
40
|
-
!isNaN(prop as any)
|
|
41
|
-
) {
|
|
42
|
-
const indexes = Array.from(obj['$items'].keys());
|
|
43
|
-
const key = parseInt(indexes[prop] || prop);
|
|
44
|
-
if (setValue === undefined || setValue === null) {
|
|
45
|
-
obj.deleteAt(key);
|
|
46
|
-
|
|
47
|
-
} else {
|
|
48
|
-
obj.setAt(key, setValue);
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
} else {
|
|
52
|
-
obj[prop] = setValue;
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
return true;
|
|
56
|
-
},
|
|
57
|
-
|
|
58
|
-
deleteProperty: (obj, prop) => {
|
|
59
|
-
if (typeof (prop) === "number") {
|
|
60
|
-
obj.deleteAt(prop);
|
|
61
|
-
|
|
62
|
-
} else {
|
|
63
|
-
delete obj[prop];
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
return true;
|
|
67
|
-
},
|
|
68
|
-
|
|
69
|
-
has: (obj, key) => {
|
|
70
|
-
if (
|
|
71
|
-
typeof (key) !== "symbol" &&
|
|
72
|
-
!isNaN(Number(key))
|
|
73
|
-
) {
|
|
74
|
-
return obj['$items'].has(Number(key))
|
|
75
|
-
}
|
|
76
|
-
return Reflect.has(obj, key)
|
|
77
|
-
}
|
|
78
|
-
});
|
|
79
|
-
|
|
80
|
-
return value;
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
export class ArraySchema<V = any> implements Array<V>, SchemaDecoderCallbacks {
|
|
84
|
-
protected $changes: ChangeTree = new ChangeTree(this);
|
|
85
|
-
|
|
86
|
-
protected $items: Map<number, V> = new Map<number, V>();
|
|
87
|
-
protected $indexes: Map<number, number> = new Map<number, number>();
|
|
20
|
+
export class ArraySchema<V = any> implements Array<V>, Collection<number, V> {
|
|
21
|
+
[n: number]: V;
|
|
88
22
|
|
|
89
|
-
protected
|
|
23
|
+
protected items: V[] = [];
|
|
24
|
+
protected tmpItems: V[] = [];
|
|
25
|
+
protected deletedIndexes: {[index: number]: boolean} = {};
|
|
90
26
|
|
|
91
|
-
[
|
|
27
|
+
static [$encoder] = encodeArray;
|
|
28
|
+
static [$decoder] = decodeArray;
|
|
92
29
|
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
30
|
+
/**
|
|
31
|
+
* Determine if a property must be filtered.
|
|
32
|
+
* - If returns false, the property is NOT going to be encoded.
|
|
33
|
+
* - If returns true, the property is going to be encoded.
|
|
34
|
+
*
|
|
35
|
+
* Encoding with "filters" happens in two steps:
|
|
36
|
+
* - First, the encoder iterates over all "not owned" properties and encodes them.
|
|
37
|
+
* - Then, the encoder iterates over all "owned" properties per instance and encodes them.
|
|
38
|
+
*/
|
|
39
|
+
static [$filter] (ref: ArraySchema, index: number, view: StateView) {
|
|
40
|
+
// console.log("ArraSchema[$filter] VIEW??", !view)
|
|
41
|
+
return (
|
|
42
|
+
!view ||
|
|
43
|
+
typeof (ref[$childType]) === "string" ||
|
|
44
|
+
// view.items.has(ref[$getByIndex](index)[$changes])
|
|
45
|
+
view.items.has(ref['tmpItems'][index]?.[$changes])
|
|
105
46
|
);
|
|
106
47
|
}
|
|
107
|
-
public onRemove(callback: (item: V, key: number) => void) { return addCallback(this.$callbacks || (this.$callbacks = {}), OPERATION.DELETE, callback); }
|
|
108
|
-
public onChange(callback: (item: V, key: number) => void) { return addCallback(this.$callbacks || (this.$callbacks = {}), OPERATION.REPLACE, callback); }
|
|
109
48
|
|
|
110
49
|
static is(type: any) {
|
|
111
50
|
return (
|
|
@@ -118,129 +57,237 @@ export class ArraySchema<V = any> implements Array<V>, SchemaDecoderCallbacks {
|
|
|
118
57
|
}
|
|
119
58
|
|
|
120
59
|
constructor (...items: V[]) {
|
|
60
|
+
|
|
61
|
+
Object.defineProperty(this, $childType, {
|
|
62
|
+
value: undefined,
|
|
63
|
+
enumerable: false,
|
|
64
|
+
writable: true,
|
|
65
|
+
configurable: true,
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
const proxy = new Proxy(this, {
|
|
69
|
+
get: (obj, prop) => {
|
|
70
|
+
if (
|
|
71
|
+
typeof (prop) !== "symbol" &&
|
|
72
|
+
!isNaN(prop as any) // https://stackoverflow.com/a/175787/892698
|
|
73
|
+
) {
|
|
74
|
+
return this.items[prop];
|
|
75
|
+
|
|
76
|
+
} else {
|
|
77
|
+
return Reflect.get(obj, prop);
|
|
78
|
+
}
|
|
79
|
+
},
|
|
80
|
+
|
|
81
|
+
set: (obj, key, setValue) => {
|
|
82
|
+
if (typeof (key) !== "symbol" && !isNaN(key as any)) {
|
|
83
|
+
if (setValue === undefined || setValue === null) {
|
|
84
|
+
obj.$deleteAt(key as unknown as number);
|
|
85
|
+
|
|
86
|
+
} else {
|
|
87
|
+
if (setValue[$changes]) {
|
|
88
|
+
if (obj.items[key as unknown as number] !== undefined) {
|
|
89
|
+
if (setValue[$changes][$isNew]) {
|
|
90
|
+
this[$changes].indexedOperation(Number(key), OPERATION.MOVE_AND_ADD);
|
|
91
|
+
|
|
92
|
+
} else {
|
|
93
|
+
if ((obj[$changes].getChange(Number(key)) & OPERATION.DELETE) === OPERATION.DELETE) {
|
|
94
|
+
this[$changes].indexedOperation(Number(key), OPERATION.DELETE_AND_MOVE);
|
|
95
|
+
} else {
|
|
96
|
+
this[$changes].indexedOperation(Number(key), OPERATION.MOVE);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
} else if (setValue[$changes][$isNew]) {
|
|
100
|
+
this[$changes].indexedOperation(Number(key), OPERATION.ADD);
|
|
101
|
+
}
|
|
102
|
+
} else {
|
|
103
|
+
obj.$changeAt(Number(key), setValue);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
this.items[key as unknown as number] = setValue;
|
|
107
|
+
this.tmpItems[key as unknown as number] = setValue;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
return true;
|
|
111
|
+
} else {
|
|
112
|
+
return Reflect.set(obj, key, setValue);
|
|
113
|
+
}
|
|
114
|
+
},
|
|
115
|
+
|
|
116
|
+
deleteProperty: (obj, prop) => {
|
|
117
|
+
if (typeof (prop) === "number") {
|
|
118
|
+
obj.$deleteAt(prop);
|
|
119
|
+
|
|
120
|
+
} else {
|
|
121
|
+
delete obj[prop];
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
return true;
|
|
125
|
+
},
|
|
126
|
+
|
|
127
|
+
has: (obj, key) => {
|
|
128
|
+
if (typeof (key) !== "symbol" && !isNaN(Number(key))) {
|
|
129
|
+
return Reflect.has(this.items, key);
|
|
130
|
+
}
|
|
131
|
+
return Reflect.has(obj, key)
|
|
132
|
+
}
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
this[$changes] = new ChangeTree(proxy);
|
|
121
136
|
this.push.apply(this, items);
|
|
137
|
+
|
|
138
|
+
return proxy;
|
|
122
139
|
}
|
|
123
140
|
|
|
124
|
-
set length (
|
|
125
|
-
if (
|
|
141
|
+
set length (newLength: number) {
|
|
142
|
+
if (newLength === 0) {
|
|
126
143
|
this.clear();
|
|
127
|
-
|
|
144
|
+
} else if (newLength < this.items.length) {
|
|
145
|
+
this.splice(newLength, this.length - newLength);
|
|
128
146
|
} else {
|
|
129
|
-
|
|
147
|
+
console.warn("ArraySchema: can't set .length to a higher value than its length.");
|
|
130
148
|
}
|
|
131
149
|
}
|
|
132
150
|
|
|
133
151
|
get length() {
|
|
134
|
-
return this
|
|
152
|
+
return this.items.length;
|
|
135
153
|
}
|
|
136
154
|
|
|
137
155
|
push(...values: V[]) {
|
|
138
|
-
let
|
|
156
|
+
let length = this.tmpItems.length;
|
|
157
|
+
|
|
158
|
+
values.forEach((value, i) => {
|
|
159
|
+
// skip null values
|
|
160
|
+
if (value === undefined || value === null) {
|
|
161
|
+
return;
|
|
162
|
+
}
|
|
139
163
|
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
164
|
+
const changeTree = this[$changes];
|
|
165
|
+
changeTree.indexedOperation(length, OPERATION.ADD, this.items.length);
|
|
166
|
+
// changeTree.indexes[length] = length;
|
|
143
167
|
|
|
144
|
-
this.
|
|
168
|
+
this.items.push(value);
|
|
169
|
+
this.tmpItems.push(value);
|
|
170
|
+
|
|
171
|
+
//
|
|
172
|
+
// set value's parent after the value is set
|
|
173
|
+
// (to avoid encoding "refId" operations before parent's "ADD" operation)
|
|
174
|
+
//
|
|
175
|
+
value[$changes]?.setParent(this, changeTree.root, length);
|
|
176
|
+
|
|
177
|
+
length++;
|
|
145
178
|
});
|
|
146
179
|
|
|
147
|
-
return
|
|
180
|
+
return length;
|
|
148
181
|
}
|
|
149
182
|
|
|
150
183
|
/**
|
|
151
184
|
* Removes the last element from an array and returns it.
|
|
152
185
|
*/
|
|
153
186
|
pop(): V | undefined {
|
|
154
|
-
|
|
155
|
-
|
|
187
|
+
let index: number = -1;
|
|
188
|
+
|
|
189
|
+
// find last non-undefined index
|
|
190
|
+
for (let i = this.tmpItems.length - 1; i >= 0; i--) {
|
|
191
|
+
// if (this.tmpItems[i] !== undefined) {
|
|
192
|
+
if (this.deletedIndexes[i] !== true) {
|
|
193
|
+
index = i;
|
|
194
|
+
break;
|
|
195
|
+
}
|
|
196
|
+
}
|
|
156
197
|
|
|
157
|
-
|
|
158
|
-
|
|
198
|
+
if (index < 0) {
|
|
199
|
+
return undefined;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
this[$changes].delete(index, undefined, this.items.length - 1);
|
|
159
203
|
|
|
160
|
-
|
|
161
|
-
this
|
|
204
|
+
// this.tmpItems[index] = undefined;
|
|
205
|
+
this.deletedIndexes[index] = true;
|
|
162
206
|
|
|
163
|
-
return
|
|
207
|
+
return this.items.pop();
|
|
164
208
|
}
|
|
165
209
|
|
|
166
210
|
at(index: number) {
|
|
167
|
-
//
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
index = Math.trunc(index) || 0;
|
|
172
|
-
// Allow negative indexing from the end
|
|
173
|
-
if (index < 0) index += this.length;
|
|
174
|
-
// OOB access is guaranteed to return undefined
|
|
175
|
-
if (index < 0 || index >= this.length) return undefined;
|
|
176
|
-
|
|
177
|
-
const key = Array.from(this.$items.keys())[index];
|
|
178
|
-
return this.$items.get(key);
|
|
211
|
+
// Allow negative indexing from the end
|
|
212
|
+
if (index < 0) index += this.length;
|
|
213
|
+
return this.items[index];
|
|
179
214
|
}
|
|
180
215
|
|
|
181
|
-
|
|
216
|
+
// encoding only
|
|
217
|
+
protected $changeAt(index: number, value: V) {
|
|
182
218
|
if (value === undefined || value === null) {
|
|
183
219
|
console.error("ArraySchema items cannot be null nor undefined; Use `deleteAt(index)` instead.");
|
|
184
220
|
return;
|
|
185
221
|
}
|
|
186
222
|
|
|
187
223
|
// skip if the value is the same as cached.
|
|
188
|
-
if (this
|
|
224
|
+
if (this.items[index] === value) {
|
|
189
225
|
return;
|
|
190
226
|
}
|
|
191
227
|
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
const operation = this.$changes.indexes[index]?.op ?? OPERATION.ADD;
|
|
197
|
-
|
|
198
|
-
this.$changes.indexes[index] = index;
|
|
228
|
+
const changeTree = this[$changes];
|
|
229
|
+
const operation = changeTree.indexes?.[index]?.op ?? OPERATION.ADD;
|
|
199
230
|
|
|
200
|
-
|
|
201
|
-
this.$items.set(index, value);
|
|
231
|
+
changeTree.change(index, operation);
|
|
202
232
|
|
|
203
|
-
|
|
233
|
+
//
|
|
234
|
+
// set value's parent after the value is set
|
|
235
|
+
// (to avoid encoding "refId" operations before parent's "ADD" operation)
|
|
236
|
+
//
|
|
237
|
+
value[$changes]?.setParent(this, changeTree.root, index);
|
|
204
238
|
}
|
|
205
239
|
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
return this.$deleteAt(key);
|
|
240
|
+
// encoding only
|
|
241
|
+
protected $deleteAt(index: number, operation?: OPERATION) {
|
|
242
|
+
this[$changes].delete(index, operation);
|
|
210
243
|
}
|
|
211
244
|
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
245
|
+
// decoding only
|
|
246
|
+
protected $setAt(index: number, value: V, operation: OPERATION) {
|
|
247
|
+
if (
|
|
248
|
+
index === 0 &&
|
|
249
|
+
operation === OPERATION.ADD &&
|
|
250
|
+
this.items[index] !== undefined
|
|
251
|
+
) {
|
|
252
|
+
// handle decoding unshift
|
|
253
|
+
this.items.unshift(value);
|
|
216
254
|
|
|
217
|
-
|
|
218
|
-
|
|
255
|
+
} else if (operation === OPERATION.DELETE_AND_MOVE) {
|
|
256
|
+
this.items.splice(index, 1);
|
|
257
|
+
this.items[index] = value;
|
|
219
258
|
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
this.$changes.discard(true, true);
|
|
223
|
-
this.$changes.indexes = {};
|
|
224
|
-
|
|
225
|
-
// clear previous indexes
|
|
226
|
-
this.$indexes.clear();
|
|
227
|
-
|
|
228
|
-
//
|
|
229
|
-
// When decoding:
|
|
230
|
-
// - enqueue items for DELETE callback.
|
|
231
|
-
// - flag child items for garbage collection.
|
|
232
|
-
//
|
|
233
|
-
if (changes) {
|
|
234
|
-
removeChildRefs.call(this, changes);
|
|
259
|
+
} else {
|
|
260
|
+
this.items[index] = value;
|
|
235
261
|
}
|
|
262
|
+
}
|
|
236
263
|
|
|
237
|
-
|
|
238
|
-
|
|
264
|
+
clear() {
|
|
265
|
+
// skip if already clear
|
|
266
|
+
if (this.items.length === 0) { return; }
|
|
267
|
+
|
|
268
|
+
// discard previous operations.
|
|
269
|
+
const changeTree = this[$changes]
|
|
270
|
+
|
|
271
|
+
// discard children
|
|
272
|
+
changeTree.forEachChild((changeTree, _) => {
|
|
273
|
+
changeTree.discard(true);
|
|
274
|
+
|
|
275
|
+
//
|
|
276
|
+
// TODO: add tests with instance sharing + .clear()
|
|
277
|
+
// FIXME: this.root? is required because it is being called at decoding time.
|
|
278
|
+
//
|
|
279
|
+
// TODO: do not use [$changes] at decoding time.
|
|
280
|
+
//
|
|
281
|
+
changeTree.root?.changes.delete(changeTree);
|
|
282
|
+
changeTree.root?.allChanges.delete(changeTree);
|
|
283
|
+
changeTree.root?.allFilteredChanges.delete(changeTree);
|
|
284
|
+
});
|
|
239
285
|
|
|
240
|
-
|
|
286
|
+
changeTree.discard(true);
|
|
287
|
+
changeTree.operation(OPERATION.CLEAR);
|
|
241
288
|
|
|
242
|
-
|
|
243
|
-
this
|
|
289
|
+
this.items.length = 0;
|
|
290
|
+
this.tmpItems.length = 0;
|
|
244
291
|
}
|
|
245
292
|
|
|
246
293
|
/**
|
|
@@ -249,7 +296,7 @@ export class ArraySchema<V = any> implements Array<V>, SchemaDecoderCallbacks {
|
|
|
249
296
|
*/
|
|
250
297
|
// @ts-ignore
|
|
251
298
|
concat(...items: (V | ConcatArray<V>)[]): ArraySchema<V> {
|
|
252
|
-
return new ArraySchema(...
|
|
299
|
+
return new ArraySchema(...this.items.concat(...items));
|
|
253
300
|
}
|
|
254
301
|
|
|
255
302
|
/**
|
|
@@ -257,7 +304,7 @@ export class ArraySchema<V = any> implements Array<V>, SchemaDecoderCallbacks {
|
|
|
257
304
|
* @param separator A string used to separate one element of an array from the next in the resulting String. If omitted, the array elements are separated with a comma.
|
|
258
305
|
*/
|
|
259
306
|
join(separator?: string): string {
|
|
260
|
-
return
|
|
307
|
+
return this.items.join(separator);
|
|
261
308
|
}
|
|
262
309
|
|
|
263
310
|
/**
|
|
@@ -265,13 +312,9 @@ export class ArraySchema<V = any> implements Array<V>, SchemaDecoderCallbacks {
|
|
|
265
312
|
*/
|
|
266
313
|
// @ts-ignore
|
|
267
314
|
reverse(): ArraySchema<V> {
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
reversedItems.forEach((item, i) => {
|
|
272
|
-
this.setAt(indexes[i], item);
|
|
273
|
-
});
|
|
274
|
-
|
|
315
|
+
this[$changes].operation(OPERATION.REVERSE);
|
|
316
|
+
this.items.reverse();
|
|
317
|
+
this.tmpItems.reverse();
|
|
275
318
|
return this;
|
|
276
319
|
}
|
|
277
320
|
|
|
@@ -279,15 +322,16 @@ export class ArraySchema<V = any> implements Array<V>, SchemaDecoderCallbacks {
|
|
|
279
322
|
* Removes the first element from an array and returns it.
|
|
280
323
|
*/
|
|
281
324
|
shift(): V | undefined {
|
|
282
|
-
|
|
325
|
+
if (this.items.length === 0) { return undefined; }
|
|
283
326
|
|
|
284
|
-
const
|
|
285
|
-
|
|
327
|
+
// const index = Number(Object.keys(changeTree.indexes)[0]);
|
|
328
|
+
const index = this.tmpItems.findIndex((item, i) => item === this.items[0]);
|
|
329
|
+
const changeTree = this[$changes];
|
|
286
330
|
|
|
287
|
-
|
|
288
|
-
|
|
331
|
+
changeTree.delete(index);
|
|
332
|
+
changeTree.shiftAllChangeIndexes(-1, index);
|
|
289
333
|
|
|
290
|
-
return
|
|
334
|
+
return this.items.shift();
|
|
291
335
|
}
|
|
292
336
|
|
|
293
337
|
/**
|
|
@@ -297,7 +341,7 @@ export class ArraySchema<V = any> implements Array<V>, SchemaDecoderCallbacks {
|
|
|
297
341
|
*/
|
|
298
342
|
slice(start?: number, end?: number): V[] {
|
|
299
343
|
const sliced = new ArraySchema<V>();
|
|
300
|
-
sliced.push(...
|
|
344
|
+
sliced.push(...this.items.slice(start, end));
|
|
301
345
|
return sliced as unknown as V[];
|
|
302
346
|
}
|
|
303
347
|
|
|
@@ -311,13 +355,13 @@ export class ArraySchema<V = any> implements Array<V>, SchemaDecoderCallbacks {
|
|
|
311
355
|
* ```
|
|
312
356
|
*/
|
|
313
357
|
sort(compareFn: (a: V, b: V) => number = DEFAULT_SORT): this {
|
|
314
|
-
const
|
|
315
|
-
const sortedItems =
|
|
358
|
+
const changeTree = this[$changes];
|
|
359
|
+
const sortedItems = this.items.sort(compareFn);
|
|
316
360
|
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
});
|
|
361
|
+
// wouldn't OPERATION.MOVE make more sense here?
|
|
362
|
+
sortedItems.forEach((_, i) => changeTree.change(i, OPERATION.REPLACE));
|
|
320
363
|
|
|
364
|
+
this.tmpItems.sort(compareFn);
|
|
321
365
|
return this;
|
|
322
366
|
}
|
|
323
367
|
|
|
@@ -325,26 +369,53 @@ export class ArraySchema<V = any> implements Array<V>, SchemaDecoderCallbacks {
|
|
|
325
369
|
* Removes elements from an array and, if necessary, inserts new elements in their place, returning the deleted elements.
|
|
326
370
|
* @param start The zero-based location in the array from which to start removing elements.
|
|
327
371
|
* @param deleteCount The number of elements to remove.
|
|
328
|
-
* @param
|
|
372
|
+
* @param insertItems Elements to insert into the array in place of the deleted elements.
|
|
329
373
|
*/
|
|
330
374
|
splice(
|
|
331
375
|
start: number,
|
|
332
|
-
deleteCount: number = this.length - start,
|
|
333
|
-
...
|
|
376
|
+
deleteCount: number = this.items.length - start,
|
|
377
|
+
...insertItems: V[]
|
|
334
378
|
): V[] {
|
|
335
|
-
const
|
|
336
|
-
const removedItems: V[] = [];
|
|
379
|
+
const changeTree = this[$changes];
|
|
337
380
|
|
|
381
|
+
const tmpItemsLength = this.tmpItems.length;
|
|
382
|
+
const insertCount = insertItems.length;
|
|
383
|
+
|
|
384
|
+
// build up-to-date list of indexes, excluding removed values.
|
|
385
|
+
const indexes: number[] = [];
|
|
386
|
+
for (let i = 0; i < tmpItemsLength; i++) {
|
|
387
|
+
// if (this.tmpItems[i] !== undefined) {
|
|
388
|
+
if (this.deletedIndexes[i] !== true) {
|
|
389
|
+
indexes.push(i);
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
// delete operations at correct index
|
|
338
394
|
for (let i = start; i < start + deleteCount; i++) {
|
|
339
|
-
|
|
340
|
-
|
|
395
|
+
const index = indexes[i];
|
|
396
|
+
changeTree.delete(index);
|
|
397
|
+
// this.tmpItems[index] = undefined;
|
|
398
|
+
this.deletedIndexes[index] = true;
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
// force insert operations
|
|
402
|
+
for (let i = 0; i < insertCount; i++) {
|
|
403
|
+
const addIndex = indexes[start] + i;
|
|
404
|
+
changeTree.indexedOperation(addIndex, OPERATION.ADD);
|
|
405
|
+
|
|
406
|
+
// set value's parent/root
|
|
407
|
+
insertItems[i][$changes]?.setParent(this, changeTree.root, addIndex);
|
|
341
408
|
}
|
|
342
409
|
|
|
343
|
-
|
|
344
|
-
|
|
410
|
+
//
|
|
411
|
+
// delete exceeding indexes from "allChanges"
|
|
412
|
+
// (prevent .encodeAll() from encoding non-existing items)
|
|
413
|
+
//
|
|
414
|
+
if (deleteCount > insertCount) {
|
|
415
|
+
changeTree.shiftAllChangeIndexes(-(deleteCount - insertCount), indexes[start + insertCount]);
|
|
345
416
|
}
|
|
346
417
|
|
|
347
|
-
return
|
|
418
|
+
return this.items.splice(start, deleteCount, ...insertItems);
|
|
348
419
|
}
|
|
349
420
|
|
|
350
421
|
/**
|
|
@@ -352,21 +423,26 @@ export class ArraySchema<V = any> implements Array<V>, SchemaDecoderCallbacks {
|
|
|
352
423
|
* @param items Elements to insert at the start of the Array.
|
|
353
424
|
*/
|
|
354
425
|
unshift(...items: V[]): number {
|
|
355
|
-
const
|
|
356
|
-
const addedLength = items.length;
|
|
426
|
+
const changeTree = this[$changes];
|
|
357
427
|
|
|
358
|
-
//
|
|
359
|
-
|
|
428
|
+
// shift indexes
|
|
429
|
+
changeTree.shiftChangeIndexes(items.length);
|
|
360
430
|
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
431
|
+
// new index
|
|
432
|
+
if (changeTree.isFiltered) {
|
|
433
|
+
changeTree.filteredChanges.set(this.items.length, OPERATION.ADD);
|
|
434
|
+
} else {
|
|
435
|
+
changeTree.allChanges.set(this.items.length, OPERATION.ADD);
|
|
436
|
+
}
|
|
364
437
|
|
|
365
|
-
|
|
366
|
-
|
|
438
|
+
// FIXME: should we use OPERATION.MOVE here instead?
|
|
439
|
+
items.forEach((_, index) => {
|
|
440
|
+
changeTree.change(index, OPERATION.ADD)
|
|
367
441
|
});
|
|
368
442
|
|
|
369
|
-
|
|
443
|
+
this.tmpItems.unshift(...items);
|
|
444
|
+
|
|
445
|
+
return this.items.unshift(...items);
|
|
370
446
|
}
|
|
371
447
|
|
|
372
448
|
/**
|
|
@@ -375,7 +451,7 @@ export class ArraySchema<V = any> implements Array<V>, SchemaDecoderCallbacks {
|
|
|
375
451
|
* @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the search starts at index 0.
|
|
376
452
|
*/
|
|
377
453
|
indexOf(searchElement: V, fromIndex?: number): number {
|
|
378
|
-
return
|
|
454
|
+
return this.items.indexOf(searchElement, fromIndex);
|
|
379
455
|
}
|
|
380
456
|
|
|
381
457
|
/**
|
|
@@ -384,7 +460,7 @@ export class ArraySchema<V = any> implements Array<V>, SchemaDecoderCallbacks {
|
|
|
384
460
|
* @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the search starts at the last index in the array.
|
|
385
461
|
*/
|
|
386
462
|
lastIndexOf(searchElement: V, fromIndex: number = this.length - 1): number {
|
|
387
|
-
return
|
|
463
|
+
return this.items.lastIndexOf(searchElement, fromIndex);
|
|
388
464
|
}
|
|
389
465
|
|
|
390
466
|
/**
|
|
@@ -396,7 +472,7 @@ export class ArraySchema<V = any> implements Array<V>, SchemaDecoderCallbacks {
|
|
|
396
472
|
* If thisArg is omitted, undefined is used as the this value.
|
|
397
473
|
*/
|
|
398
474
|
every(callbackfn: (value: V, index: number, array: V[]) => unknown, thisArg?: any): boolean {
|
|
399
|
-
return
|
|
475
|
+
return this.items.every(callbackfn, thisArg);
|
|
400
476
|
}
|
|
401
477
|
|
|
402
478
|
/**
|
|
@@ -408,7 +484,7 @@ export class ArraySchema<V = any> implements Array<V>, SchemaDecoderCallbacks {
|
|
|
408
484
|
* If thisArg is omitted, undefined is used as the this value.
|
|
409
485
|
*/
|
|
410
486
|
some(callbackfn: (value: V, index: number, array: V[]) => unknown, thisArg?: any): boolean {
|
|
411
|
-
return
|
|
487
|
+
return this.items.some(callbackfn, thisArg);
|
|
412
488
|
}
|
|
413
489
|
|
|
414
490
|
/**
|
|
@@ -417,7 +493,7 @@ export class ArraySchema<V = any> implements Array<V>, SchemaDecoderCallbacks {
|
|
|
417
493
|
* @param thisArg An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value.
|
|
418
494
|
*/
|
|
419
495
|
forEach(callbackfn: (value: V, index: number, array: V[]) => void, thisArg?: any): void {
|
|
420
|
-
|
|
496
|
+
return this.items.forEach(callbackfn, thisArg);
|
|
421
497
|
}
|
|
422
498
|
|
|
423
499
|
/**
|
|
@@ -426,7 +502,7 @@ export class ArraySchema<V = any> implements Array<V>, SchemaDecoderCallbacks {
|
|
|
426
502
|
* @param thisArg An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value.
|
|
427
503
|
*/
|
|
428
504
|
map<U>(callbackfn: (value: V, index: number, array: V[]) => U, thisArg?: any): U[] {
|
|
429
|
-
return
|
|
505
|
+
return this.items.map(callbackfn, thisArg);
|
|
430
506
|
}
|
|
431
507
|
|
|
432
508
|
/**
|
|
@@ -436,7 +512,7 @@ export class ArraySchema<V = any> implements Array<V>, SchemaDecoderCallbacks {
|
|
|
436
512
|
*/
|
|
437
513
|
filter(callbackfn: (value: V, index: number, array: V[]) => unknown, thisArg?: any): V[]
|
|
438
514
|
filter<S extends V>(callbackfn: (value: V, index: number, array: V[]) => value is S, thisArg?: any): V[] {
|
|
439
|
-
return
|
|
515
|
+
return this.items.filter(callbackfn, thisArg);
|
|
440
516
|
}
|
|
441
517
|
|
|
442
518
|
/**
|
|
@@ -445,7 +521,7 @@ export class ArraySchema<V = any> implements Array<V>, SchemaDecoderCallbacks {
|
|
|
445
521
|
* @param initialValue If initialValue is specified, it is used as the initial value to start the accumulation. The first call to the callbackfn function provides this value as an argument instead of an array value.
|
|
446
522
|
*/
|
|
447
523
|
reduce<U=V>(callbackfn: (previousValue: U, currentValue: V, currentIndex: number, array: V[]) => U, initialValue?: U): U {
|
|
448
|
-
return
|
|
524
|
+
return this.items.reduce(callbackfn, initialValue);
|
|
449
525
|
}
|
|
450
526
|
|
|
451
527
|
/**
|
|
@@ -454,7 +530,7 @@ export class ArraySchema<V = any> implements Array<V>, SchemaDecoderCallbacks {
|
|
|
454
530
|
* @param initialValue If initialValue is specified, it is used as the initial value to start the accumulation. The first call to the callbackfn function provides this value as an argument instead of an array value.
|
|
455
531
|
*/
|
|
456
532
|
reduceRight<U=V>(callbackfn: (previousValue: U, currentValue: V, currentIndex: number, array: V[]) => U, initialValue?: U): U {
|
|
457
|
-
return
|
|
533
|
+
return this.items.reduceRight(callbackfn, initialValue);
|
|
458
534
|
}
|
|
459
535
|
|
|
460
536
|
/**
|
|
@@ -467,7 +543,7 @@ export class ArraySchema<V = any> implements Array<V>, SchemaDecoderCallbacks {
|
|
|
467
543
|
* predicate. If it is not provided, undefined is used instead.
|
|
468
544
|
*/
|
|
469
545
|
find(predicate: (value: V, index: number, obj: V[]) => boolean, thisArg?: any): V | undefined {
|
|
470
|
-
return
|
|
546
|
+
return this.items.find(predicate, thisArg);
|
|
471
547
|
}
|
|
472
548
|
|
|
473
549
|
/**
|
|
@@ -480,7 +556,7 @@ export class ArraySchema<V = any> implements Array<V>, SchemaDecoderCallbacks {
|
|
|
480
556
|
* predicate. If it is not provided, undefined is used instead.
|
|
481
557
|
*/
|
|
482
558
|
findIndex(predicate: (value: V, index: number, obj: V[]) => unknown, thisArg?: any): number {
|
|
483
|
-
return
|
|
559
|
+
return this.items.findIndex(predicate, thisArg);
|
|
484
560
|
}
|
|
485
561
|
|
|
486
562
|
/**
|
|
@@ -521,16 +597,20 @@ export class ArraySchema<V = any> implements Array<V>, SchemaDecoderCallbacks {
|
|
|
521
597
|
/**
|
|
522
598
|
* Returns a string representation of an array.
|
|
523
599
|
*/
|
|
524
|
-
toString(): string {
|
|
600
|
+
toString(): string {
|
|
601
|
+
return this.items.toString();
|
|
602
|
+
}
|
|
525
603
|
|
|
526
604
|
/**
|
|
527
605
|
* Returns a string representation of an array. The elements are converted to string using their toLocalString methods.
|
|
528
606
|
*/
|
|
529
|
-
toLocaleString(): string {
|
|
607
|
+
toLocaleString(): string {
|
|
608
|
+
return this.items.toLocaleString()
|
|
609
|
+
};
|
|
530
610
|
|
|
531
611
|
/** Iterator */
|
|
532
612
|
[Symbol.iterator](): IterableIterator<V> {
|
|
533
|
-
return
|
|
613
|
+
return this.items[Symbol.iterator]();
|
|
534
614
|
}
|
|
535
615
|
|
|
536
616
|
static get [Symbol.species]() {
|
|
@@ -545,17 +625,17 @@ export class ArraySchema<V = any> implements Array<V>, SchemaDecoderCallbacks {
|
|
|
545
625
|
/**
|
|
546
626
|
* Returns an iterable of key, value pairs for every entry in the array
|
|
547
627
|
*/
|
|
548
|
-
entries(): IterableIterator<[number, V]> { return this
|
|
628
|
+
entries(): IterableIterator<[number, V]> { return this.items.entries(); }
|
|
549
629
|
|
|
550
630
|
/**
|
|
551
631
|
* Returns an iterable of keys in the array
|
|
552
632
|
*/
|
|
553
|
-
keys(): IterableIterator<number> { return this
|
|
633
|
+
keys(): IterableIterator<number> { return this.items.keys(); }
|
|
554
634
|
|
|
555
635
|
/**
|
|
556
636
|
* Returns an iterable of values in the array
|
|
557
637
|
*/
|
|
558
|
-
values(): IterableIterator<V> { return this
|
|
638
|
+
values(): IterableIterator<V> { return this.items.values(); }
|
|
559
639
|
|
|
560
640
|
/**
|
|
561
641
|
* Determines whether an array includes a certain element, returning true or false as appropriate.
|
|
@@ -563,7 +643,7 @@ export class ArraySchema<V = any> implements Array<V>, SchemaDecoderCallbacks {
|
|
|
563
643
|
* @param fromIndex The position in this array at which to begin searching for searchElement.
|
|
564
644
|
*/
|
|
565
645
|
includes(searchElement: V, fromIndex?: number): boolean {
|
|
566
|
-
return
|
|
646
|
+
return this.items.includes(searchElement, fromIndex);
|
|
567
647
|
}
|
|
568
648
|
|
|
569
649
|
//
|
|
@@ -598,60 +678,71 @@ export class ArraySchema<V = any> implements Array<V>, SchemaDecoderCallbacks {
|
|
|
598
678
|
}
|
|
599
679
|
|
|
600
680
|
findLast() {
|
|
601
|
-
const arr = Array.from(this.$items.values());
|
|
602
681
|
// @ts-ignore
|
|
603
|
-
return
|
|
682
|
+
return this.items.findLast.apply(this.items, arguments);
|
|
604
683
|
}
|
|
605
684
|
|
|
606
685
|
findLastIndex(...args) {
|
|
607
|
-
const arr = Array.from(this.$items.values());
|
|
608
686
|
// @ts-ignore
|
|
609
|
-
return
|
|
687
|
+
return this.items.findLastIndex.apply(this.items, arguments);
|
|
610
688
|
}
|
|
611
689
|
|
|
612
690
|
//
|
|
613
691
|
// ES2023
|
|
614
692
|
//
|
|
615
|
-
with(index: number, value: V):
|
|
616
|
-
const copy =
|
|
693
|
+
with(index: number, value: V): V[] {
|
|
694
|
+
const copy = this.items.slice();
|
|
617
695
|
copy[index] = value;
|
|
618
696
|
return new ArraySchema(...copy);
|
|
619
697
|
}
|
|
620
698
|
toReversed(): V[] {
|
|
621
|
-
return
|
|
699
|
+
return this.items.slice().reverse();
|
|
622
700
|
}
|
|
623
701
|
toSorted(compareFn?: (a: V, b: V) => number): V[] {
|
|
624
|
-
return
|
|
702
|
+
return this.items.slice().sort(compareFn);
|
|
625
703
|
}
|
|
626
704
|
toSpliced(start: number, deleteCount: number, ...items: V[]): V[];
|
|
627
705
|
toSpliced(start: number, deleteCount?: number): V[];
|
|
628
706
|
// @ts-ignore
|
|
629
707
|
toSpliced(start: unknown, deleteCount?: unknown, ...items?: unknown[]): V[] {
|
|
630
|
-
const copy = Array.from(this.$items.values());
|
|
631
708
|
// @ts-ignore
|
|
632
|
-
return
|
|
709
|
+
return this.items.toSpliced.apply(copy, arguments);
|
|
633
710
|
}
|
|
634
711
|
|
|
635
|
-
protected
|
|
636
|
-
|
|
712
|
+
protected [$getByIndex](index: number, isEncodeAll: boolean = false) {
|
|
713
|
+
//
|
|
714
|
+
// TODO: avoid unecessary `this.tmpItems` check during decoding.
|
|
715
|
+
//
|
|
716
|
+
// ENCODING uses `this.tmpItems` (or `this.items` if `isEncodeAll` is true)
|
|
717
|
+
// DECODING uses `this.items`
|
|
718
|
+
//
|
|
719
|
+
|
|
720
|
+
return (isEncodeAll)
|
|
721
|
+
? this.items[index]
|
|
722
|
+
: this.deletedIndexes[index]
|
|
723
|
+
? this.items[index]
|
|
724
|
+
: this.tmpItems[index] || this.items[index];
|
|
725
|
+
|
|
726
|
+
// return (isEncodeAll)
|
|
727
|
+
// ? this.items[index]
|
|
728
|
+
// : this.tmpItems[index] ?? this.items[index];
|
|
637
729
|
}
|
|
638
730
|
|
|
639
|
-
protected
|
|
640
|
-
|
|
731
|
+
protected [$deleteByIndex](index: number) {
|
|
732
|
+
this.items[index] = undefined;
|
|
641
733
|
}
|
|
642
734
|
|
|
643
|
-
protected
|
|
644
|
-
|
|
735
|
+
protected [$onEncodeEnd]() {
|
|
736
|
+
this.tmpItems = this.items.slice();
|
|
737
|
+
this.deletedIndexes = {};
|
|
645
738
|
}
|
|
646
739
|
|
|
647
|
-
protected
|
|
648
|
-
|
|
649
|
-
this.$items.delete(key);
|
|
650
|
-
this.$indexes.delete(index);
|
|
740
|
+
protected [$onDecodeEnd]() {
|
|
741
|
+
this.items = this.items.filter((item) => item !== undefined);
|
|
651
742
|
}
|
|
652
743
|
|
|
653
744
|
toArray() {
|
|
654
|
-
return
|
|
745
|
+
return this.items.slice(0);
|
|
655
746
|
}
|
|
656
747
|
|
|
657
748
|
toJSON() {
|
|
@@ -669,11 +760,12 @@ export class ArraySchema<V = any> implements Array<V>, SchemaDecoderCallbacks {
|
|
|
669
760
|
let cloned: ArraySchema;
|
|
670
761
|
|
|
671
762
|
if (isDecoding) {
|
|
672
|
-
cloned = new ArraySchema(
|
|
763
|
+
cloned = new ArraySchema();
|
|
764
|
+
cloned.push(...this.items);
|
|
673
765
|
|
|
674
766
|
} else {
|
|
675
767
|
cloned = new ArraySchema(...this.map(item => (
|
|
676
|
-
(item[
|
|
768
|
+
(item[$changes])
|
|
677
769
|
? (item as any as Schema).clone()
|
|
678
770
|
: item
|
|
679
771
|
)));
|
|
@@ -683,3 +775,5 @@ export class ArraySchema<V = any> implements Array<V>, SchemaDecoderCallbacks {
|
|
|
683
775
|
};
|
|
684
776
|
|
|
685
777
|
}
|
|
778
|
+
|
|
779
|
+
registerType("array", { constructor: ArraySchema });
|