Skip to content

Commit

Permalink
Add method name to callback parameters (#56)
Browse files Browse the repository at this point in the history
  • Loading branch information
DarrenPaulWright committed Aug 12, 2020
1 parent 19ca0f5 commit 26d431a
Show file tree
Hide file tree
Showing 4 changed files with 86 additions and 39 deletions.
26 changes: 24 additions & 2 deletions index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -112,12 +112,13 @@ declare const onChange: {
};
let i = 0;
const watchedObject = onChange(object, function (path, value, previousValue) {
const watchedObject = onChange(object, function (path, value, previousValue, name) {
console.log('Object changed:', ++i);
console.log('this:', this);
console.log('path:', path);
console.log('value:', value);
console.log('previousValue:', previousValue);
console.log('name:', name);
});
watchedObject.foo = true;
Expand All @@ -135,6 +136,7 @@ declare const onChange: {
//=> 'path: "foo"'
//=> 'value: true'
//=> 'previousValue: false'
//=> 'name: undefined'
watchedObject.a.b[0].c = true;
//=> 'Object changed: 2'
Expand All @@ -151,6 +153,25 @@ declare const onChange: {
//=> 'path: "a.b.0.c"'
//=> 'value: true'
//=> 'previousValue: false'
//=> 'name: undefined'
watchedObject.a.b.push(3);
//=> 'Object changed: 3'
//=> 'this: {
// foo: true,
// a: {
// b: [
// {
// c: true
// },
// 3
// ]
// }
// }'
//=> 'path: "a.b"'
//=> 'value: [{c: true}, 3]'
//=> 'previousValue: [{c: true}]'
//=> 'name: "push"'
// Access the original object
onChange.target(watchedObject).foo = false;
Expand All @@ -168,7 +189,8 @@ declare const onChange: {
this: ObjectType,
path: string,
value: unknown,
previousValue: unknown
previousValue: unknown,
name: string
) => void,
options?: onChange.Options
): ObjectType;
Expand Down
7 changes: 4 additions & 3 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,12 @@ const onChange = (object, onChange, options = {}) => {
}
};

const handleChange = (changePath, property, previous, value) => {
// eslint-disable-next-line max-params
const handleChange = (changePath, property, previous, value, name) => {
if (smartClone.isCloning) {
smartClone.update(changePath, property, previous);
} else {
onChange(path.concat(changePath, property), value, previous);
onChange(path.concat(changePath, property), value, previous, name);
}
};

Expand Down Expand Up @@ -142,7 +143,7 @@ const onChange = (object, onChange, options = {}) => {

if (smartClone.isChanged(isMutable, thisArg, equals)) {
const clone = smartClone.done();
handleChange(applyPath, '', clone, thisProxyTarget);
handleChange(applyPath, '', clone, thisProxyTarget, target.name);
}

smartClone.done();
Expand Down
26 changes: 24 additions & 2 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,13 @@ const object = {
};

let i = 0;
const watchedObject = onChange(object, function (path, value, previousValue) {
const watchedObject = onChange(object, function (path, value, previousValue, name) {
console.log('Object changed:', ++i);
console.log('this:', this);
console.log('path:', path);
console.log('value:', value);
console.log('previousValue:', previousValue);
console.log('name:', name);
});

watchedObject.foo = true;
Expand All @@ -52,6 +53,7 @@ watchedObject.foo = true;
//=> 'path: "foo"'
//=> 'value: true'
//=> 'previousValue: false'
//=> 'name: undefined'

watchedObject.a.b[0].c = true;
//=> 'Object changed: 2'
Expand All @@ -68,6 +70,25 @@ watchedObject.a.b[0].c = true;
//=> 'path: "a.b.0.c"'
//=> 'value: true'
//=> 'previousValue: false'
//=> 'name: undefined'

watchedObject.a.b.push(3);
//=> 'Object changed: 3'
//=> 'this: {
// foo: true,
// a: {
// b: [
// {
// c: true
// },
// 3
// ]
// }
// }'
//=> 'path: "a.b"'
//=> 'value: [{c: true}, 3]'
//=> 'previousValue: [{c: true}]'
//=> 'name: "push"'

// Access the original object
onChange.target(watchedObject).foo = false;
Expand Down Expand Up @@ -97,10 +118,11 @@ Type: `Function`

Function that gets called anytime the object changes.

The function receives three arguments:
The function receives four arguments:
1. A path to the value that was changed. A change to `c` in the above example would return `a.b.0.c`.
2. The new value at the path.
3. The previous value at the path.
4. The name of the method that produced the change.

The context (this) is set to the original object passed to `onChange` (with Proxy).

Expand Down
66 changes: 34 additions & 32 deletions tests/on-change.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,21 +16,23 @@ const testHelper = (t, object, options, callback) => {

reset();

const proxy = onChange(object, function (path, value, previous) {
const proxy = onChange(object, function (path, value, previous, name) {
last.count++;
last.thisArg = this;
last.path = path;
last.value = value;
last.previous = previous;
last.name = name;
}, options);

// eslint-disable-next-line max-params
const verify = (count, thisArg, path, value, previous, fullObject) => {
const verify = (count, thisArg, path, value, previous, name, fullObject) => {
t.is(count, last.count);
t.is(thisArg, last.thisArg);
t.deepEqual(path, last.path);
t.deepEqual(value, last.value);
t.deepEqual(previous, last.previous);
t.is(name, last.name);

t.is(object, onChange.target(proxy));

Expand Down Expand Up @@ -188,14 +190,14 @@ test('dates', t => {

let clone = new Date(date);
proxy.a.setSeconds(32);
verify(2, proxy, 'a', date, clone);
verify(2, proxy, 'a', date, clone, 'setSeconds');

clone = new Date(date);
proxy.a.setHours(5);
verify(3, proxy, 'a', date, clone);
verify(3, proxy, 'a', date, clone, 'setHours');

proxy.a.setHours(5);
verify(3, proxy, 'a', date, clone);
verify(3, proxy, 'a', date, clone, 'setHours');
});
});

Expand All @@ -204,7 +206,7 @@ test('should trigger once when an array element is set with an array as the main

testHelper(t, object, {}, (proxy, verify) => {
proxy[0] = 'a';
verify(1, proxy, '0', 'a', 1, ['a', 2, {a: false}]);
verify(1, proxy, '0', 'a', 1, undefined, ['a', 2, {a: false}]);
});
});

Expand All @@ -213,7 +215,7 @@ test('should trigger once when a property of an array element is set with an arr

testHelper(t, object, {}, (proxy, verify) => {
proxy[2].a = true;
verify(1, proxy, '2.a', true, false, [1, 2, {a: true}]);
verify(1, proxy, '2.a', true, false, undefined, [1, 2, {a: true}]);
});
});

Expand All @@ -222,7 +224,7 @@ test('should trigger once when an array is sorted with an array as the main obje

testHelper(t, object, {}, (proxy, verify) => {
proxy.sort();
verify(1, proxy, '', [1, 2, 3], [2, 3, 1], [1, 2, 3]);
verify(1, proxy, '', [1, 2, 3], [2, 3, 1], 'sort', [1, 2, 3]);
});
});

Expand All @@ -231,7 +233,7 @@ test('should trigger once when an array is popped with an array as the main obje

testHelper(t, object, {}, (proxy, verify) => {
proxy.pop();
verify(1, proxy, '', [2, 3], [2, 3, 1], [2, 3]);
verify(1, proxy, '', [2, 3], [2, 3, 1], 'pop', [2, 3]);
});
});

Expand All @@ -240,7 +242,7 @@ test('should trigger once when an array is reversed with an array as the main ob

testHelper(t, object, {}, (proxy, verify) => {
proxy.reverse();
verify(1, proxy, '', [1, 3, 2], [2, 3, 1], [1, 3, 2]);
verify(1, proxy, '', [1, 3, 2], [2, 3, 1], 'reverse', [1, 3, 2]);
});
});

Expand All @@ -249,7 +251,7 @@ test('should trigger once when an array is spliced with an array as the main obj

testHelper(t, object, {}, (proxy, verify) => {
proxy.splice(1, 1, 'a', 'b');
verify(1, proxy, '', [2, 'a', 'b', 1], [2, 3, 1], [2, 'a', 'b', 1]);
verify(1, proxy, '', [2, 'a', 'b', 1], [2, 3, 1], 'splice', [2, 'a', 'b', 1]);
});
});

Expand Down Expand Up @@ -456,31 +458,31 @@ test('the callback should provide the original proxied object, the path to the c
verify(3, proxy, 'x.y.0.new', undefined, 1);

proxy.x.y.push('pushed');
verify(4, proxy, 'x.y', [{z: 1}, 'pushed'], [{z: 1}]);
verify(4, proxy, 'x.y', [{z: 1}, 'pushed'], [{z: 1}], 'push');

proxy.x.y.pop();
verify(5, proxy, 'x.y', [{z: 1}], [{z: 1}, 'pushed']);
verify(5, proxy, 'x.y', [{z: 1}], [{z: 1}, 'pushed'], 'pop');

proxy.x.y.unshift('unshifted');
verify(6, proxy, 'x.y', ['unshifted', {z: 1}], [{z: 1}]);
verify(6, proxy, 'x.y', ['unshifted', {z: 1}], [{z: 1}], 'unshift');

proxy.x.y.shift();
verify(7, proxy, 'x.y', [{z: 1}], ['unshifted', {z: 1}]);
verify(7, proxy, 'x.y', [{z: 1}], ['unshifted', {z: 1}], 'shift');

proxy.x.y = proxy.x.y.concat([{z: 3}, {z: 2}]);
verify(8, proxy, 'x.y', [{z: 1}, {z: 3}, {z: 2}], [{z: 1}]);

proxy.x.y.sort((a, b) => a.z - b.z);
verify(9, proxy, 'x.y', [{z: 1}, {z: 2}, {z: 3}], [{z: 1}, {z: 3}, {z: 2}]);
verify(9, proxy, 'x.y', [{z: 1}, {z: 2}, {z: 3}], [{z: 1}, {z: 3}, {z: 2}], 'sort');

proxy.x.y.reverse();
verify(10, proxy, 'x.y', [{z: 3}, {z: 2}, {z: 1}], [{z: 1}, {z: 2}, {z: 3}]);
verify(10, proxy, 'x.y', [{z: 3}, {z: 2}, {z: 1}], [{z: 1}, {z: 2}, {z: 3}], 'reverse');

proxy.x.y.forEach(item => item.z++);
verify(11, proxy, 'x.y', [{z: 4}, {z: 3}, {z: 2}], [{z: 3}, {z: 2}, {z: 1}]);
verify(11, proxy, 'x.y', [{z: 4}, {z: 3}, {z: 2}], [{z: 3}, {z: 2}, {z: 1}], 'forEach');

proxy.x.y.splice(1, 2);
verify(12, proxy, 'x.y', [{z: 4}], [{z: 4}, {z: 3}, {z: 2}]);
verify(12, proxy, 'x.y', [{z: 4}], [{z: 4}, {z: 3}, {z: 2}], 'splice');

let unproxied = onChange.target(proxy);

Expand Down Expand Up @@ -529,31 +531,31 @@ test('the callback should provide the original proxied object, the path to the c
verify(3, proxy, ['x', 'y', '0', 'new'], undefined, 1);

proxy.x.y.push('pushed');
verify(4, proxy, ['x', 'y'], [{z: 1}, 'pushed'], [{z: 1}]);
verify(4, proxy, ['x', 'y'], [{z: 1}, 'pushed'], [{z: 1}], 'push');

proxy.x.y.pop();
verify(5, proxy, ['x', 'y'], [{z: 1}], [{z: 1}, 'pushed']);
verify(5, proxy, ['x', 'y'], [{z: 1}], [{z: 1}, 'pushed'], 'pop');

proxy.x.y.unshift('unshifted');
verify(6, proxy, ['x', 'y'], ['unshifted', {z: 1}], [{z: 1}]);
verify(6, proxy, ['x', 'y'], ['unshifted', {z: 1}], [{z: 1}], 'unshift');

proxy.x.y.shift();
verify(7, proxy, ['x', 'y'], [{z: 1}], ['unshifted', {z: 1}]);
verify(7, proxy, ['x', 'y'], [{z: 1}], ['unshifted', {z: 1}], 'shift');

proxy.x.y = proxy.x.y.concat([{z: 3}, {z: 2}]);
verify(8, proxy, ['x', 'y'], [{z: 1}, {z: 3}, {z: 2}], [{z: 1}]);

proxy.x.y.sort((a, b) => a.z - b.z);
verify(9, proxy, ['x', 'y'], [{z: 1}, {z: 2}, {z: 3}], [{z: 1}, {z: 3}, {z: 2}]);
verify(9, proxy, ['x', 'y'], [{z: 1}, {z: 2}, {z: 3}], [{z: 1}, {z: 3}, {z: 2}], 'sort');

proxy.x.y.reverse();
verify(10, proxy, ['x', 'y'], [{z: 3}, {z: 2}, {z: 1}], [{z: 1}, {z: 2}, {z: 3}]);
verify(10, proxy, ['x', 'y'], [{z: 3}, {z: 2}, {z: 1}], [{z: 1}, {z: 2}, {z: 3}], 'reverse');

proxy.x.y.forEach(item => item.z++);
verify(11, proxy, ['x', 'y'], [{z: 4}, {z: 3}, {z: 2}], [{z: 3}, {z: 2}, {z: 1}]);
verify(11, proxy, ['x', 'y'], [{z: 4}, {z: 3}, {z: 2}], [{z: 3}, {z: 2}, {z: 1}], 'forEach');

proxy.x.y.splice(1, 2);
verify(12, proxy, ['x', 'y'], [{z: 4}], [{z: 4}, {z: 3}, {z: 2}]);
verify(12, proxy, ['x', 'y'], [{z: 4}], [{z: 4}, {z: 3}, {z: 2}], 'splice');

let unproxied = onChange.target(proxy);

Expand Down Expand Up @@ -619,7 +621,7 @@ test('the callback should return a raw value when apply traps are triggered', t

testHelper(t, object, {}, (proxy, verify, reset, last) => {
proxy.x.y.push('pushed');
verify(1, proxy, 'x.y', [{z: 0}, 'pushed'], [{z: 0}]);
verify(1, proxy, 'x.y', [{z: 0}, 'pushed'], [{z: 0}], 'push');

last.value.pop();
t.is(last.count, 1);
Expand All @@ -637,7 +639,7 @@ test('the callback should return a raw value when apply traps are triggered and

testHelper(t, object, {pathAsArray: true}, (proxy, verify, reset, last) => {
proxy.x.y.push('pushed');
verify(1, proxy, ['x', 'y'], [{z: 0}, 'pushed'], [{z: 0}]);
verify(1, proxy, ['x', 'y'], [{z: 0}, 'pushed'], [{z: 0}], 'push');

last.value.pop();
t.is(last.count, 1);
Expand Down Expand Up @@ -856,7 +858,7 @@ test('should not call the callback for nested items of an array if isShallow is
verify(0);

proxy.unshift('a');
verify(1, proxy, '', ['a', {z: 1}], [{z: 1}]);
verify(1, proxy, '', ['a', {z: 1}], [{z: 1}], 'unshift');
});
});

Expand Down Expand Up @@ -1045,7 +1047,7 @@ test('should be able to mutate itself in an object', t => {
verify(1, proxy, '', {x: 1, method}, {
x: 0,
method
});
}, 'method');
});
});

Expand All @@ -1064,7 +1066,7 @@ test('should be able to mutate itself in a class', t => {
proxy.method();
verify(1, proxy, '', new TestClass(1), {
x: 0
});
}, 'method');
});
});

Expand Down

0 comments on commit 26d431a

Please sign in to comment.