Skip to content

Commit

Permalink
v2.0.0. Added ability to pause and resume notifications. Changed Gawk…
Browse files Browse the repository at this point in the history
…Event 'target' to 'targets' and now it's an array of targets.
  • Loading branch information
cb1kenobi committed Jul 2, 2016
1 parent f6d2a17 commit fe621a6
Show file tree
Hide file tree
Showing 10 changed files with 133 additions and 3,096 deletions.
3,044 changes: 0 additions & 3,044 deletions npm-shrinkwrap.json

This file was deleted.

13 changes: 6 additions & 7 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "gawk",
"version": "1.8.0",
"version": "2.0.0",
"description": "Observable JavaScript object model",
"main": "./dist/index.js",
"author": "Chris Barber <[email protected]> (https://github.com/cb1kenobi)",
Expand All @@ -19,25 +19,24 @@
"build": "gulp build",
"coverage": "gulp coverage",
"docs": "gulp docs",
"prepublish": "gulp build && in-publish && npm shrinkwrap || not-in-publish",
"prepublish": "gulp build",
"test": "gulp test"
},
"dependencies": {
"in-publish": "^2.0.0",
"object-hash": "^1.1.2",
"source-map-support": "^0.4.0"
"source-map-support": "^0.4.1"
},
"devDependencies": {
"babel-eslint": "^6.0.4",
"babel-eslint": "^6.1.0",
"babel-preset-nodejs-lts": "^1.2.2",
"chai": "^3.5.0",
"codeclimate-test-reporter": "^0.3.3",
"coveralls": "^2.11.9",
"del": "^2.2.0",
"del": "^2.2.1",
"esdoc-es7-plugin": "^0.0.3",
"gulp": "^3.9.1",
"gulp-babel": "^6.1.2",
"gulp-babel-istanbul": "^1.3.1",
"gulp-babel-istanbul": "^1.4.0",
"gulp-debug": "^2.1.2",
"gulp-esdoc": "^0.2.0",
"gulp-eslint": "^2.0.0",
Expand Down
90 changes: 72 additions & 18 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -69,9 +69,9 @@ export { gawk as gawk };
* Event class.
*/
export class GawkEvent {
constructor({ source, target, type }) {
constructor({ source, targets, type }) {
this.source = source;
this.target = target;
this.targets = targets;
this.type = type;
}
}
Expand Down Expand Up @@ -129,7 +129,23 @@ export class GawkBase {
* @type {Array}
* @access private
*/
_watchers: { value: [], writable: true }
_watchers: { value: [], writable: true },

/**
* An internal flag that if true when `resume()` is called, it sends
* out notifications if anything changed while paused.
* @type {Boolean}
* @access private
*/
_paused: { value: 0, writable: true },

/**
* When set to a GawkEvent, then we are paused until `resume()` is
* been called.
* @type {GawkEvent|null}
* @access private
*/
_pausedEvent: { value: null, writable: true }
});
}

Expand Down Expand Up @@ -231,6 +247,36 @@ export class GawkBase {
// noop
}

/**
* Sets the paused flag which pauses change notifications from being sent to
* watchers and parents.
* @access public
*/
pause() {
this._paused = true;
}

/**
* Sets the paused flag which pauses change notifications from being sent to
* watchers and parents.
* @access public
*/
resume() {
const evt = this._paused && this._pausedEvent;
this._paused = false;
if (evt) {
// send notifications
for (const w of this._watchers) {
w(evt);
}

for (const p of this._parents) {
p.notify(evt);
}
}
this._pausedEvent = null;
}

/**
* Notifies watchers and the parent gawk object when this object changes.
* @param {*|GawkEvent} [newValue] - When value is a GawkEvent, that means
Expand Down Expand Up @@ -262,18 +308,32 @@ export class GawkBase {
this._value = newValue;
}

const targets = arguments.length && newValue instanceof GawkEvent ? newValue.targets : [ this ];

if (this._paused && this._pausedEvent) {
for (const target of targets) {
if (this._pausedEvent.targets.indexOf(target) === -1) {
this._pausedEvent.targets.push(target);
}
}
return;
}

const evt = new GawkEvent({
source: this,
target: arguments.length && newValue instanceof GawkEvent ? newValue.target : this,
targets: targets,
type: 'change'
});

for (const w of this._watchers) {
w(evt);
}

for (const p of this._parents) {
p.notify(evt);
if (!this._paused) {
for (const w of this._watchers) {
w(evt);
}
for (const p of this._parents) {
p.notify(evt);
}
} else if (!this._pausedEvent) {
this._pausedEvent = evt;
}
}

Expand Down Expand Up @@ -994,10 +1054,7 @@ export class GawkObject extends GawkBase {

// we need to detach the parent and all watchers so that they will be
// notified after everything has been merged
const parents = this._parents;
const watchers = this._watchers;
this._parents = [];
this._watchers = [];
this.pause();

let changed = false;

Expand Down Expand Up @@ -1044,11 +1101,8 @@ export class GawkObject extends GawkBase {
this._hash = 'gawk rocks';
}

// restore the parent and the watchers
this._parents = parents;
this._watchers = watchers;

this.notify();
this.resume();

return this;
}
Expand Down
12 changes: 6 additions & 6 deletions test/test-array.js
Original file line number Diff line number Diff line change
Expand Up @@ -320,9 +320,9 @@ describe('array', () => {

garr.watch(evt => {
expect(evt.source).to.equal(garr);
expect(evt.target).to.equal(garr);
expect(evt.targets).to.deep.equal([ garr ]);

const val = evt.target.val;
const val = evt.targets[0].val;
expect(val).to.be.an.array;
expect(val).to.deep.equal(arr);
});
Expand Down Expand Up @@ -380,7 +380,7 @@ describe('array', () => {
expect(count).to.equal(4);
});

it('should be notified when deeply nexted children change', () => {
it('should be notified when deeply nested children change', () => {
let count1 = 0;
let count2 = 0;
let count3 = 0;
Expand All @@ -401,19 +401,19 @@ describe('array', () => {
arr1.watch(evt => {
count1++;
expect(evt.source).to.equal(arr1);
expect(evt.target).to.equal(arr3);
expect(evt.targets).to.deep.equal([ arr3 ]);
});

arr2.watch(evt => {
count2++;
expect(evt.source).to.equal(arr2);
expect(evt.target).to.equal(arr3);
expect(evt.targets).to.deep.equal([ arr3 ]);
});

arr3.watch(evt => {
count3++;
expect(evt.source).to.equal(arr3);
expect(evt.target).to.equal(arr3);
expect(evt.targets).to.deep.equal([ arr3 ]);
});

arr3.push('foo');
Expand Down
4 changes: 2 additions & 2 deletions test/test-boolean.js
Original file line number Diff line number Diff line change
Expand Up @@ -127,9 +127,9 @@ describe('boolean', () => {
const bool = gawk(true);

bool.watch(evt => {
expect(evt.target).to.equal(bool);
expect(evt.targets[0]).to.equal(bool);

const val = evt.target.val;
const val = evt.targets[0].val;
expect(val).to.be.a.boolean;
expect(val).to.equal(false);
});
Expand Down
4 changes: 2 additions & 2 deletions test/test-date.js
Original file line number Diff line number Diff line change
Expand Up @@ -114,9 +114,9 @@ describe('date', () => {
const now = new Date;

date.watch(evt => {
expect(evt.target).to.equal(date);
expect(evt.targets).to.deep.equal([ date ]);

const val = evt.target.val;
const val = evt.targets[0].val;
expect(val).to.be.a.date;
expect(val).to.equal(now);
});
Expand Down
4 changes: 2 additions & 2 deletions test/test-function.js
Original file line number Diff line number Diff line change
Expand Up @@ -146,9 +146,9 @@ describe('function', () => {
const fn = gawk(function () {});

fn.watch(evt => {
expect(evt.target).to.equal(fn);
expect(evt.targets[0]).to.equal(fn);

const val = evt.target.val;
const val = evt.targets[0].val;
expect(val).to.be.a.function;
expect(val).to.equal(foo);
});
Expand Down
4 changes: 2 additions & 2 deletions test/test-number.js
Original file line number Diff line number Diff line change
Expand Up @@ -153,9 +153,9 @@ describe('number', () => {
const num = gawk(123);

num.watch(evt => {
expect(evt.target).to.equal(num);
expect(evt.targets[0]).to.equal(num);

const val = evt.target.val;
const val = evt.targets[0].val;
expect(val).to.be.a.number;
expect(val).to.equal(456);
});
Expand Down
50 changes: 39 additions & 11 deletions test/test-object.js
Original file line number Diff line number Diff line change
Expand Up @@ -452,9 +452,9 @@ describe('object', () => {
const gobj = gawk({ foo: 'bar' });
gobj.watch(evt => {
expect(evt.source).to.equal(gobj);
expect(evt.target).to.equal(gobj);
expect(evt.targets).to.deep.equal([ gobj ]);

const obj = evt.target.val;
const obj = evt.targets[0].val;
expect(obj).to.deep.equal({ bar: 'wiz' });
});
gobj.val = { bar: 'wiz' };
Expand All @@ -464,9 +464,9 @@ describe('object', () => {
const gobj = gawk({ foo: 'bar' });
gobj.watch(evt => {
expect(evt.source).to.equal(gobj);
expect(evt.target).to.equal(gobj);
expect(evt.targets).to.deep.equal([ gobj ]);

const obj = evt.target.val;
const obj = evt.targets[0].val;
expect(obj).to.deep.equal({ foo: 'bar', pi: 3.14 });
});
gobj.set('pi', 3.14);
Expand All @@ -476,9 +476,9 @@ describe('object', () => {
const gobj = gawk({ foo: 'bar' });
gobj.watch(evt => {
expect(evt.source).to.equal(gobj);
expect(evt.target).to.equal(gobj);
expect(evt.targets).to.deep.equal([ gobj ]);

const obj = evt.target.val;
const obj = evt.targets[0].val;
expect(obj).to.deep.equal({ foo: 'wiz' });
});
gobj.set('foo', 'wiz');
Expand All @@ -488,9 +488,9 @@ describe('object', () => {
const gobj = gawk({ foo: 'bar', pi: 3.14 });
gobj.watch(evt => {
expect(evt.source).to.equal(gobj);
expect(evt.target).to.equal(gobj);
expect(evt.targets).to.deep.equal([ gobj ]);

const obj = evt.target.val;
const obj = evt.targets[0].val;
expect(obj).to.deep.equal({ foo: 'bar' });
});
gobj.delete('pi');
Expand All @@ -508,9 +508,9 @@ describe('object', () => {
const gobj = gawk({ foo: 'bar', pi: 3.14 });
gobj.watch(evt => {
expect(evt.source).to.equal(gobj);
expect(evt.target).to.equal(gobj);
expect(evt.targets).to.deep.equal([ gobj ]);

const obj = evt.target.val;
const obj = evt.targets[0].val;
expect(obj).to.be.an.object;
expect(obj).to.deep.equal({});
});
Expand Down Expand Up @@ -557,7 +557,7 @@ describe('object', () => {

gobj.watch(evt => {
expect(evt.source).to.equal(gobj);
expect(evt.target).to.equal(nested);
expect(evt.targets).to.deep.equal([ nested ]);

const obj = evt.source.val;
expect(obj).to.be.an.object;
Expand Down Expand Up @@ -689,5 +689,33 @@ describe('object', () => {
arr.push('b');
expect(count).to.equal(6);
});

it('should pause and resume notifications', () => {
const gobj = gawk({ foo: 'bar' });
let counter = 0;

gobj.watch(evt => {
counter++;
});

gobj.set('pi', 3.14);
expect(counter).to.equal(1);

const gobj2 = new GawkObject({ wiz: 123 });

gobj.pause();
gobj.set('baz', gobj2);
expect(counter).to.equal(1);
gobj.resume();
expect(counter).to.equal(2);

gobj.pause();
gobj.set('color', 'red');
expect(counter).to.equal(2);
gobj2.set('lorum', 'ipsum');
expect(counter).to.equal(2);
gobj.resume();
expect(counter).to.equal(3);
});
});
});
4 changes: 2 additions & 2 deletions test/test-string.js
Original file line number Diff line number Diff line change
Expand Up @@ -107,9 +107,9 @@ describe('string', () => {
const str = gawk('foo');

str.watch(evt => {
expect(evt.target).to.equal(str);
expect(evt.targets).to.deep.equal([ str ]);

const val = evt.target.val;
const val = evt.targets[0].val;
expect(val).to.be.a.string;
expect(val).to.equal('bar');
});
Expand Down

0 comments on commit fe621a6

Please sign in to comment.