Skip to content

Commit 84726ca

Browse files
Fix diffJson's handling of non-callable toJSON properties (#700)
* Add test showing behaviour reported in #699 * Fix #699 * Add release notes * Release notes
1 parent c207c49 commit 84726ca

3 files changed

Lines changed: 34 additions & 1 deletion

File tree

release-notes.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
## 9.1.0 (prerelease)
44

55
- [#697](https://github.com/kpdecker/jsdiff/pull/697) *`diffJson` now correctly handles JSON objects containing a key named `__proto__`*. (Previously, the returned diff would be as if the `__proto__` key did not exist on either of the objects being diffed.)
6+
- [#700](https://github.com/kpdecker/jsdiff/pull/700) *`diffJson` now correctly handles JSON objects containing a non-callable property named `toJSON`* - i.e. it gives such a property no special behaviour whatsoever, just as `JSON.stringify` doesn't. Previously, such properties caused an error to be thrown. (*Callable* `toJSON` properties continue to get the same special behaviour that `JSON.stringify` gives them.)
67

78
## 9.0.0
89

src/diff/json.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ export function canonicalize(
9797
return canonicalizedObj;
9898
}
9999

100-
if (obj && obj.toJSON) {
100+
if (obj && typeof obj.toJSON === 'function') {
101101
obj = obj.toJSON();
102102
}
103103

test/diff/json.js

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,38 @@ describe('diff/json', function() {
127127
{ count: 1, value: '}', removed: false, added: false }
128128
]);
129129
});
130+
131+
it('handles custom toJSON methods like JSON.stringify does', function() {
132+
const x = {
133+
toJSON: () => 'aaa'
134+
};
135+
const y = {
136+
toJSON: () => 'bbb'
137+
};
138+
139+
expect(diffJson({ foo: x }, {foo: y})).to.eql([
140+
{ count: 1, value: '{\n', removed: false, added: false },
141+
{ count: 1, value: ' "foo": "aaa"\n', added: false, removed: true },
142+
{ count: 1, value: ' "foo": "bbb"\n', added: true, removed: false },
143+
{ count: 1, value: '}', removed: false, added: false }
144+
]);
145+
});
146+
147+
it('treats non-callable toJSON properties as normal properties (like JSON.stringify does)', function() {
148+
const x = {
149+
toJSON: 'aaa'
150+
};
151+
const y = {
152+
toJSON: 'bbb'
153+
};
154+
155+
expect(diffJson(x, y)).to.eql([
156+
{ count: 1, value: '{\n', removed: false, added: false },
157+
{ count: 1, value: ' "toJSON": "aaa"\n', added: false, removed: true },
158+
{ count: 1, value: ' "toJSON": "bbb"\n', added: true, removed: false },
159+
{ count: 1, value: '}', removed: false, added: false }
160+
]);
161+
});
130162
});
131163

132164
describe('#canonicalize', function() {

0 commit comments

Comments
 (0)