Skip to content

Commit

Permalink
Merge pull request #212 from Starcounter-Jack/Use-Maps
Browse files Browse the repository at this point in the history
Use Map and WeakMap to remove leaks and enhance perf
  • Loading branch information
alshakero authored Aug 30, 2018
2 parents 7902a59 + 0afa1b8 commit 0d6be6a
Show file tree
Hide file tree
Showing 7 changed files with 41 additions and 79 deletions.
8 changes: 2 additions & 6 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,8 +1,4 @@
language: node_js
dist: trusty
before_script:
- npm install
node_js: 6
node_js: 8
script:
- npm test
- npm run bench
- npm test && npm run bench
41 changes: 11 additions & 30 deletions dist/fast-json-patch.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/*! fast-json-patch, version: 2.0.6 */
/*! fast-json-patch, version: 2.0.7 */
var jsonpatch =
/******/ (function(modules) { // webpackBootstrap
/******/ // The module cache
Expand Down Expand Up @@ -741,10 +741,10 @@ exports.JsonPatchError = helpers_2.PatchError;
exports.deepClone = helpers_2._deepClone;
exports.escapePathComponent = helpers_2.escapePathComponent;
exports.unescapePathComponent = helpers_2.unescapePathComponent;
var beforeDict = [];
var beforeDict = new WeakMap();
var Mirror = (function () {
function Mirror(obj) {
this.observers = [];
this.observers = new Map();
this.obj = obj;
}
return Mirror;
Expand All @@ -757,26 +757,13 @@ var ObserverInfo = (function () {
return ObserverInfo;
}());
function getMirror(obj) {
for (var i = 0, length = beforeDict.length; i < length; i++) {
if (beforeDict[i].obj === obj) {
return beforeDict[i];
}
}
return beforeDict.get(obj);
}
function getObserverFromMirror(mirror, callback) {
for (var j = 0, length = mirror.observers.length; j < length; j++) {
if (mirror.observers[j].callback === callback) {
return mirror.observers[j].observer;
}
}
return mirror.observers.get(callback);
}
function removeObserverFromMirror(mirror, observer) {
for (var j = 0, length = mirror.observers.length; j < length; j++) {
if (mirror.observers[j].observer === observer) {
mirror.observers.splice(j, 1);
return;
}
}
mirror.observers.delete(observer.callback);
}
/**
* Detach an observer from an object
Expand All @@ -790,15 +777,15 @@ exports.unobserve = unobserve;
*/
function observe(obj, callback) {
var patches = [];
var root = obj;
var observer;
var mirror = getMirror(obj);
if (!mirror) {
mirror = new Mirror(obj);
beforeDict.push(mirror);
beforeDict.set(obj, mirror);
}
else {
observer = getObserverFromMirror(mirror, callback);
var observerInfo = getObserverFromMirror(mirror, callback);
observer = observerInfo && observerInfo.observer;
}
if (observer) {
return observer;
Expand Down Expand Up @@ -853,21 +840,15 @@ function observe(obj, callback) {
}
}
};
mirror.observers.push(new ObserverInfo(callback, observer));
mirror.observers.set(callback, new ObserverInfo(callback, observer));
return observer;
}
exports.observe = observe;
/**
* Generate an array of patches from an observer
*/
function generate(observer) {
var mirror;
for (var i = 0, length = beforeDict.length; i < length; i++) {
if (beforeDict[i].obj === observer.object) {
mirror = beforeDict[i];
break;
}
}
var mirror = beforeDict.get(observer.object);
_generate(mirror.value, observer.object, observer.patches, "");
if (observer.patches.length) {
core_1.applyPatch(mirror.value, observer.patches);
Expand Down
4 changes: 2 additions & 2 deletions dist/fast-json-patch.min.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "fast-json-patch",
"version": "2.0.6",
"version": "2.0.7",
"description": "Fast implementation of JSON-Patch (RFC-6902) with duplex (observe changes) capabilities",
"homepage": "https://github.com/Starcounter-Jack/JSON-Patch",
"keywords": [
Expand Down
60 changes: 21 additions & 39 deletions src/duplex.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,50 +26,38 @@ export interface Observer<T> {
callback: (patches: Operation[]) => void;
}

var beforeDict = [];
var beforeDict = new WeakMap();

class Mirror {
obj: any;
observers = [];
observers : Map<Function, ObserverInfo> = new Map();
value: Object | Array<any>;

constructor(obj: any) {
constructor(obj: Object) {
this.obj = obj;
}
}

class ObserverInfo {
callback: any;
observer: any;
callback: Function;
observer: ObserverInfo;

constructor(callback, observer) {
constructor(callback: Function, observer: ObserverInfo) {
this.callback = callback;
this.observer = observer;
}
}

function getMirror(obj: any): any {
for (var i = 0, length = beforeDict.length; i < length; i++) {
if (beforeDict[i].obj === obj) {
return beforeDict[i];
}
}
function getMirror(obj: Object): Mirror {
return beforeDict.get(obj);
}

function getObserverFromMirror(mirror: any, callback): any {
for (var j = 0, length = mirror.observers.length; j < length; j++) {
if (mirror.observers[j].callback === callback) {
return mirror.observers[j].observer;
}
}
function getObserverFromMirror(mirror: Mirror, callback): ObserverInfo {
return mirror.observers.get(callback)
}

function removeObserverFromMirror(mirror: any, observer): any {
for (var j = 0, length = mirror.observers.length; j < length; j++) {
if (mirror.observers[j].observer === observer) {
mirror.observers.splice(j, 1);
return;
}
}
function removeObserverFromMirror(mirror: Mirror, observer): void {
mirror.observers.delete(observer.callback);
}

/**
Expand All @@ -82,17 +70,17 @@ export function unobserve<T>(root: T, observer: Observer<T>) {
/**
* Observes changes made to an object, which can then be retrieved using generate
*/
export function observe<T>(obj: any, callback?: (patches: Operation[]) => void): Observer<T> {
export function observe<T>(obj: Object|Array<T>, callback?: (patches: Operation[]) => void): Observer<T> {
var patches = [];
var root = obj;
var observer;
var mirror = getMirror(obj);

if (!mirror) {
mirror = new Mirror(obj);
beforeDict.push(mirror);
beforeDict.set(obj, mirror);
} else {
observer = getObserverFromMirror(mirror, callback);
const observerInfo = getObserverFromMirror(mirror, callback);
observer = observerInfo && observerInfo.observer;
}

if (observer) {
Expand Down Expand Up @@ -155,22 +143,16 @@ export function observe<T>(obj: any, callback?: (patches: Operation[]) => void):
}
};

mirror.observers.push(new ObserverInfo(callback, observer));
mirror.observers.set(callback, new ObserverInfo(callback, observer));

return observer;
}

/**
* Generate an array of patches from an observer
*/
export function generate<T>(observer: Observer<T>): Operation[] {
var mirror;
for (var i = 0, length = beforeDict.length; i < length; i++) {
if (beforeDict[i].obj === observer.object) {
mirror = beforeDict[i];
break;
}
}
export function generate<T>(observer: Observer<Object>): Operation[] {
var mirror = beforeDict.get(observer.object);
_generate(mirror.value, observer.object, observer.patches, "");
if (observer.patches.length) {
applyPatch(mirror.value, observer.patches);
Expand Down Expand Up @@ -237,7 +219,7 @@ function _generate(mirror, obj, patches, path) {
/**
* Create an array of patches from the differences in two objects
*/
export function compare(tree1: any, tree2: any): Operation[] {
export function compare(tree1: Object | Array<any>, tree2: Object | Array<any>): Operation[] {
var patches = [];
_generate(tree1, tree2, patches, '');
return patches;
Expand Down
3 changes: 3 additions & 0 deletions tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@
"target": "es5",
"outDir": "lib/",
"module": "commonjs",
"lib": [
"es2016", "dom"
],
"noEmitHelpers": false,
"declaration": true,
"removeComments": false,
Expand Down

0 comments on commit 0d6be6a

Please sign in to comment.