-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Andrea Giammarchi
committed
Mar 16, 2017
1 parent
972feeb
commit 98a6319
Showing
9 changed files
with
276 additions
and
276 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,261 @@ | ||
/*! (C) Andrea Giammarchi Mit Style License */ | ||
var notify=function(){function e(t){"use strict";function l(e){return i.call(r,e)?r[e]:r[e]={args:null,cb:[]}}function c(e){var t=arguments.length,n=l(e),r=1,i;if(r===t)return function(){var t=[e];return t.push.apply(t,arguments),c.apply(null,t)};n.args=[];while(r<t)n.args.push(arguments[r++]);r=0,t=n.cb.length,i=n.cb.splice(r,t);while(r<t)a(n.args).then(o.call(s,i[r++]));return n.args[0]}function h(e,t){var r=l(e),i;return arguments.length===1&&(i=new Promise(function(e){t=e})),n&&r.args?a(r.args).then(o.call(s,t)):u.call(r.cb,t)<0&&r.cb.push(t),i}var n=!0,r=(t.create||t)(null),i=t.prototype.hasOwnProperty,s=function(e){this.apply(null,e)},o=t.bind||function(e){var t=this;return function(){return t.apply(e,arguments)}},u=Array.prototype.indexOf||function(t){var n=this.length;while(n--&&this[n]!==t);return n},a=typeof Promise=="undefined"?function(e){return{then:function(t){setTimeout(t,1,e)}}}:function(e){return Promise.resolve(e)},f=typeof WeakMap=="undefined"?function(e,t,n){return{"delete":function(r){n=u.call(e,r),~n&&(e.splice(n,1),t.splice(n,1))},get:function(n){return t[u.call(e,n)]},set:function(r,i){n=u.call(e,r),t[n<0?e.push(r)-1:n]=i}}}([],[],0):new WeakMap;return(t.freeze||t)({when:h,about:c,that:c,drop:function p(e,t){var n=f.get(t),r,i;n?(f["delete"](t),p(e,n)):(r=l(e).cb,i=u.call(r,t),~i&&r.splice(i,1))},"new":function(){return e(t)},all:function(t,r){f.get(r)||(f.set(r,function i(){n=!1,h(t,i),n=!0,a(arguments).then(o.call(s,r))}),h(t,f.get(r)))}})}return e(Object)}(); | ||
/*! | ||
Copyright (C) 2015-2017 by Andrea Giammarchi | ||
Permission is hereby granted, free of charge, to any person obtaining a copy | ||
of this software and associated documentation files (the "Software"), to deal | ||
in the Software without restriction, including without limitation the rights | ||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
copies of the Software, and to permit persons to whom the Software is | ||
furnished to do so, subject to the following conditions: | ||
The above copyright notice and this permission notice shall be included in | ||
all copies or substantial portions of the Software. | ||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||
THE SOFTWARE. | ||
*/ | ||
var broadcast = (function () { | ||
/** | ||
* // assuming "data" event hasn't happened yet | ||
* broadcast.when("data", function (data) { | ||
* console.log(data); | ||
* }); | ||
* | ||
* // whenever it will happen | ||
* broadcast.that("data", {any:'value'}); | ||
* // all listeners waiting for it, will be triggered | ||
* | ||
* | ||
* // what if you add a listener after the `.about` call? | ||
* broadcast.when("data", function (data) { | ||
* console.log('yep, instantly called!', data); | ||
* }); | ||
* | ||
* | ||
* // what if we redefine data ? | ||
* broadcast.about("data", {another:'value'}); | ||
* // from now on, whoever will ask `.when` data | ||
* // the value will be the updated one | ||
* // but every listener already fired and satisfied | ||
* // will be simply ignored | ||
* | ||
* | ||
* // what if I want to be sure the channel is private? | ||
* // feel free to use a Symbol as channel | ||
* var myPrivateSymbol = Symbol(); | ||
* broadcast.when(myPrivateSymbol, ...); | ||
* | ||
* // otherwise create a new broadcast like variable | ||
* var privateBroadcast = broadcast.new(); | ||
*/ | ||
function create(O) {'use strict'; | ||
|
||
var | ||
// flag for internal operations (used by all) | ||
invoke = true, | ||
// create a dictionary, fallback as regular object | ||
_ = (O.create || O)(null), | ||
// dictionaries don't have this method, borrow it | ||
hOP = O.prototype.hasOwnProperty, | ||
// will invoke the callback within the Promise | ||
broadcast = function (args) { | ||
this.apply(null, args); | ||
}, | ||
// IE < 9 doesn't have this method, sham it | ||
bind = O.bind || function (self) { | ||
var cb = this; | ||
return function () { | ||
return cb.apply(self, arguments); | ||
}; | ||
}, | ||
// IE < 9 doesn't have this method, sham it | ||
indexOf = Array.prototype.indexOf || function indexOf(v) { | ||
var i = this.length; | ||
while (i-- && this[i] !== v) {} | ||
return i; | ||
}, | ||
resolve = typeof Promise == 'undefined' ? | ||
function (value) { | ||
return {then: function (cb) { | ||
setTimeout(cb, 1, value); | ||
}}; | ||
} : | ||
function (value) { | ||
return Promise.resolve(value); | ||
}, | ||
// little WeakMap poly | ||
wm = typeof WeakMap == 'undefined' ? | ||
(function (k, v, i) { | ||
return { | ||
// delete used to be a reserved property name | ||
'delete': function (x) { | ||
i = indexOf.call(k, x); | ||
if (~i) { | ||
k.splice(i, 1); | ||
v.splice(i, 1); | ||
} | ||
}, | ||
get: function (x) { | ||
return v[indexOf.call(k, x)]; | ||
}, | ||
set: function (x, y) { | ||
i = indexOf.call(k, x); | ||
v[i < 0 ? (k.push(x) - 1) : i] = y; | ||
} | ||
}; | ||
}([], [], 0)) : | ||
new WeakMap() | ||
; | ||
|
||
// check if a private _[type] is known | ||
// if not, create the info object | ||
// returns such object either cases | ||
function get(type) { | ||
return hOP.call(_, type) ? | ||
_[type] : | ||
(_[type] = { | ||
args: null, | ||
cb: [] | ||
}); | ||
} | ||
|
||
function that(type) { | ||
var | ||
len = arguments.length, | ||
info = get(type), | ||
i = 1, | ||
cb | ||
; | ||
// in case it's invoked | ||
// without any error or value | ||
if (i === len) { | ||
// creates a callback | ||
// that once invoked will resolve | ||
return function () { | ||
var args = [type]; | ||
args.push.apply(args, arguments); | ||
return that.apply(null, args); | ||
}; | ||
} | ||
// in every other case | ||
// resolve the type with any amount | ||
// of arguments received | ||
else { | ||
info.args = []; | ||
while (i < len) info.args.push(arguments[i++]); | ||
i = 0; | ||
len = info.cb.length; | ||
// be sure the list of waiting listeners | ||
// will be cleaned up so these won't | ||
// every be notified more than once | ||
// ( unless these are passed again via `.when` ) | ||
// NOTE: .splice(0) would be enough | ||
// but IE8 wants the length too | ||
cb = info.cb.splice(i, len); | ||
while (i < len) resolve(info.args).then(bind.call(broadcast, cb[i++])); | ||
} | ||
return info.args[0]; | ||
} | ||
|
||
function when(type, callback) { | ||
var info = get(type), out; | ||
if (arguments.length === 1) { | ||
out = new Promise(function (resolve) { | ||
callback = resolve; | ||
}); | ||
} | ||
if (invoke && info.args) { | ||
resolve(info.args).then(bind.call(broadcast, callback)); | ||
} else if(indexOf.call(info.cb, callback) < 0) { | ||
info.cb.push(callback); | ||
} | ||
return out; | ||
} | ||
|
||
// freeze, if possible, the broadcast object | ||
// to be sure no other scripts can change its methods | ||
return (O.freeze || O)({ | ||
|
||
// There are two ways to use this method | ||
// | ||
// .when(type, callback) | ||
// add a listener to a generic type | ||
// whenever such type will happen | ||
// or if it happened already | ||
// invoke the callback with the resolved value | ||
// | ||
// .when(type) | ||
// return a new Promise that will be resolved | ||
// once the notification will happen | ||
// | ||
// broadcast.when('event').then(function (data) { ... }); | ||
// | ||
when: when, | ||
|
||
// .about is an alias for .that | ||
// There are two ways to use this method | ||
// | ||
// .about(type) | ||
// will return a callback | ||
// that will try to resolve once executed | ||
// fs.readFile('setup.json', broadcast.about('setup.json')) | ||
// | ||
// overload | ||
// .that(type, any1[, any2[, ...]]) | ||
// resolve type passing anyValue around | ||
// | ||
// // through one argument | ||
// broadcast.that('some-event', {all: 'good'}); | ||
// // through more arguments | ||
// broadcast.that('some-event', null, 'OK'); | ||
// | ||
about: that, | ||
that: that, | ||
|
||
// if we set a listener through `.when` | ||
// and this hasn't been notified yet | ||
// but we changed our mind about such notification | ||
// we can still remove such listener via `.drop` | ||
drop: function drop(type, callback) { | ||
var fn = wm.get(callback), cb, i; | ||
if (fn) { | ||
wm['delete'](callback); | ||
drop(type, fn); | ||
} else { | ||
cb = get(type).cb; | ||
i = indexOf.call(cb, callback); | ||
if (~i) cb.splice(i, 1); | ||
} | ||
}, | ||
|
||
// create a new broadcast-like object | ||
'new': function () { | ||
return create(O); | ||
}, | ||
|
||
// in case we'd like to react each time | ||
// to a specific event. | ||
// In this case a callback is mandatory, | ||
// and it's also needed to eventually drop. | ||
all: function all(type, callback) { | ||
if (!wm.get(callback)) { | ||
wm.set(callback, function fn() { | ||
invoke = false; | ||
when(type, fn); | ||
invoke = true; | ||
resolve(arguments).then(bind.call(broadcast, callback)); | ||
}); | ||
when(type, wm.get(callback)); | ||
} | ||
} | ||
}); | ||
} | ||
return create(Object); | ||
|
||
}()); |
Oops, something went wrong.