Fix array un-observe
This commit is contained in:
parent
c506f8d98e
commit
0039ecdd4f
@ -81,6 +81,11 @@ export default class uObserve {
|
|||||||
}
|
}
|
||||||
if (this.isObserved(obj, property)) {
|
if (this.isObserved(obj, property)) {
|
||||||
obj._values[property] = value;
|
obj._values[property] = value;
|
||||||
|
if (Array.isArray(obj[property])) {
|
||||||
|
for (const obs of obj._observers[property]) {
|
||||||
|
this.observeArray(obj[property], obs);
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
obj[property] = value;
|
obj[property] = value;
|
||||||
}
|
}
|
||||||
@ -110,7 +115,7 @@ export default class uObserve {
|
|||||||
uObserve.notify(obj._observers[property], newValue);
|
uObserve.notify(obj._observers[property], newValue);
|
||||||
}
|
}
|
||||||
if (Array.isArray(obj[property])) {
|
if (Array.isArray(obj[property])) {
|
||||||
this.observeArray(obj[property], observer);
|
this.observeArray(obj[property], obj._observers[property]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -139,21 +144,17 @@ export default class uObserve {
|
|||||||
/**
|
/**
|
||||||
* Observe array
|
* Observe array
|
||||||
* @param {Object} arr
|
* @param {Object} arr
|
||||||
* @param {ObserveCallback} observer
|
* @param {(ObserveCallback|Set<ObserveCallback>)} observer
|
||||||
*/
|
*/
|
||||||
static observeArray(arr, observer) {
|
static observeArray(arr, observer) {
|
||||||
this.addObserver(arr, observer);
|
if (observer instanceof Set) {
|
||||||
[ 'pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift' ].forEach(
|
for (const obs of observer) {
|
||||||
(operation) => {
|
this.addObserver(arr, obs);
|
||||||
const descriptor = Object.getOwnPropertyDescriptor(Array.prototype, operation);
|
}
|
||||||
descriptor.value = function () {
|
} else {
|
||||||
const result = Array.prototype[operation].apply(arr, arguments);
|
this.addObserver(arr, observer);
|
||||||
console.log(`[${operation}] ` + (arr.length ? `[${arr[0]}, …](${arr.length})` : arr));
|
}
|
||||||
uObserve.notify(arr._observers, arr);
|
this.overrideArrayPrototypes(arr, arguments);
|
||||||
return result;
|
|
||||||
};
|
|
||||||
Object.defineProperty(arr, operation, descriptor);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -271,11 +272,32 @@ export default class uObserve {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static restoreArrayPrototypes(arr) {
|
/**
|
||||||
|
* @param {Object} arr
|
||||||
|
*/
|
||||||
|
static overrideArrayPrototypes(arr) {
|
||||||
[ 'pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift' ].forEach(
|
[ 'pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift' ].forEach(
|
||||||
(operation) => {
|
(operation) => {
|
||||||
const descriptor = Object.getOwnPropertyDescriptor(Array.prototype, operation);
|
const descriptor = Object.getOwnPropertyDescriptor(Array.prototype, operation);
|
||||||
Object.defineProperty(arr, operation, descriptor);
|
if (!arr.hasOwnProperty(operation)) {
|
||||||
|
descriptor.value = function () {
|
||||||
|
const result = Array.prototype[operation].apply(arr, arguments);
|
||||||
|
console.log(`[${operation}] ` + (arr.length ? `[${arr[0]}, …](${arr.length})` : arr));
|
||||||
|
uObserve.notify(arr._observers, arr);
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
Object.defineProperty(arr, operation, descriptor);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {Object} arr
|
||||||
|
*/
|
||||||
|
static restoreArrayPrototypes(arr) {
|
||||||
|
[ 'pop', 'push', 'reverse', 'shift', 'sort', 'splice', 'unshift' ].forEach(
|
||||||
|
(operation) => {
|
||||||
|
delete arr[operation];
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -157,6 +157,8 @@ describe('Observe tests', () => {
|
|||||||
|
|
||||||
it('should retain observers after array is reassigned', () => {
|
it('should retain observers after array is reassigned', () => {
|
||||||
// given
|
// given
|
||||||
|
let result2 = false;
|
||||||
|
let resultValue2;
|
||||||
const array = [ 1, 2 ];
|
const array = [ 1, 2 ];
|
||||||
const newArray = [ 3, 4 ];
|
const newArray = [ 3, 4 ];
|
||||||
object = { array: array };
|
object = { array: array };
|
||||||
@ -164,15 +166,56 @@ describe('Observe tests', () => {
|
|||||||
result = true;
|
result = true;
|
||||||
resultValue = value;
|
resultValue = value;
|
||||||
});
|
});
|
||||||
|
uObserve.observe(object, 'array', (value) => {
|
||||||
|
result2 = true;
|
||||||
|
resultValue2 = value;
|
||||||
|
});
|
||||||
// when
|
// when
|
||||||
object.array = newArray;
|
object.array = newArray;
|
||||||
result = false;
|
result = false;
|
||||||
|
result2 = false;
|
||||||
|
|
||||||
expect(result).toBe(false);
|
expect(result).toBe(false);
|
||||||
|
expect(result2).toBe(false);
|
||||||
object.array.push(5);
|
object.array.push(5);
|
||||||
// then
|
// then
|
||||||
expect(result).toBe(true);
|
expect(result).toBe(true);
|
||||||
|
expect(result2).toBe(true);
|
||||||
expect(resultValue).toEqual(newArray);
|
expect(resultValue).toEqual(newArray);
|
||||||
|
// noinspection JSUnusedAssignment
|
||||||
|
expect(resultValue2).toEqual(newArray);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should retain observers after array property is silently set', () => {
|
||||||
|
// given
|
||||||
|
let result2 = false;
|
||||||
|
let resultValue2;
|
||||||
|
const array = [ 1, 2 ];
|
||||||
|
const newArray = [ 3, 4 ];
|
||||||
|
object = { array: [] };
|
||||||
|
uObserve.observe(object, 'array', (value) => {
|
||||||
|
result = true;
|
||||||
|
resultValue = value;
|
||||||
|
});
|
||||||
|
uObserve.observe(object, 'array', (value) => {
|
||||||
|
result2 = true;
|
||||||
|
resultValue2 = value;
|
||||||
|
});
|
||||||
|
// when
|
||||||
|
uObserve.setSilently(object, 'array', array);
|
||||||
|
object.array = newArray;
|
||||||
|
result = false;
|
||||||
|
result2 = false;
|
||||||
|
|
||||||
|
expect(result).toBe(false);
|
||||||
|
expect(result2).toBe(false);
|
||||||
|
object.array.push(5);
|
||||||
|
// then
|
||||||
|
expect(result).toBe(true);
|
||||||
|
expect(result2).toBe(true);
|
||||||
|
expect(resultValue).toEqual(newArray);
|
||||||
|
// noinspection JSUnusedAssignment
|
||||||
|
expect(resultValue2).toEqual(newArray);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user