diff --git a/lib/generate.js b/lib/generate.js index b2a5f68..ba5d6f2 100644 --- a/lib/generate.js +++ b/lib/generate.js @@ -19,53 +19,33 @@ module.exports = function generate(before, after) { before = serialize(before); after = serialize(after); + if (!(before instanceof Object) && + !(after instanceof Object) && + before === after) { // Return no op when values match + return {} + } + if (before === null || after === null || typeof before !== 'object' || typeof after !== 'object' || - Array.isArray(before) !== Array.isArray(after)) { - return after; + Array.isArray(before) || Array.isArray(after)) { + return serialize(after); } - if (Array.isArray(before)) { - if (!arrayEquals(before, after)) { - return after; + let patch = {}; + for (let key of Object.keys(before)) { + let newVal = generate(before[key] ?? null, after[key] ?? null); + // Omit noops + if (equal(newVal, {})) { + continue; } - return undefined; + patch[key] = serialize(newVal); } - var patch = {}; - var beforeKeys = Object.keys(before); - var afterKeys = Object.keys(after); - - var key, i; - - // new elements - var newKeys = {}; - for (i = 0; i < afterKeys.length; i++) { - key = afterKeys[i]; - if (beforeKeys.indexOf(key) === -1) { - newKeys[key] = true; + for (let key of Object.keys(after)) { + if (!(key in before)) { patch[key] = serialize(after[key]); } } - // removed & modified elements - var removedKeys = {}; - for (i = 0; i < beforeKeys.length; i++) { - key = beforeKeys[i]; - if (afterKeys.indexOf(key) === -1) { - removedKeys[key] = true; - patch[key] = null; - } else { - if (before[key] !== null && typeof before[key] === 'object') { - var subPatch = generate(before[key], after[key]); - if (subPatch !== undefined) { - patch[key] = subPatch; - } - } else if (before[key] !== after[key]) { - patch[key] = serialize(after[key]); - } - } - } - - return (Object.keys(patch).length > 0 ? patch : undefined); + return (Object.keys(patch).length > 0 ? patch : {}); }; diff --git a/package.json b/package.json index 36861d3..b22fad0 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "json-merge-patch", - "version": "1.0.2", + "version": "2.1.0", "description": "Implementation of JSON Merge Patch (RFC 7396)", "main": "index.js", "directories": { diff --git a/test/lib/generate.js b/test/lib/generate.js index a91499b..c1c47e4 100644 --- a/test/lib/generate.js +++ b/test/lib/generate.js @@ -126,24 +126,24 @@ describe('generate', function() { ); }); - it('should return undefined if the object hasnt changed', function() { + it('should return {} if the object hasnt changed', function() { assert.deepEqual( generate({a: 'a'}, {a: 'a'}), - undefined + {} ); }); - it('should return undefined if the object with sub attributes hasnt changed', function() { + it('should return {} if the object with sub attributes hasnt changed', function() { assert.deepEqual( generate({a: {b: 'c'}}, {a: {b: 'c'}}), - undefined + {} ); }); - it('should return undefined if the array hasnt changed', function() { + it('should return the target if the output is an array', function() { assert.deepEqual( generate([1, 2, 3], [1, 2, 3]), - undefined + [1,2,3] ); });