Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

deep-diff

Package Overview
Dependencies
Maintainers
1
Versions
22
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

deep-diff - npm Package Compare versions

Comparing version 0.1.1 to 0.1.2

examples/performance.js

415

index.js

@@ -1,206 +0,257 @@

({ define: typeof define === "function"
? define // browser
: function(F) { F(require,exports,module); } }). // Node.js
define(function (require, exports, module) {
"use strict";
;(function(undefined) {
"use strict";
var util = require('util');
var $scope
, conflict, conflictResolution = [];
if (typeof global == 'object' && global) {
$scope = global;
} else if (typeof window !== 'undefined'){
$scope = window;
} else {
$scope = {};
}
conflict = $scope.DeepDiff;
if (conflict) {
conflictResolution.push(
function() {
if ($scope.DeepDiff === accumulateDiff) {
$scope.DeepDiff = conflict;
conflict = undefined;
}
});
}
function Diff(kind, path) {
Object.defineProperty(this, 'kind', { value: kind, enumerable: true });
if (path && path.length) {
Object.defineProperty(this, 'path', { value: path, enumerable: true });
}
}
function DiffEdit(path, origin, value) {
DiffEdit.super_.call(this, 'E', path);
// nodejs compatible on server side and in the browser.
function inherits(ctor, superCtor) {
ctor.super_ = superCtor;
ctor.prototype = Object.create(superCtor.prototype, {
constructor: {
value: ctor,
enumerable: false,
writable: true,
configurable: true
}
});
}
Object.defineProperty(this, 'lhs', { value: origin, enumerable: true });
Object.defineProperty(this, 'rhs', { value: value, enumerable: true });
}
util.inherits(DiffEdit, Diff);
function DiffNew(path, value) {
DiffNew.super_.call(this, 'N', path);
function Diff(kind, path) {
Object.defineProperty(this, 'kind', { value: kind, enumerable: true });
if (path && path.length) {
Object.defineProperty(this, 'path', { value: path, enumerable: true });
}
}
Object.defineProperty(this, 'rhs', { value: value, enumerable: true });
}
util.inherits(DiffNew, Diff);
function DiffDeleted(path, value) {
DiffDeleted.super_.call(this, 'D', path);
function DiffEdit(path, origin, value) {
DiffEdit.super_.call(this, 'E', path);
Object.defineProperty(this, 'lhs', { value: origin, enumerable: true });
Object.defineProperty(this, 'rhs', { value: value, enumerable: true });
}
inherits(DiffEdit, Diff);
Object.defineProperty(this, 'lhs', { value: value, enumerable: true });
}
util.inherits(DiffDeleted, Diff);
function DiffArray(path, index, item) {
DiffArray.super_.call(this, 'A', path);
function DiffNew(path, value) {
DiffNew.super_.call(this, 'N', path);
Object.defineProperty(this, 'rhs', { value: value, enumerable: true });
}
inherits(DiffNew, Diff);
Object.defineProperty(this, 'index', { value: index, enumerable: true });
Object.defineProperty(this, 'item', { value: item, enumerable: true });
}
util.inherits(DiffArray, Diff);
function DiffDeleted(path, value) {
DiffDeleted.super_.call(this, 'D', path);
Object.defineProperty(this, 'lhs', { value: value, enumerable: true });
}
inherits(DiffDeleted, Diff);
function arrayRemove(arr, from, to) {
var rest = arr.slice((to || from) + 1 || arr.length);
arr.length = from < 0 ? arr.length + from : from;
arr.push.apply(arr, rest);
return arr;
}
function DiffArray(path, index, item) {
DiffArray.super_.call(this, 'A', path);
Object.defineProperty(this, 'index', { value: index, enumerable: true });
Object.defineProperty(this, 'item', { value: item, enumerable: true });
}
inherits(DiffArray, Diff);
var recordDifferences;
function arrayRemove(arr, from, to) {
var rest = arr.slice((to || from) + 1 || arr.length);
arr.length = from < 0 ? arr.length + from : from;
arr.push.apply(arr, rest);
return arr;
}
function deepDiff(lhs, rhs, changes, path, key, stack) {
path = path || [];
var currentPath = path.slice(0);
if (key) { currentPath.push(key); }
var ltype = typeof lhs;
var rtype = typeof rhs;
if (ltype === 'undefined') {
if (rtype !== 'undefined') {
changes(new DiffNew(currentPath, rhs ));
}
} else if (rtype === 'undefined') {
changes(new DiffDeleted(currentPath, lhs));
} else if (ltype !== rtype) {
changes(new DiffEdit(currentPath, lhs, rhs));
} else if (ltype === 'object' && lhs != null) {
stack = stack || [];
if (stack.indexOf(lhs) < 0) {
stack.push(lhs);
if (Array.isArray(lhs)) {
var i, ea = function(d) {
changes(new DiffArray(currentPath, i, d));
};
for(i = 0; i < lhs.length; i++) {
if (i >= rhs.length) {
changes(new DiffArray(currentPath, i, new DiffDeleted(undefined, lhs[i])));
} else {
deepDiff(lhs[i], rhs[i], ea, [], null, stack);
}
}
while(i < rhs.length) {
changes(new DiffArray(currentPath, i, new DiffNew(undefined, rhs[i++])));
}
} else {
var akeys = Object.keys(lhs);
var pkeys = Object.keys(rhs);
akeys.forEach(function(k) {
var i = pkeys.indexOf(k);
if (i >= 0) {
deepDiff(lhs[k], rhs[k], changes, currentPath, k, stack);
pkeys = arrayRemove(pkeys, i);
} else {
deepDiff(lhs[k], undefined, changes, currentPath, k, stack);
}
});
pkeys.forEach(function(k) {
deepDiff(undefined, rhs[k], changes, currentPath, k, stack);
});
}
stack.length = stack.length - 1;
}
} else if (lhs !== rhs) {
changes(new DiffEdit(currentPath, lhs, rhs));
function deepDiff(lhs, rhs, changes, path, key, stack) {
path = path || [];
var currentPath = path.slice(0);
if (key) { currentPath.push(key); }
var ltype = typeof lhs;
var rtype = typeof rhs;
if (ltype === 'undefined') {
if (rtype !== 'undefined') {
changes(new DiffNew(currentPath, rhs ));
}
} else if (rtype === 'undefined') {
changes(new DiffDeleted(currentPath, lhs));
} else if (ltype !== rtype) {
changes(new DiffEdit(currentPath, lhs, rhs));
} else if (ltype === 'object' && lhs != null) {
stack = stack || [];
if (stack.indexOf(lhs) < 0) {
stack.push(lhs);
if (Array.isArray(lhs)) {
var i
, len = lhs.length
, ea = function(d) {
changes(new DiffArray(currentPath, i, d));
};
for(i = 0; i < lhs.length; i++) {
if (i >= rhs.length) {
changes(new DiffArray(currentPath, i, new DiffDeleted(undefined, lhs[i])));
} else {
deepDiff(lhs[i], rhs[i], ea, [], null, stack);
}
}
while(i < rhs.length) {
changes(new DiffArray(currentPath, i, new DiffNew(undefined, rhs[i++])));
}
} else {
var akeys = Object.keys(lhs);
var pkeys = Object.keys(rhs);
akeys.forEach(function(k) {
var i = pkeys.indexOf(k);
if (i >= 0) {
deepDiff(lhs[k], rhs[k], changes, currentPath, k, stack);
pkeys = arrayRemove(pkeys, i);
} else {
deepDiff(lhs[k], undefined, changes, currentPath, k, stack);
}
});
pkeys.forEach(function(k) {
deepDiff(undefined, rhs[k], changes, currentPath, k, stack);
});
}
stack.length = stack.length - 1;
}
} else if (lhs !== rhs) {
changes(new DiffEdit(currentPath, lhs, rhs));
}
}
function accumulateDiff(lhs, rhs, accum) {
accum = accum || [];
deepDiff(lhs, rhs, function(diff) {
if (diff) {
accum.push(diff);
}
});
return (accum.length) ? accum : undefined;
}
function applyArrayChange(arr, index, change) {
if (change.path && change.path.length) {
// the structure of the object at the index has changed...
var it = arr[index], i, u = change.path.length - 1;
for(i = 0; i < u; i++){
it = it[change.path[i]];
}
switch(change.kind) {
case 'A':
// Array was modified...
// it will be an array...
applyArrayChange(it, change.index, change.item);
break;
case 'D':
// Item was deleted...
delete it[change.path[i]];
break;
case 'E':
case 'N':
// Item was edited or is new...
it[change.path[i]] = change.rhs;
break;
}
} else {
// the array item is different...
switch(change.kind) {
case 'A':
// Array was modified...
// it will be an array...
applyArrayChange(arr[index], change.index, change.item);
break;
case 'D':
// Item was deleted...
arr = arrayRemove(arr, index);
break;
case 'E':
case 'N':
// Item was edited or is new...
arr[index] = change.rhs;
break;
}
}
return arr;
}
function accumulateDiff(lhs, rhs, accum) {
accum = accum || [];
deepDiff(lhs, rhs, function(diff) {
if (diff) {
accum.push(diff);
}
});
return (accum.length) ? accum : undefined;
function applyChange(target, source, change) {
if (!(change instanceof Diff)) {
throw new TypeError('[Object] change must be instanceof Diff');
}
function applyArrayChange(arr, index, change) {
if (change.path && change.path.length) {
// the structure of the object at the index has changed...
var it = arr[index], i, u = change.path.length - 1;
for(i = 0; i < u; i++){
it = it[change.path[i]];
if (target && source && change) {
var it = target, i, u;
u = change.path.length - 1;
for(i = 0; i < u; i++){
if (typeof it[change.path[i]] === 'undefined') {
it[change.path[i]] = {};
}
switch(change.kind) {
case 'A':
// Array was modified...
// it will be an array...
applyArrayChange(it, change.index, change.item);
break;
case 'D':
// Item was deleted...
delete it[change.path[i]];
break;
case 'E':
case 'N':
// Item was edited or is new...
it[change.path[i]] = change.rhs;
break;
it = it[change.path[i]];
}
switch(change.kind) {
case 'A':
// Array was modified...
// it will be an array...
applyArrayChange(it[change.path[i]], change.index, change.item);
break;
case 'D':
// Item was deleted...
delete it[change.path[i]];
break;
case 'E':
case 'N':
// Item was edited or is new...
it[change.path[i]] = change.rhs;
break;
}
} else {
// the array item is different...
switch(change.kind) {
case 'A':
// Array was modified...
// it will be an array...
applyArrayChange(arr[index], change.index, change.item);
break;
case 'D':
// Item was deleted...
arr = arrayRemove(arr, index);
break;
case 'E':
case 'N':
// Item was edited or is new...
arr[index] = change.rhs;
break;
}
}
return arr;
}
function applyChange(target, source, change) {
if (!(change instanceof Diff)) {
throw new TypeError('[Object] change must be instanceof Diff');
}
if (target && source && change) {
var it = target, i, u;
u = change.path.length - 1;
for(i = 0; i < u; i++){
it = it[change.path[i]];
function applyDiff(target, source, filter) {
if (target && source) {
var onChange = function(change) {
if (!filter || filter(target, source, change)) {
applyChange(target, source, change);
}
switch(change.kind) {
case 'A':
// Array was modified...
// it will be an array...
applyArrayChange(it[change.path[i]], change.index, change.item);
break;
case 'D':
// Item was deleted...
delete it[change.path[i]];
break;
case 'E':
case 'N':
// Item was edited or is new...
it[change.path[i]] = change.rhs;
break;
}
}
};
deepDiff(target, source, onChange);
}
}
function applyDiff(target, source, filter) {
if (target && source) {
var onChange = function(change) {
if (!filter || filter(target, source, change)) {
applyChange(target, source, change);
}
};
deepDiff(target, source, onChange);
}
Object.defineProperties(accumulateDiff, {
diff: { value: accumulateDiff, enumerable:true },
observableDiff: { value: deepDiff, enumerable:true },
applyDiff: { value: applyDiff, enumerable:true },
applyChange: { value: applyChange, enumerable:true },
isConflict: { get: function() { return 'undefined' !== typeof conflict; }, enumerable: true },
noConflict: {
value: function () {
if (conflictResolution) {
conflictResolution.forEach(function (it) { it(); });
conflictResolution = null;
}
return accumulateDiff;
},
enumerable: true
}
exports.diff = accumulateDiff;
exports.observableDiff = deepDiff;
exports.applyDiff = applyDiff;
exports.applyChange = applyChange;
});
if (typeof module != 'undefined' && module && typeof exports == 'object' && exports && module.exports === exports) {
module.exports = accumulateDiff; // nodejs
} else {
$scope.DeepDiff = accumulateDiff; // other... browser?
}
}());
{
"name": "deep-diff",
"description": "Node.js module providing utility functions for working with the structural differences between objects.",
"version": "0.1.1",
"version": "0.1.2",
"keywords": [

@@ -11,6 +11,6 @@ "diff",

],
"author": {
"name": "Phillip Clark",
"email": "phillip@flitbit.org"
},
"author": "Phillip Clark <phillip@flitbit.com>",
"contributors": [
"SocalNick"
],
"repository": { "type": "git", "url": "git://github.com/flitbit/diff.git" },

@@ -17,0 +17,0 @@ "main": "./index.js",

@@ -1,2 +0,2 @@

# deep-diff
# deep-diff [![Build Status](https://travis-ci.org/flitbit/diff.png)](http://travis-ci.org/flitbit/diff)

@@ -17,15 +17,36 @@ **deep-diff** is a javascript/node.js module providing utility functions for working with the structural differences between objects.

## Testing
Tests are written using [vows](http://vowsjs.org/) & [should.js](https://github.com/visionmedia/should.js/) (you may need to install them). If you've installed in a development environment you can use npm to run the tests.
## Tests
Tests use [mocha](http://visionmedia.github.io/mocha/) and [expect.js](https://github.com/LearnBoost/expect.js/), so if you clone the [github repository](https://github.com/flitbit/json-ptr) you'll need to run:
```bash
npm install
```
npm test deep-diff
... followed by ...
```bash
npm test
```
If you intend to run the examples you'll also need [extend](https://github.com/justmoon/node-extend) and [lodash](https://github.com/bestiejs/lodash).
... or ...
## Warning!
```bash
mocha -R spec
```
I've only had time to verify its behavior in node.js. If you're working in a browser you're on your own for now.
### Importing
**nodejs**
```javascript
var deep = require('deep-diff')
```
**browser**
```html
<script src="deep-diff-0.1.2.min.js"></script>
```
> In a browser, `deep-diff` defines a global variable `DeepDiff`. If there is a conflict in the global namesapce you can restore the conflicting definition and assign `deep-diff` to another variable like this: `var deep = DeepDiff.noConflict();`.
## Simple Examples

@@ -58,3 +79,3 @@

var differences = diff(lhs, rhs);
var differences = diff(lhs, rhs);
```

@@ -94,3 +115,3 @@ The code snippet above would result in the following structure describing the differences:

* `index` - when kind === 'A', indicates the array index where the change occurred
* `item` - when kind === 'A', contains a nested change record indicating the change that occurred at the array index
* `item` - when kind === 'A', contains a nested change record indicating the change that occurred at the array index

@@ -132,8 +153,9 @@ Change records are generated for all structural differences between `origin` and `comparand`. The methods only consider an object's own properties and array elements; those inherited from an object's prototype chain are not considered.

if (d.path.length !== 1 || d.path.join('.') !== 'name') {
applyChange(lhs, rhs, d);
applyChange(lhs, rhs, d);
}
});
});
```
## API Documentation
A standard import of `var diff = require('deep-diff')` is assumed in all of the code examples. The import results in an object having the following public properties:

@@ -140,0 +162,0 @@

@@ -1,4 +0,8 @@

var deep = require('..')
, expect = require('expect.js')
, util = require('util')
if (typeof require === 'function') {
var expect = require('expect.js'),
DeepDiff = require('..')
;
}
var deep = DeepDiff
, executingInBrowser = 'undefined' !== typeof window
;

@@ -95,3 +99,73 @@

describe('When executing in a browser (otherwise these tests are benign)', function() {
it('#isConflict reports conflict in the global namespace for `DeepDiff`', function() {
// the browser test harness sets up a conflict.
if (executingInBrowser) {
expect(DeepDiff.isConflict).to.be.ok();
}
});
it('#noConflict restores prior definition for the global `DeepDiff`', function() {
// the browser test harness sets up a conflict.
if (executingInBrowser) {
expect(DeepDiff.isConflict).to.be.ok();
var another = DeepDiff.noConflict();
expect(another).to.be(deep);
expect(DeepDiff).to.be(DeepDiffConflict);
}
});
});
describe('A target that has nested values', function() {
var nestedOne = { noChange: 'same', levelOne: { levelTwo: 'value' } };
var nestedTwo = { noChange: 'same', levelOne: { levelTwo: 'another value' } };
it('shows no differences when compared to itself', function() {
expect(deep.diff(nestedOne, nestedOne)).to.be.an('undefined');
});
it('shows the property as removed when compared to an empty object', function() {
var diff = deep(nestedOne, empty);
expect(diff).to.be.ok();
expect(diff.length).to.be(2);
expect(diff[0]).to.have.property('kind');
expect(diff[0].kind).to.be('D');
expect(diff[1]).to.have.property('kind');
expect(diff[1].kind).to.be('D');
});
it('shows the property is changed when compared to an object that has value', function() {
var diff = deep.diff(nestedOne, nestedTwo);
expect(diff).to.be.ok();
expect(diff.length).to.be(1);
expect(diff[0]).to.have.property('kind');
expect(diff[0].kind).to.be('E');
});
it('shows the property as added when compared to an empty object on left', function() {
var diff = deep.diff(empty, nestedOne);
expect(diff).to.be.ok();
expect(diff.length).to.be(2);
expect(diff[0]).to.have.property('kind');
expect(diff[0].kind).to.be('N');
});
describe('when diff is applied to a different empty object', function () {
var diff = deep.diff(nestedOne, nestedTwo);
var result = {};
it('has result with nested values', function() {
deep.applyChange(result, nestedTwo, diff[0]);
expect(result.levelOne).to.be.ok();
expect(result.levelOne).to.be.an('object');
expect(result.levelOne.levelTwo).to.be.ok();
expect(result.levelOne.levelTwo).to.eql('another value');
});
});
});
});
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc