@colyseus/schema 3.0.0-alpha.25 → 3.0.0-alpha.27
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 +97 -102
- package/build/cjs/index.js.map +1 -1
- package/build/esm/index.mjs +97 -102
- package/build/esm/index.mjs.map +1 -1
- package/build/umd/index.js +97 -102
- package/lib/Reflection.js +1 -3
- package/lib/Reflection.js.map +1 -1
- package/lib/Schema.d.ts +1 -1
- package/lib/Schema.js +2 -2
- package/lib/Schema.js.map +1 -1
- package/lib/annotations.js +13 -5
- package/lib/annotations.js.map +1 -1
- package/lib/decoder/DecodeOperation.js +1 -0
- package/lib/decoder/DecodeOperation.js.map +1 -1
- package/lib/decoder/Decoder.d.ts +1 -1
- package/lib/decoder/Decoder.js +2 -2
- package/lib/decoder/Decoder.js.map +1 -1
- package/lib/decoder/strategy/StateCallbacks.js +20 -17
- package/lib/decoder/strategy/StateCallbacks.js.map +1 -1
- package/lib/encoder/ChangeTree.js +3 -2
- package/lib/encoder/ChangeTree.js.map +1 -1
- package/lib/encoder/Encoder.d.ts +3 -3
- package/lib/encoder/Encoder.js +10 -11
- package/lib/encoder/Encoder.js.map +1 -1
- package/lib/encoder/StateView.d.ts +2 -2
- package/lib/encoder/StateView.js +45 -60
- package/lib/encoder/StateView.js.map +1 -1
- package/package.json +1 -1
- package/src/Reflection.ts +1 -3
- package/src/Schema.ts +2 -2
- package/src/annotations.ts +16 -5
- package/src/decoder/DecodeOperation.ts +4 -1
- package/src/decoder/Decoder.ts +3 -2
- package/src/decoder/strategy/StateCallbacks.ts +30 -20
- package/src/encoder/ChangeTree.ts +4 -2
- package/src/encoder/Encoder.ts +11 -13
- package/src/encoder/StateView.ts +50 -69
package/build/cjs/index.js
CHANGED
|
@@ -329,7 +329,7 @@ class ChangeTree {
|
|
|
329
329
|
// MapSchema / ArraySchema, etc.
|
|
330
330
|
this.ref.forEach((value, key) => {
|
|
331
331
|
if (Metadata.isValidInstance(value)) {
|
|
332
|
-
callback(value[$changes], this.ref[$changes].indexes[key]);
|
|
332
|
+
callback(value[$changes], this.ref[$changes].indexes[key] ?? key);
|
|
333
333
|
}
|
|
334
334
|
});
|
|
335
335
|
}
|
|
@@ -357,8 +357,9 @@ class ChangeTree {
|
|
|
357
357
|
// TODO: are DELETE operations being encoded as ADD here ??
|
|
358
358
|
//
|
|
359
359
|
if (isFiltered) {
|
|
360
|
-
this.allFilteredChanges.set(index, exports.OPERATION.ADD);
|
|
361
360
|
this.root?.filteredChanges.set(this, this.filteredChanges);
|
|
361
|
+
this.allFilteredChanges.set(index, exports.OPERATION.ADD);
|
|
362
|
+
this.root?.allFilteredChanges.set(this, this.allFilteredChanges);
|
|
362
363
|
}
|
|
363
364
|
else {
|
|
364
365
|
this.allChanges.set(index, exports.OPERATION.ADD);
|
|
@@ -1405,6 +1406,7 @@ const decodeSchemaOperation = function (decoder, bytes, it, ref, allChanges) {
|
|
|
1405
1406
|
// skip early if field is not defined
|
|
1406
1407
|
const field = metadata[index];
|
|
1407
1408
|
if (field === undefined) {
|
|
1409
|
+
console.warn("@colyseus/schema: field not defined at", { index, ref: ref.constructor.name, metadata });
|
|
1408
1410
|
return DEFINITION_MISMATCH;
|
|
1409
1411
|
}
|
|
1410
1412
|
const { value, previousValue } = decodeValue(decoder, operation, ref, index, metadata[field].type, bytes, it, allChanges);
|
|
@@ -2427,13 +2429,13 @@ class TypeContext {
|
|
|
2427
2429
|
getTypeId(klass) {
|
|
2428
2430
|
return this.schemas.get(klass);
|
|
2429
2431
|
}
|
|
2430
|
-
discoverTypes(klass) {
|
|
2432
|
+
discoverTypes(klass, parentFieldViewTag) {
|
|
2431
2433
|
if (!this.add(klass)) {
|
|
2432
2434
|
return;
|
|
2433
2435
|
}
|
|
2434
2436
|
// add classes inherited from this base class
|
|
2435
2437
|
TypeContext.inheritedTypes.get(klass)?.forEach((child) => {
|
|
2436
|
-
this.discoverTypes(child);
|
|
2438
|
+
this.discoverTypes(child, parentFieldViewTag);
|
|
2437
2439
|
});
|
|
2438
2440
|
// skip if no fields are defined for this class.
|
|
2439
2441
|
if (klass[Symbol.metadata] === undefined) {
|
|
@@ -2446,7 +2448,15 @@ class TypeContext {
|
|
|
2446
2448
|
this.hasFilters = true;
|
|
2447
2449
|
}
|
|
2448
2450
|
for (const field in metadata) {
|
|
2451
|
+
//
|
|
2452
|
+
// Modify the field's metadata to include the parent field's view tag
|
|
2453
|
+
//
|
|
2454
|
+
if (parentFieldViewTag !== undefined &&
|
|
2455
|
+
metadata[field].tag === undefined) {
|
|
2456
|
+
metadata[field].tag = parentFieldViewTag;
|
|
2457
|
+
}
|
|
2449
2458
|
const fieldType = metadata[field].type;
|
|
2459
|
+
const viewTag = metadata[field].tag;
|
|
2450
2460
|
if (typeof (fieldType) === "string") {
|
|
2451
2461
|
continue;
|
|
2452
2462
|
}
|
|
@@ -2455,10 +2465,10 @@ class TypeContext {
|
|
|
2455
2465
|
if (type === "string") {
|
|
2456
2466
|
continue;
|
|
2457
2467
|
}
|
|
2458
|
-
this.discoverTypes(type);
|
|
2468
|
+
this.discoverTypes(type, viewTag);
|
|
2459
2469
|
}
|
|
2460
2470
|
else if (typeof (fieldType) === "function") {
|
|
2461
|
-
this.discoverTypes(fieldType);
|
|
2471
|
+
this.discoverTypes(fieldType, viewTag);
|
|
2462
2472
|
}
|
|
2463
2473
|
else {
|
|
2464
2474
|
const type = Object.values(fieldType)[0];
|
|
@@ -2466,7 +2476,7 @@ class TypeContext {
|
|
|
2466
2476
|
if (typeof (type) === "string") {
|
|
2467
2477
|
continue;
|
|
2468
2478
|
}
|
|
2469
|
-
this.discoverTypes(type);
|
|
2479
|
+
this.discoverTypes(type, viewTag);
|
|
2470
2480
|
}
|
|
2471
2481
|
}
|
|
2472
2482
|
}
|
|
@@ -3025,13 +3035,13 @@ class Schema {
|
|
|
3025
3035
|
}
|
|
3026
3036
|
return output;
|
|
3027
3037
|
}
|
|
3028
|
-
static debugChangesDeep(ref) {
|
|
3038
|
+
static debugChangesDeep(ref, changeSetName = "changes") {
|
|
3029
3039
|
let output = "";
|
|
3030
3040
|
const rootChangeTree = ref[$changes];
|
|
3031
3041
|
const changeTrees = new Map();
|
|
3032
3042
|
let totalInstances = 0;
|
|
3033
3043
|
let totalOperations = 0;
|
|
3034
|
-
for (const [changeTree, changes] of (rootChangeTree.root.
|
|
3044
|
+
for (const [changeTree, changes] of (rootChangeTree.root[changeSetName].entries())) {
|
|
3035
3045
|
let includeChangeTree = false;
|
|
3036
3046
|
let parentChangeTrees = [];
|
|
3037
3047
|
let parentChangeTree = changeTree.parent?.[$changes];
|
|
@@ -3434,26 +3444,26 @@ typeof SuppressedError === "function" ? SuppressedError : function (error, suppr
|
|
|
3434
3444
|
|
|
3435
3445
|
class Encoder {
|
|
3436
3446
|
static { this.BUFFER_SIZE = 8 * 1024; } // 8KB
|
|
3437
|
-
constructor(
|
|
3447
|
+
constructor(state) {
|
|
3438
3448
|
this.sharedBuffer = Buffer.allocUnsafeSlow(Encoder.BUFFER_SIZE);
|
|
3449
|
+
this.root = new Root();
|
|
3439
3450
|
//
|
|
3440
3451
|
// TODO: cache and restore "Context" based on root schema
|
|
3441
3452
|
// (to avoid creating a new context for every new room)
|
|
3442
3453
|
//
|
|
3443
|
-
this.context = new TypeContext(
|
|
3444
|
-
this.
|
|
3454
|
+
this.context = new TypeContext(state.constructor);
|
|
3455
|
+
this.setState(state);
|
|
3445
3456
|
// console.log(">>>>>>>>>>>>>>>> Encoder types");
|
|
3446
3457
|
// this.context.schemas.forEach((id, schema) => {
|
|
3447
3458
|
// console.log("type:", id, schema.name, Object.keys(schema[Symbol.metadata]));
|
|
3448
3459
|
// });
|
|
3449
3460
|
}
|
|
3450
|
-
|
|
3451
|
-
this.root = new Root();
|
|
3461
|
+
setState(state) {
|
|
3452
3462
|
this.state = state;
|
|
3453
|
-
state[$changes].setRoot(this.root);
|
|
3463
|
+
this.state[$changes].setRoot(this.root);
|
|
3454
3464
|
}
|
|
3455
|
-
encode(it = { offset: 0 }, view, buffer = this.sharedBuffer, changeTrees = this.root.changes, isEncodeAll = this.root.allChanges === changeTrees
|
|
3456
|
-
|
|
3465
|
+
encode(it = { offset: 0 }, view, buffer = this.sharedBuffer, changeTrees = this.root.changes, isEncodeAll = this.root.allChanges === changeTrees, initialOffset = it.offset // cache current offset in case we need to resize the buffer
|
|
3466
|
+
) {
|
|
3457
3467
|
const hasView = (view !== undefined);
|
|
3458
3468
|
const rootChangeTree = this.state[$changes];
|
|
3459
3469
|
const changeTreesIterator = changeTrees.entries();
|
|
@@ -3492,7 +3502,6 @@ class Encoder {
|
|
|
3492
3502
|
// TODO: avoid checking if no view tags were defined
|
|
3493
3503
|
//
|
|
3494
3504
|
if (filter && !filter(ref, fieldIndex, view)) {
|
|
3495
|
-
// console.log("SKIP FIELD:", { ref: changeTree.ref.constructor.name, fieldIndex, })
|
|
3496
3505
|
// console.log("ADD AS INVISIBLE:", fieldIndex, changeTree.ref.constructor.name)
|
|
3497
3506
|
// view?.invisible.add(changeTree);
|
|
3498
3507
|
continue;
|
|
@@ -3570,8 +3579,6 @@ class Encoder {
|
|
|
3570
3579
|
}
|
|
3571
3580
|
encodeView(view, sharedOffset, it, bytes = this.sharedBuffer) {
|
|
3572
3581
|
const viewOffset = it.offset;
|
|
3573
|
-
// try to encode "filtered" changes
|
|
3574
|
-
this.encode(it, view, bytes, this.root.filteredChanges);
|
|
3575
3582
|
// encode visibility changes (add/remove for this view)
|
|
3576
3583
|
const viewChangesIterator = view.changes.entries();
|
|
3577
3584
|
for (const [changeTree, changes] of viewChangesIterator) {
|
|
@@ -3598,6 +3605,8 @@ class Encoder {
|
|
|
3598
3605
|
//
|
|
3599
3606
|
// clear "view" changes after encoding
|
|
3600
3607
|
view.changes.clear();
|
|
3608
|
+
// try to encode "filtered" changes
|
|
3609
|
+
this.encode(it, view, bytes, this.root.filteredChanges, false, viewOffset);
|
|
3601
3610
|
return Buffer.concat([
|
|
3602
3611
|
bytes.subarray(0, sharedOffset),
|
|
3603
3612
|
bytes.subarray(viewOffset, it.offset)
|
|
@@ -3770,14 +3779,14 @@ class ReferenceTracker {
|
|
|
3770
3779
|
class Decoder {
|
|
3771
3780
|
constructor(root, context) {
|
|
3772
3781
|
this.currentRefId = 0;
|
|
3773
|
-
this.
|
|
3782
|
+
this.setState(root);
|
|
3774
3783
|
this.context = context || new TypeContext(root.constructor);
|
|
3775
3784
|
// console.log(">>>>>>>>>>>>>>>> Decoder types");
|
|
3776
3785
|
// this.context.schemas.forEach((id, schema) => {
|
|
3777
3786
|
// console.log("type:", id, schema.name, Object.keys(schema[Symbol.metadata]));
|
|
3778
3787
|
// });
|
|
3779
3788
|
}
|
|
3780
|
-
|
|
3789
|
+
setState(root) {
|
|
3781
3790
|
this.state = root;
|
|
3782
3791
|
this.root = new ReferenceTracker();
|
|
3783
3792
|
this.root.addRef(0, root);
|
|
@@ -3906,9 +3915,7 @@ class Reflection extends Schema {
|
|
|
3906
3915
|
this.types = new ArraySchema();
|
|
3907
3916
|
}
|
|
3908
3917
|
static encode(instance, context, it = { offset: 0 }) {
|
|
3909
|
-
|
|
3910
|
-
context = new TypeContext(instance.constructor);
|
|
3911
|
-
}
|
|
3918
|
+
context ??= new TypeContext(instance.constructor);
|
|
3912
3919
|
const reflection = new Reflection();
|
|
3913
3920
|
const encoder = new Encoder(reflection);
|
|
3914
3921
|
const buildType = (currentType, metadata) => {
|
|
@@ -4032,7 +4039,8 @@ __decorate([
|
|
|
4032
4039
|
function getDecoderStateCallbacks(decoder) {
|
|
4033
4040
|
const $root = decoder.root;
|
|
4034
4041
|
const callbacks = $root.callbacks;
|
|
4035
|
-
|
|
4042
|
+
const onAddCalls = new WeakMap();
|
|
4043
|
+
let currentOnAddCallback;
|
|
4036
4044
|
decoder.triggerChanges = function (allChanges) {
|
|
4037
4045
|
const uniqueRefIds = new Set();
|
|
4038
4046
|
for (let i = 0, l = allChanges.length; i < l; i++) {
|
|
@@ -4095,7 +4103,6 @@ function getDecoderStateCallbacks(decoder) {
|
|
|
4095
4103
|
}
|
|
4096
4104
|
}
|
|
4097
4105
|
// Handle DELETE_AND_ADD operations
|
|
4098
|
-
// FIXME: should we set "isTriggeringOnAdd" here?
|
|
4099
4106
|
if ((change.op & exports.OPERATION.ADD) === exports.OPERATION.ADD) {
|
|
4100
4107
|
const addCallbacks = $callbacks[exports.OPERATION.ADD];
|
|
4101
4108
|
for (let i = addCallbacks?.length - 1; i >= 0; i--) {
|
|
@@ -4105,12 +4112,10 @@ function getDecoderStateCallbacks(decoder) {
|
|
|
4105
4112
|
}
|
|
4106
4113
|
else if ((change.op & exports.OPERATION.ADD) === exports.OPERATION.ADD && change.previousValue === undefined) {
|
|
4107
4114
|
// triger onAdd
|
|
4108
|
-
isTriggeringOnAdd = true;
|
|
4109
4115
|
const addCallbacks = $callbacks[exports.OPERATION.ADD];
|
|
4110
4116
|
for (let i = addCallbacks?.length - 1; i >= 0; i--) {
|
|
4111
4117
|
addCallbacks[i](change.value, change.dynamicIndex ?? change.field);
|
|
4112
4118
|
}
|
|
4113
|
-
isTriggeringOnAdd = false;
|
|
4114
4119
|
}
|
|
4115
4120
|
// trigger onChange
|
|
4116
4121
|
if (change.value !== change.previousValue) {
|
|
@@ -4132,7 +4137,7 @@ function getDecoderStateCallbacks(decoder) {
|
|
|
4132
4137
|
// immediate trigger
|
|
4133
4138
|
if (immediate &&
|
|
4134
4139
|
context.instance[prop] !== undefined &&
|
|
4135
|
-
!
|
|
4140
|
+
!onAddCalls.has(callback) // Workaround for https://github.com/colyseus/schema/issues/147
|
|
4136
4141
|
) {
|
|
4137
4142
|
callback(context.instance[prop], undefined);
|
|
4138
4143
|
}
|
|
@@ -4158,10 +4163,11 @@ function getDecoderStateCallbacks(decoder) {
|
|
|
4158
4163
|
onChange: function onChange(callback) {
|
|
4159
4164
|
return $root.addCallback($root.refIds.get(context.instance), exports.OPERATION.REPLACE, callback);
|
|
4160
4165
|
},
|
|
4166
|
+
//
|
|
4167
|
+
// TODO: refactor `bindTo()` implementation.
|
|
4168
|
+
// There is room for improvement.
|
|
4169
|
+
//
|
|
4161
4170
|
bindTo: function bindTo(targetObject, properties) {
|
|
4162
|
-
//
|
|
4163
|
-
// TODO: refactor this implementation. There is room for improvement here.
|
|
4164
|
-
//
|
|
4165
4171
|
if (!properties) {
|
|
4166
4172
|
properties = Object.keys(metadata);
|
|
4167
4173
|
}
|
|
@@ -4188,7 +4194,8 @@ function getDecoderStateCallbacks(decoder) {
|
|
|
4188
4194
|
}
|
|
4189
4195
|
});
|
|
4190
4196
|
return getProxy(metadata[prop].type, {
|
|
4191
|
-
instance
|
|
4197
|
+
// make sure refId is available, otherwise need to wait for the instance to be available.
|
|
4198
|
+
instance: ($root.refIds.get(instance) && instance),
|
|
4192
4199
|
parentInstance: context.instance,
|
|
4193
4200
|
onInstanceAvailable,
|
|
4194
4201
|
});
|
|
@@ -4212,7 +4219,12 @@ function getDecoderStateCallbacks(decoder) {
|
|
|
4212
4219
|
if (immediate) {
|
|
4213
4220
|
ref.forEach((v, k) => callback(v, k));
|
|
4214
4221
|
}
|
|
4215
|
-
return $root.addCallback($root.refIds.get(ref), exports.OPERATION.ADD,
|
|
4222
|
+
return $root.addCallback($root.refIds.get(ref), exports.OPERATION.ADD, (value, key) => {
|
|
4223
|
+
onAddCalls.set(callback, true);
|
|
4224
|
+
currentOnAddCallback = callback;
|
|
4225
|
+
callback(value, key);
|
|
4226
|
+
onAddCalls.delete(callback);
|
|
4227
|
+
});
|
|
4216
4228
|
};
|
|
4217
4229
|
const onRemove = function (ref, callback) {
|
|
4218
4230
|
return $root.addCallback($root.refIds.get(ref), exports.OPERATION.DELETE, callback);
|
|
@@ -4223,19 +4235,17 @@ function getDecoderStateCallbacks(decoder) {
|
|
|
4223
4235
|
// https://github.com/colyseus/schema/issues/147
|
|
4224
4236
|
// If parent instance has "onAdd" registered, avoid triggering immediate callback.
|
|
4225
4237
|
//
|
|
4226
|
-
|
|
4227
|
-
|
|
4228
|
-
|
|
4238
|
+
if (context.instance) {
|
|
4239
|
+
return onAdd(context.instance, callback, immediate && !onAddCalls.has(currentOnAddCallback));
|
|
4240
|
+
}
|
|
4241
|
+
else if (context.onInstanceAvailable) {
|
|
4229
4242
|
// collection instance not received yet
|
|
4230
4243
|
let detachCallback = () => { };
|
|
4231
4244
|
context.onInstanceAvailable((ref, existing) => {
|
|
4232
|
-
detachCallback = onAdd(ref, callback, immediate && existing && !
|
|
4245
|
+
detachCallback = onAdd(ref, callback, immediate && existing && !onAddCalls.has(currentOnAddCallback));
|
|
4233
4246
|
});
|
|
4234
4247
|
return () => detachCallback();
|
|
4235
4248
|
}
|
|
4236
|
-
else if (context.instance) {
|
|
4237
|
-
return onAdd(context.instance, callback, immediate && !isTriggeringOnAdd);
|
|
4238
|
-
}
|
|
4239
4249
|
},
|
|
4240
4250
|
onRemove: function (callback) {
|
|
4241
4251
|
if (context.onInstanceAvailable) {
|
|
@@ -4290,26 +4300,21 @@ class StateView {
|
|
|
4290
4300
|
this.changes = new Map();
|
|
4291
4301
|
}
|
|
4292
4302
|
// TODO: allow to set multiple tags at once
|
|
4293
|
-
add(obj, tag = DEFAULT_VIEW_TAG) {
|
|
4303
|
+
add(obj, tag = DEFAULT_VIEW_TAG, checkIncludeParent = true) {
|
|
4294
4304
|
if (!obj[$changes]) {
|
|
4295
4305
|
console.warn("StateView#add(), invalid object:", obj);
|
|
4296
4306
|
return this;
|
|
4297
4307
|
}
|
|
4298
4308
|
// FIXME: ArraySchema/MapSchema does not have metadata
|
|
4299
4309
|
const metadata = obj.constructor[Symbol.metadata];
|
|
4300
|
-
|
|
4310
|
+
const changeTree = obj[$changes];
|
|
4301
4311
|
this.items.add(changeTree);
|
|
4302
|
-
//
|
|
4303
|
-
|
|
4304
|
-
|
|
4305
|
-
|
|
4306
|
-
|
|
4307
|
-
|
|
4308
|
-
this.add(change.ref, tag);
|
|
4309
|
-
});
|
|
4310
|
-
// add parent ChangeTree's, if they are invisible to this view
|
|
4311
|
-
// TODO: REFACTOR addParent()
|
|
4312
|
-
this.addParent(changeTree, tag);
|
|
4312
|
+
// add parent ChangeTree's
|
|
4313
|
+
// - if it was invisible to this view
|
|
4314
|
+
// - if it were previously filtered out
|
|
4315
|
+
if (checkIncludeParent && changeTree.parent) {
|
|
4316
|
+
this.addParent(changeTree.parent[$changes], changeTree.parentIndex, tag);
|
|
4317
|
+
}
|
|
4313
4318
|
//
|
|
4314
4319
|
// TODO: when adding an item of a MapSchema, the changes may not
|
|
4315
4320
|
// be set (only the parent's changes are set)
|
|
@@ -4341,73 +4346,63 @@ class StateView {
|
|
|
4341
4346
|
});
|
|
4342
4347
|
}
|
|
4343
4348
|
else {
|
|
4344
|
-
|
|
4345
|
-
|
|
4346
|
-
// metadata?.[-3]?.[DEFAULT_VIEW_TAG]?.forEach((index) => {
|
|
4347
|
-
// if (changeTree.getChange(index) !== OPERATION.DELETE) {
|
|
4348
|
-
// changes.set(index, OPERATION.ADD);
|
|
4349
|
-
// }
|
|
4350
|
-
// });
|
|
4351
|
-
const allChangesSet = (changeTree.isFiltered || changeTree.isPartiallyFiltered)
|
|
4349
|
+
const isInvisible = this.invisible.has(changeTree);
|
|
4350
|
+
const changeSet = (changeTree.isFiltered || changeTree.isPartiallyFiltered)
|
|
4352
4351
|
? changeTree.allFilteredChanges
|
|
4353
4352
|
: changeTree.allChanges;
|
|
4354
|
-
|
|
4355
|
-
|
|
4356
|
-
|
|
4357
|
-
|
|
4358
|
-
|
|
4359
|
-
|
|
4353
|
+
changeSet.forEach((op, index) => {
|
|
4354
|
+
const tagAtIndex = metadata?.[metadata?.[index]].tag;
|
|
4355
|
+
if ((isInvisible || // if "invisible", include all
|
|
4356
|
+
tagAtIndex === undefined || // "all change" with no tag
|
|
4357
|
+
tagAtIndex === tag // tagged property
|
|
4358
|
+
) &&
|
|
4359
|
+
op !== exports.OPERATION.DELETE) {
|
|
4360
|
+
changes.set(index, op);
|
|
4360
4361
|
}
|
|
4361
|
-
}
|
|
4362
|
-
}
|
|
4363
|
-
// TODO: avoid unnecessary iteration here
|
|
4364
|
-
while (changeTree.parent &&
|
|
4365
|
-
(changeTree = changeTree.parent[$changes]) &&
|
|
4366
|
-
(changeTree.isFiltered || changeTree.isPartiallyFiltered)) {
|
|
4367
|
-
this.items.add(changeTree);
|
|
4362
|
+
});
|
|
4368
4363
|
}
|
|
4364
|
+
// Add children of this ChangeTree to this view
|
|
4365
|
+
changeTree.forEachChild((change, index) => {
|
|
4366
|
+
// Do not ADD children that don't have the same tag
|
|
4367
|
+
if (metadata && metadata[metadata[index]].tag !== tag) {
|
|
4368
|
+
return;
|
|
4369
|
+
}
|
|
4370
|
+
this.add(change.ref, tag, false);
|
|
4371
|
+
});
|
|
4369
4372
|
return this;
|
|
4370
4373
|
}
|
|
4371
|
-
addParent(changeTree, tag) {
|
|
4372
|
-
|
|
4373
|
-
|
|
4374
|
-
|
|
4374
|
+
addParent(changeTree, parentIndex, tag) {
|
|
4375
|
+
// view must have all "changeTree" parent tree
|
|
4376
|
+
this.items.add(changeTree);
|
|
4377
|
+
// add parent's parent
|
|
4378
|
+
const parentChangeTree = changeTree.parent?.[$changes];
|
|
4379
|
+
if (parentChangeTree && (parentChangeTree.isFiltered || parentChangeTree.isPartiallyFiltered)) {
|
|
4380
|
+
this.addParent(parentChangeTree, changeTree.parentIndex, tag);
|
|
4375
4381
|
}
|
|
4376
|
-
|
|
4377
|
-
|
|
4378
|
-
if (!this.invisible.has(parentChangeTree)) {
|
|
4379
|
-
// parent is already available, no need to add it!
|
|
4382
|
+
// parent is already available, no need to add it!
|
|
4383
|
+
if (!this.invisible.has(changeTree)) {
|
|
4380
4384
|
return;
|
|
4381
4385
|
}
|
|
4382
|
-
this.addParent(parentChangeTree, tag);
|
|
4383
4386
|
// add parent's tag properties
|
|
4384
|
-
if (
|
|
4385
|
-
let
|
|
4386
|
-
if (
|
|
4387
|
-
|
|
4388
|
-
this.changes.set(
|
|
4387
|
+
if (changeTree.getChange(parentIndex) !== exports.OPERATION.DELETE) {
|
|
4388
|
+
let changes = this.changes.get(changeTree);
|
|
4389
|
+
if (changes === undefined) {
|
|
4390
|
+
changes = new Map();
|
|
4391
|
+
this.changes.set(changeTree, changes);
|
|
4389
4392
|
}
|
|
4390
|
-
// console.log("add parent change", {
|
|
4391
|
-
// parentIndex,
|
|
4392
|
-
// parentChanges,
|
|
4393
|
-
// parentChange: (
|
|
4394
|
-
// parentChangeTree.getChange(parentIndex) &&
|
|
4395
|
-
// OPERATION[parentChangeTree.getChange(parentIndex)]
|
|
4396
|
-
// ),
|
|
4397
|
-
// })
|
|
4398
4393
|
if (!this.tags) {
|
|
4399
4394
|
this.tags = new WeakMap();
|
|
4400
4395
|
}
|
|
4401
4396
|
let tags;
|
|
4402
|
-
if (!this.tags.has(
|
|
4397
|
+
if (!this.tags.has(changeTree)) {
|
|
4403
4398
|
tags = new Set();
|
|
4404
|
-
this.tags.set(
|
|
4399
|
+
this.tags.set(changeTree, tags);
|
|
4405
4400
|
}
|
|
4406
4401
|
else {
|
|
4407
|
-
tags = this.tags.get(
|
|
4402
|
+
tags = this.tags.get(changeTree);
|
|
4408
4403
|
}
|
|
4409
4404
|
tags.add(tag);
|
|
4410
|
-
|
|
4405
|
+
changes.set(parentIndex, exports.OPERATION.ADD);
|
|
4411
4406
|
}
|
|
4412
4407
|
}
|
|
4413
4408
|
remove(obj, tag = DEFAULT_VIEW_TAG) {
|