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