|
2 | 2 | v0.8.1 (c) Kyle Simpson |
3 | 3 | MIT License: http://getify.mit-license.org |
4 | 4 | */ |
5 | | -!function(t,n,e){n[t]=n[t]||e(),"undefined"!=typeof module&&module.exports?module.exports=n[t]:"function"==typeof define&&define.amd&&define(function(){return n[t]})}("Promise","undefined"!=typeof global?global:this,function(){"use strict";function t(t,n){l.add(t,n),h||(h=y(l.drain))}function n(t){var n,e=typeof t;return null==t||"object"!=e&&"function"!=e||(n=t.then),"function"==typeof n?n:!1}function e(){for(var t=0;t<this.chain.length;t++)o(this,1===this.state?this.chain[t].success:this.chain[t].failure,this.chain[t]);this.chain.length=0}function o(t,e,o){var r,i;try{e===!1?o.reject(t.msg):(r=e===!0?t.msg:e.call(void 0,t.msg),r===o.promise?o.reject(TypeError("Promise-chain cycle")):(i=n(r))?i.call(r,o.resolve,o.reject):o.resolve(r))}catch(c){o.reject(c)}}function r(o){var c,u=this;if(!u.triggered){u.triggered=!0,u.def&&(u=u.def);try{(c=n(o))?t(function(){var t=new f(u);try{c.call(o,function(){r.apply(t,arguments)},function(){i.apply(t,arguments)})}catch(n){i.call(t,n)}}):(u.msg=o,u.state=1,u.chain.length>0&&t(e,u))}catch(a){i.call(new f(u),a)}}}function i(n){var o=this;o.triggered||(o.triggered=!0,o.def&&(o=o.def),o.msg=n,o.state=2,o.chain.length>0&&t(e,o))}function c(t,n,e,o){for(var r=0;r<n.length;r++)!function(r){t.resolve(n[r]).then(function(t){e(r,t)},o)}(r)}function f(t){this.def=t,this.triggered=!1}function u(t){this.promise=t,this.state=0,this.triggered=!1,this.chain=[],this.msg=void 0}function a(n){if("function"!=typeof n)throw TypeError("Not a function");if(0!==this.__NPO__)throw TypeError("Not a promise");this.__NPO__=1;var o=new u(this);this.then=function(n,r){var i={success:"function"==typeof n?n:!0,failure:"function"==typeof r?r:!1};return i.promise=new this.constructor(function(t,n){if("function"!=typeof t||"function"!=typeof n)throw TypeError("Not a function");i.resolve=t,i.reject=n}),o.chain.push(i),0!==o.state&&t(e,o),i.promise},this["catch"]=function(t){return this.then(void 0,t)};try{n.call(void 0,function(t){r.call(o,t)},function(t){i.call(o,t)})}catch(c){i.call(o,c)}}var s,h,l,p=Object.prototype.toString,y="undefined"!=typeof setImmediate?function(t){return setImmediate(t)}:setTimeout;try{Object.defineProperty({},"x",{}),s=function(t,n,e,o){return Object.defineProperty(t,n,{value:e,writable:!0,configurable:o!==!1})}}catch(d){s=function(t,n,e){return t[n]=e,t}}l=function(){function t(t,n){this.fn=t,this.self=n,this.next=void 0}var n,e,o;return{add:function(r,i){o=new t(r,i),e?e.next=o:n=o,e=o,o=void 0},drain:function(){var t=n;for(n=e=h=void 0;t;)t.fn.call(t.self),t=t.next}}}();var g=s({},"constructor",a,!1);return a.prototype=g,s(g,"__NPO__",0,!1),s(a,"resolve",function(t){var n=this;return t&&"object"==typeof t&&1===t.__NPO__?t:new n(function(n,e){if("function"!=typeof n||"function"!=typeof e)throw TypeError("Not a function");n(t)})}),s(a,"reject",function(t){return new this(function(n,e){if("function"!=typeof n||"function"!=typeof e)throw TypeError("Not a function");e(t)})}),s(a,"all",function(t){var n=this;return"[object Array]"!=p.call(t)?n.reject(TypeError("Not an array")):0===t.length?n.resolve([]):new n(function(e,o){if("function"!=typeof e||"function"!=typeof o)throw TypeError("Not a function");var r=t.length,i=Array(r),f=0;c(n,t,function(t,n){i[t]=n,++f===r&&e(i)},o)})}),s(a,"race",function(t){var n=this;return"[object Array]"!=p.call(t)?n.reject(TypeError("Not an array")):new n(function(e,o){if("function"!=typeof e||"function"!=typeof o)throw TypeError("Not a function");c(n,t,function(t,n){e(n)},o)})}),a}); |
| 5 | + |
| 6 | +(function UMD(name,context,definition){ |
| 7 | + // special form of UMD for polyfilling across evironments |
| 8 | + context[name] = context[name] || definition(); |
| 9 | + if (typeof module != "undefined" && module.exports) { module.exports = context[name]; } |
| 10 | + else if (typeof define == "function" && define.amd) { define(function $AMD$(){ return context[name]; }); } |
| 11 | +})("Promise",typeof global != "undefined" ? global : this,function DEF(){ |
| 12 | + /*jshint validthis:true */ |
| 13 | + "use strict"; |
| 14 | + |
| 15 | + var builtInProp, cycle, scheduling_queue, |
| 16 | + ToString = Object.prototype.toString, |
| 17 | + timer = (typeof setImmediate != "undefined") ? |
| 18 | + function timer(fn) { return setImmediate(fn); } : |
| 19 | + setTimeout |
| 20 | + ; |
| 21 | + |
| 22 | + // dammit, IE8. |
| 23 | + try { |
| 24 | + Object.defineProperty({},"x",{}); |
| 25 | + builtInProp = function builtInProp(obj,name,val,config) { |
| 26 | + return Object.defineProperty(obj,name,{ |
| 27 | + value: val, |
| 28 | + writable: true, |
| 29 | + configurable: config !== false |
| 30 | + }); |
| 31 | + }; |
| 32 | + } |
| 33 | + catch (err) { |
| 34 | + builtInProp = function builtInProp(obj,name,val) { |
| 35 | + obj[name] = val; |
| 36 | + return obj; |
| 37 | + }; |
| 38 | + } |
| 39 | + |
| 40 | + // Note: using a queue instead of array for efficiency |
| 41 | + scheduling_queue = (function Queue() { |
| 42 | + var first, last, item; |
| 43 | + |
| 44 | + function Item(fn,self) { |
| 45 | + this.fn = fn; |
| 46 | + this.self = self; |
| 47 | + this.next = void 0; |
| 48 | + } |
| 49 | + |
| 50 | + return { |
| 51 | + add: function add(fn,self) { |
| 52 | + item = new Item(fn,self); |
| 53 | + if (last) { |
| 54 | + last.next = item; |
| 55 | + } |
| 56 | + else { |
| 57 | + first = item; |
| 58 | + } |
| 59 | + last = item; |
| 60 | + item = void 0; |
| 61 | + }, |
| 62 | + drain: function drain() { |
| 63 | + var f = first; |
| 64 | + first = last = cycle = void 0; |
| 65 | + |
| 66 | + while (f) { |
| 67 | + f.fn.call(f.self); |
| 68 | + f = f.next; |
| 69 | + } |
| 70 | + } |
| 71 | + }; |
| 72 | + })(); |
| 73 | + |
| 74 | + function schedule(fn,self) { |
| 75 | + scheduling_queue.add(fn,self); |
| 76 | + if (!cycle) { |
| 77 | + cycle = timer(scheduling_queue.drain); |
| 78 | + } |
| 79 | + } |
| 80 | + |
| 81 | + // promise duck typing |
| 82 | + function isThenable(o) { |
| 83 | + var _then, o_type = typeof o; |
| 84 | + |
| 85 | + if (o != null && |
| 86 | + ( |
| 87 | + o_type == "object" || o_type == "function" |
| 88 | + ) |
| 89 | + ) { |
| 90 | + _then = o.then; |
| 91 | + } |
| 92 | + return typeof _then == "function" ? _then : false; |
| 93 | + } |
| 94 | + |
| 95 | + function notify() { |
| 96 | + for (var i=0; i<this.chain.length; i++) { |
| 97 | + notifyIsolated( |
| 98 | + this, |
| 99 | + (this.state === 1) ? this.chain[i].success : this.chain[i].failure, |
| 100 | + this.chain[i] |
| 101 | + ); |
| 102 | + } |
| 103 | + this.chain.length = 0; |
| 104 | + } |
| 105 | + |
| 106 | + // NOTE: This is a separate function to isolate |
| 107 | + // the `try..catch` so that other code can be |
| 108 | + // optimized better |
| 109 | + function notifyIsolated(self,cb,chain) { |
| 110 | + var ret, _then; |
| 111 | + try { |
| 112 | + if (cb === false) { |
| 113 | + chain.reject(self.msg); |
| 114 | + } |
| 115 | + else { |
| 116 | + if (cb === true) { |
| 117 | + ret = self.msg; |
| 118 | + } |
| 119 | + else { |
| 120 | + ret = cb.call(void 0,self.msg); |
| 121 | + } |
| 122 | + |
| 123 | + if (ret === chain.promise) { |
| 124 | + chain.reject(TypeError("Promise-chain cycle")); |
| 125 | + } |
| 126 | + else if (_then = isThenable(ret)) { |
| 127 | + _then.call(ret,chain.resolve,chain.reject); |
| 128 | + } |
| 129 | + else { |
| 130 | + chain.resolve(ret); |
| 131 | + } |
| 132 | + } |
| 133 | + } |
| 134 | + catch (err) { |
| 135 | + chain.reject(err); |
| 136 | + } |
| 137 | + } |
| 138 | + |
| 139 | + function resolve(msg) { |
| 140 | + var _then, self = this; |
| 141 | + |
| 142 | + // already triggered? |
| 143 | + if (self.triggered) { return; } |
| 144 | + |
| 145 | + self.triggered = true; |
| 146 | + |
| 147 | + // unwrap |
| 148 | + if (self.def) { |
| 149 | + self = self.def; |
| 150 | + } |
| 151 | + |
| 152 | + try { |
| 153 | + if (_then = isThenable(msg)) { |
| 154 | + schedule(function(){ |
| 155 | + var def_wrapper = new MakeDefWrapper(self); |
| 156 | + try { |
| 157 | + _then.call(msg, |
| 158 | + function $resolve$(){ resolve.apply(def_wrapper,arguments); }, |
| 159 | + function $reject$(){ reject.apply(def_wrapper,arguments); } |
| 160 | + ); |
| 161 | + } |
| 162 | + catch (err) { |
| 163 | + reject.call(def_wrapper,err); |
| 164 | + } |
| 165 | + }) |
| 166 | + } |
| 167 | + else { |
| 168 | + self.msg = msg; |
| 169 | + self.state = 1; |
| 170 | + if (self.chain.length > 0) { |
| 171 | + schedule(notify,self); |
| 172 | + } |
| 173 | + } |
| 174 | + } |
| 175 | + catch (err) { |
| 176 | + reject.call(new MakeDefWrapper(self),err); |
| 177 | + } |
| 178 | + } |
| 179 | + |
| 180 | + function reject(msg) { |
| 181 | + var self = this; |
| 182 | + |
| 183 | + // already triggered? |
| 184 | + if (self.triggered) { return; } |
| 185 | + |
| 186 | + self.triggered = true; |
| 187 | + |
| 188 | + // unwrap |
| 189 | + if (self.def) { |
| 190 | + self = self.def; |
| 191 | + } |
| 192 | + |
| 193 | + self.msg = msg; |
| 194 | + self.state = 2; |
| 195 | + if (self.chain.length > 0) { |
| 196 | + schedule(notify,self); |
| 197 | + } |
| 198 | + } |
| 199 | + |
| 200 | + function iteratePromises(Constructor,arr,resolver,rejecter) { |
| 201 | + for (var idx=0; idx<arr.length; idx++) { |
| 202 | + (function IIFE(idx){ |
| 203 | + Constructor.resolve(arr[idx]) |
| 204 | + .then( |
| 205 | + function $resolver$(msg){ |
| 206 | + resolver(idx,msg); |
| 207 | + }, |
| 208 | + rejecter |
| 209 | + ); |
| 210 | + })(idx); |
| 211 | + } |
| 212 | + } |
| 213 | + |
| 214 | + function MakeDefWrapper(self) { |
| 215 | + this.def = self; |
| 216 | + this.triggered = false; |
| 217 | + } |
| 218 | + |
| 219 | + function MakeDef(self) { |
| 220 | + this.promise = self; |
| 221 | + this.state = 0; |
| 222 | + this.triggered = false; |
| 223 | + this.chain = []; |
| 224 | + this.msg = void 0; |
| 225 | + } |
| 226 | + |
| 227 | + function Promise(executor) { |
| 228 | + if (typeof executor != "function") { |
| 229 | + throw TypeError("Not a function"); |
| 230 | + } |
| 231 | + |
| 232 | + if (this.__NPO__ !== 0) { |
| 233 | + throw TypeError("Not a promise"); |
| 234 | + } |
| 235 | + |
| 236 | + // instance shadowing the inherited "brand" |
| 237 | + // to signal an already "initialized" promise |
| 238 | + this.__NPO__ = 1; |
| 239 | + |
| 240 | + var def = new MakeDef(this); |
| 241 | + |
| 242 | + this["then"] = function then(success,failure) { |
| 243 | + var o = { |
| 244 | + success: typeof success == "function" ? success : true, |
| 245 | + failure: typeof failure == "function" ? failure : false |
| 246 | + }; |
| 247 | + // Note: `then(..)` itself can be borrowed to be used against |
| 248 | + // a different promise constructor for making the chained promise, |
| 249 | + // by substituting a different `this` binding. |
| 250 | + o.promise = new this.constructor(function extractChain(resolve,reject) { |
| 251 | + if (typeof resolve != "function" || typeof reject != "function") { |
| 252 | + throw TypeError("Not a function"); |
| 253 | + } |
| 254 | + |
| 255 | + o.resolve = resolve; |
| 256 | + o.reject = reject; |
| 257 | + }); |
| 258 | + def.chain.push(o); |
| 259 | + |
| 260 | + if (def.state !== 0) { |
| 261 | + schedule(notify,def); |
| 262 | + } |
| 263 | + |
| 264 | + return o.promise; |
| 265 | + }; |
| 266 | + this["catch"] = function $catch$(failure) { |
| 267 | + return this.then(void 0,failure); |
| 268 | + }; |
| 269 | + |
| 270 | + try { |
| 271 | + executor.call( |
| 272 | + void 0, |
| 273 | + function publicResolve(msg){ |
| 274 | + resolve.call(def,msg); |
| 275 | + }, |
| 276 | + function publicReject(msg) { |
| 277 | + reject.call(def,msg); |
| 278 | + } |
| 279 | + ); |
| 280 | + } |
| 281 | + catch (err) { |
| 282 | + reject.call(def,err); |
| 283 | + } |
| 284 | + } |
| 285 | + |
| 286 | + var PromisePrototype = builtInProp({},"constructor",Promise, |
| 287 | + /*configurable=*/false |
| 288 | + ); |
| 289 | + |
| 290 | + // Note: Android 4 cannot use `Object.defineProperty(..)` here |
| 291 | + Promise.prototype = PromisePrototype; |
| 292 | + |
| 293 | + // built-in "brand" to signal an "uninitialized" promise |
| 294 | + builtInProp(PromisePrototype,"__NPO__",0, |
| 295 | + /*configurable=*/false |
| 296 | + ); |
| 297 | + |
| 298 | + builtInProp(Promise,"resolve",function Promise$resolve(msg) { |
| 299 | + var Constructor = this; |
| 300 | + |
| 301 | + // spec mandated checks |
| 302 | + // note: best "isPromise" check that's practical for now |
| 303 | + if (msg && typeof msg == "object" && msg.__NPO__ === 1) { |
| 304 | + return msg; |
| 305 | + } |
| 306 | + |
| 307 | + return new Constructor(function executor(resolve,reject){ |
| 308 | + if (typeof resolve != "function" || typeof reject != "function") { |
| 309 | + throw TypeError("Not a function"); |
| 310 | + } |
| 311 | + |
| 312 | + resolve(msg); |
| 313 | + }); |
| 314 | + }); |
| 315 | + |
| 316 | + builtInProp(Promise,"reject",function Promise$reject(msg) { |
| 317 | + return new this(function executor(resolve,reject){ |
| 318 | + if (typeof resolve != "function" || typeof reject != "function") { |
| 319 | + throw TypeError("Not a function"); |
| 320 | + } |
| 321 | + |
| 322 | + reject(msg); |
| 323 | + }); |
| 324 | + }); |
| 325 | + |
| 326 | + builtInProp(Promise,"all",function Promise$all(arr) { |
| 327 | + var Constructor = this; |
| 328 | + |
| 329 | + // spec mandated checks |
| 330 | + if (ToString.call(arr) != "[object Array]") { |
| 331 | + return Constructor.reject(TypeError("Not an array")); |
| 332 | + } |
| 333 | + if (arr.length === 0) { |
| 334 | + return Constructor.resolve([]); |
| 335 | + } |
| 336 | + |
| 337 | + return new Constructor(function executor(resolve,reject){ |
| 338 | + if (typeof resolve != "function" || typeof reject != "function") { |
| 339 | + throw TypeError("Not a function"); |
| 340 | + } |
| 341 | + |
| 342 | + var len = arr.length, msgs = Array(len), count = 0; |
| 343 | + |
| 344 | + iteratePromises(Constructor,arr,function resolver(idx,msg) { |
| 345 | + msgs[idx] = msg; |
| 346 | + if (++count === len) { |
| 347 | + resolve(msgs); |
| 348 | + } |
| 349 | + },reject); |
| 350 | + }); |
| 351 | + }); |
| 352 | + |
| 353 | + builtInProp(Promise,"race",function Promise$race(arr) { |
| 354 | + var Constructor = this; |
| 355 | + |
| 356 | + // spec mandated checks |
| 357 | + if (ToString.call(arr) != "[object Array]") { |
| 358 | + return Constructor.reject(TypeError("Not an array")); |
| 359 | + } |
| 360 | + |
| 361 | + return new Constructor(function executor(resolve,reject){ |
| 362 | + if (typeof resolve != "function" || typeof reject != "function") { |
| 363 | + throw TypeError("Not a function"); |
| 364 | + } |
| 365 | + |
| 366 | + iteratePromises(Constructor,arr,function resolver(idx,msg){ |
| 367 | + resolve(msg); |
| 368 | + },reject); |
| 369 | + }); |
| 370 | + }); |
| 371 | + |
| 372 | + return Promise; |
| 373 | +}); |
0 commit comments