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

evil-diff

Package Overview
Dependencies
Maintainers
1
Versions
6
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

evil-diff - npm Package Compare versions

Comparing version 0.0.2 to 0.0.3

lib/index.js.map

5

lib/index.d.ts

@@ -0,4 +1,7 @@

export { revise as reviseOperator } from './operators/revise';
export { retainFn } from './retainFn';
export { revise } from './revise';
export { reviseFn } from './reviseFn';
export { retainFn } from './retainFn';
export { reviseReducer } from './reviseReducer';
export { smartEach } from './smartEach';
export { smartMap } from './smartMap';

15

lib/index.js
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var revise_1 = require("./revise");
exports.revise = revise_1.revise;
var revise_1 = require("./operators/revise");
exports.reviseOperator = revise_1.revise;
var retainFn_1 = require("./retainFn");
exports.retainFn = retainFn_1.retainFn;
var revise_2 = require("./revise");
exports.revise = revise_2.revise;
var reviseFn_1 = require("./reviseFn");
exports.reviseFn = reviseFn_1.reviseFn;
var retainFn_1 = require("./retainFn");
exports.retainFn = retainFn_1.retainFn;
var reviseReducer_1 = require("./reviseReducer");
exports.reviseReducer = reviseReducer_1.reviseReducer;
var smartEach_1 = require("./smartEach");
exports.smartEach = smartEach_1.smartEach;
var smartMap_1 = require("./smartMap");
exports.smartMap = smartMap_1.smartMap;
//# sourceMappingURL=index.js.map

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

export declare const isObject: (obj: {}) => obj is object;
export declare const isObject: (obj: any) => obj is object;
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
// tslint:disable-next-line no-any We allow any object to be checked.
exports.isObject = (obj) => {
return typeof obj === 'object';
return typeof obj === 'object' && obj != null;
};
//# sourceMappingURL=isObject.js.map

@@ -7,3 +7,5 @@ "use strict";

let output;
// TODO(asif): Use WeakMap to allow obj dealloc.
return function (...newArgs) {
// TODO(#27): reviseFn instead of shallowArrayEqual.
const unchanged = shallowArrayEqual_1.shallowArrayEqual(lastArgs, newArgs);

@@ -17,1 +19,2 @@ if (!unchanged) {

};
//# sourceMappingURL=retainFn.js.map

@@ -1,1 +0,5 @@

export declare const revise: <T>(source: T, revision: T) => T;
import { WalkFilter } from './walkTree';
export interface ReviseOptions {
prefilter?: WalkFilter;
}
export declare const revise: <T>(source: T, revision: T, reviseOptions?: ReviseOptions) => T;
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const walkTree_1 = require("./walkTree");
exports.revise = (source, revision) => {
return walkTree_1.walkTree(source, revision);
exports.revise = (source, revision, reviseOptions = {}) => {
const { prefilter } = reviseOptions;
// TODO(asif): See if we can get this type working.
const nodeSet = new Set();
return walkTree_1.walkTree(source, revision, {
nodeSet,
path: [],
prefilter,
});
};
//# sourceMappingURL=revise.js.map
export declare type callback<K, A, M> = (this: K, ...args: A[]) => M;
export declare const reviseFn: <K, A, M>(fn: callback<K, A, M>) => (...args: A[]) => M;
export declare const reviseFn: <K, A, M>(fn: callback<K, A, M>, initial?: M | undefined) => (...args: A[]) => M;
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const revise_1 = require("./revise");
exports.reviseFn = (fn) => {
let source;
exports.reviseFn = (fn, initial) => {
let source = initial;
return function (...args) {

@@ -12,1 +12,2 @@ const revision = fn.apply(this, args);

};
//# sourceMappingURL=reviseFn.js.map
import { AnyAction, Reducer } from 'redux';
/**
* EvilDiff.revise wrapper for redux.
*
* Usage:
* createStore(reviseReducer(rootReducer));
*/
export declare const reviseReducer: <S>(reducer: Reducer<S>) => (state: S, action: AnyAction) => S;
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const revise_1 = require("./revise");
/**
* EvilDiff.revise wrapper for redux.
*
* Usage:
* createStore(reviseReducer(rootReducer));
*/
exports.reviseReducer = (reducer) => {

@@ -9,1 +15,2 @@ return (state, action) => {

};
//# sourceMappingURL=reviseReducer.js.map

@@ -17,1 +17,2 @@ "use strict";

};
//# sourceMappingURL=shallowArrayEqual.js.map

@@ -5,5 +5,9 @@ "use strict";

const base = Array.isArray(source) ? [] : {};
// TODO(asif): Remove this hack when TS/pull/13288 is merged in
const sourceObj = source;
// Explicitly use Object.assign to avoid array to object conversion.
// tslint:disable-next-line prefer-object-spread
const cloneObj = Object.assign(base, sourceObj);
return cloneObj;
};
//# sourceMappingURL=shallowClone.js.map

@@ -1,1 +0,11 @@

export declare const walkTree: <T>(source: T, revision: T) => T;
export declare type WalkFilter = (path: string[], value: any, newValue: any) => boolean;
export interface TreeWalkerOptions {
nodeSet: Set<{}>;
path: string[];
prefilter?: WalkFilter;
}
/**
* Recursively walks tree, copy values to revision object and cloning
* paths that have cloned.
*/
export declare function walkTree<T>(source: T, revision: T, options: TreeWalkerOptions): T;

@@ -5,9 +5,62 @@ "use strict";

const shallowClone_1 = require("./shallowClone");
exports.walkTree = (source, revision) => {
/*
* We want to return a Symbol from crawl that lets us know we hit a circular
* dep. In order to work with typescript, we have to trick it in a few ways.
*
* First, we need to tell it that CIRCULAR_DEP_DETECTED is of type CrawlEscape.
* This is handled by casting to any to string.
*
* Second, we the caller function, walkTree, to identify the Symbol, without
* having newValue muddled ed as T|CrawlEscape. But because we cast a symbol to
* string, we can't do newValue === 'CIRCULAR_DEP_DETECTED', which would allow
* typescript to infer that newValue wouldn't be CIRCULAR_DEP_DETECTED after
* that line. To get around that, we implement isCrawlEscape that does the
* symbol check for us.
*/
const CIRCULAR_DEP_DETECTED = Symbol();
const crawl = (source, revision, options) => {
const { nodeSet, path, prefilter, } = options;
// Crawl assumes path is up to date.
if (prefilter && prefilter(path, source, revision)) {
return source;
}
if (isObject_1.isObject(source)) {
if (nodeSet.has(source)) {
// Source will be removed by callee from the set.
return CIRCULAR_DEP_DETECTED;
}
else {
nodeSet.add(source);
}
}
const newValue = walkTree(source, revision, options);
if (isObject_1.isObject(source)) {
nodeSet.delete(source);
}
return newValue;
};
/**
* Hack to transform CIRCULAR_DEP_DETECTED to CrawlEscape.
*/
// tslint:disable-next-line no-any We allow any object to be checked.
const isCrawlEscape = (value) => {
return value === CIRCULAR_DEP_DETECTED;
};
/**
* Recursively walks tree, copy values to revision object and cloning
* paths that have cloned.
*/
// tslint:disable-next-line only-arrow-functions crawl needs hoisting.
function walkTree(source, revision, options) {
const { path, prefilter, } = options;
// Return early for no op.
if (source === revision) {
return source;
}
// Return revision if its a non object type.
// This also catches null/undefined values.
if (!isObject_1.isObject(source) || !isObject_1.isObject(revision)) {
return revision;
}
// Check if both objects are the same. This catches Arr/Obj merging.
const matchingType = source instanceof revision.constructor &&

@@ -18,18 +71,77 @@ revision instanceof source.constructor;

}
// Gather keys. For arrays, its just a list of indexes.
// TODO(asif): Test walking arrays instead of getting its keys.
const sourceKeys = Object.keys(source);
let changed = false;
const revisionKeys = Object.keys(revision);
let cloned = false;
let deletedCount = 0;
for (const key of sourceKeys) {
const sourceValue = source[key];
const revisionValue = revision[key];
const newValue = exports.walkTree(sourceValue, revisionValue);
const revisionValue = key in revision ? revision[key] : undefined;
// TOOD(asif): Optimize path by only mutating if prefilter is set.
// Add key to the path before crawling.
path.push(key);
// Recursive call. If newValue is deeply equal to sourceValue, then
// we return sourceValue, allowing us to skip cloning.
// To handle deleted property via undefined, we need to explictly set this
// return type.
const newValue = crawl(sourceValue, revisionValue, options);
// Remove key from path after crawling.
path.pop();
// Check to see if we hit a circular dependency.
if (isCrawlEscape(newValue)) {
return revisionValue;
}
// If walkTree doesn't return new object, that means no change.
if (newValue === sourceValue) {
continue;
}
if (!changed && isObject_1.isObject(source)) {
// On first change, clone current object.
// This needs to be done before we set the newValue to the property,
// so we don't modify the original object.
// TODO(asif): Remove isObject call when TS/pull/13288 is merged in.
if (!cloned && isObject_1.isObject(source)) {
source = shallowClone_1.shallowClone(source);
changed = true;
cloned = true;
}
source[key] = newValue;
if (newValue === undefined) {
deletedCount++;
// TODO(asif): Investigate performance of delete vs setting
// undefined.
// TODO(asif): Add configuration property to prefer undefined vs
// delete.
delete source[key];
}
else {
source[key] = newValue;
}
}
// Check if there are any new keys in revision object.
if (sourceKeys.length - deletedCount === revisionKeys.length) {
return source;
}
// TODO(asif): Optimize this best O(n) to worst O(n) by switching to a
// set.
for (const key of revisionKeys) {
// TODO(asif): Use deletedCount to return early.
const sourceHasKey = key in source;
// TOOD(asif): Optimize path by only mutating if prefilter is set.
if (!sourceHasKey) {
path.push(key);
if (prefilter && prefilter(path, source[key], revision[key])) {
continue;
}
path.pop();
// There are new keys, so we should clone if we haven't done so already.
// TODO(asif): Remove isObject call when TS/pull/13288 is merged in.
if (!cloned && isObject_1.isObject(source)) {
source = shallowClone_1.shallowClone(source);
cloned = true;
}
source[key] = revision[key];
}
}
return source;
};
}
exports.walkTree = walkTree;
//# sourceMappingURL=walkTree.js.map
{
"name": "evil-diff",
"version": "0.0.2",
"version": "0.0.3",
"description": "evil-diff",

@@ -18,3 +18,3 @@ "license": "MIT",

"clean": "gts clean",
"compile": "tsc -p .",
"compile": "yarn run clean; tsc -p . --project tsconfig.build.json",
"coverage": "nyc --include='src/**/*.ts' --reporter=text --reporter=html --reporter=lcov mocha --compilers ts:ts-node/register --recursive 'test/**/*-spec.ts'",

@@ -26,3 +26,3 @@ "fix": "gts fix",

"pretest": "yarn run lint && yarn run check && yarn run compile",
"test": "mocha --compilers ts:ts-node/register --recursive 'test/**/*-spec.ts' 'src/**/*.ts'",
"test": "yarn run clean; mocha --compilers ts:ts-node/register --recursive 'test/**/*-spec.ts' 'src/**/*.ts'",
"version": "tsc --version",

@@ -47,2 +47,3 @@ "watch": "yarn run compile --watch",

"rimraf": "^2.0.0",
"rxjs": "^5.5.2",
"sinon": "^2.2.0",

@@ -49,0 +50,0 @@ "ts-node": "^3.3.0",

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