|
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"!=typeofmodule&&module.exports?module.exports=n[t]:"function"==typeofdefine&&define.amd&&define(function(){returnn[t]})}("Promise","undefined"!=typeofglobal?global:this,function(){"use strict";functiont(t,n){l.add(t,n),h||(h=y(l.drain))}functionn(t){varn,e=typeoft;returnnull==t||"object"!=e&&"function"!=e||(n=t.then),"function"==typeofn?n:!1}functione(){for(vart=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}functiono(t,e,o){varr,i;try{e===!1?o.reject(t.msg):(r=e===!0?t.msg:e.call(void0,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)}}functionr(o){varc,u=this;if(!u.triggered){u.triggered=!0,u.def&&(u=u.def);try{(c=n(o))?t(function(){vart=newf(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(newf(u),a)}}}functioni(n){varo=this;o.triggered||(o.triggered=!0,o.def&&(o=o.def),o.msg=n,o.state=2,o.chain.length>0&&t(e,o))}functionc(t,n,e,o){for(varr=0;r<n.length;r++)!function(r){t.resolve(n[r]).then(function(t){e(r,t)},o)}(r)}functionf(t){this.def=t,this.triggered=!1}functionu(t){this.promise=t,this.state=0,this.triggered=!1,this.chain=[],this.msg=void0}functiona(n){if("function"!=typeofn)throwTypeError("Not a function");if(0!==this.__NPO__)throwTypeError("Not a promise");this.__NPO__=1;varo=newu(this);this.then=function(n,r){vari={success:"function"==typeofn?n:!0,failure:"function"==typeofr?r:!1};returni.promise=newthis.constructor(function(t,n){if("function"!=typeoft||"function"!=typeofn)throwTypeError("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){returnthis.then(void0,t)};try{n.call(void0,function(t){r.call(o,t)},function(t){i.call(o,t)})}catch(c){i.call(o,c)}}vars,h,l,p=Object.prototype.toString,y="undefined"!=typeofsetImmediate?function(t){returnsetImmediate(t)}:setTimeout;try{Object.defineProperty({},"x",{}),s=function(t,n,e,o){returnObject.defineProperty(t,n,{value:e,writable:!0,configurable:o!==!1})}}catch(d){s=function(t,n,e){returnt[n]=e,t}}l=function(){functiont(t,n){this.fn=t,this.self=n,this.next=void0}varn,e,o;return{add:function(r,i){o=newt(r,i),e?e.next=o:n=o,e=o,o=void0},drain:function(){vart=n;for(n=e=h=void0;t;)t.fn.call(t.self),t=t.next}}}();varg=s({},"constructor",a,!1);returna.prototype=g,s(g,"__NPO__",0,!1),s(a,"resolve",function(t){varn=this;returnt&&"object"==typeoft&&1===t.__NPO__?t:newn(function(n,e){if("function"!=typeofn||"function"!=typeofe)throwTypeError("Not a function");n(t)})}),s(a,"reject",function(t){returnnewthis(function(n,e){if("function"!=typeofn||"function"!=typeofe)throwTypeError("Not a function");e(t)})}),s(a,"all",function(t){varn=this;return"[object Array]"!=p.call(t)?n.reject(TypeError("Not an array")):0===t.length?n.resolve([]):newn(function(e,o){if("function"!=typeofe||"function"!=typeofo)throwTypeError("Not a function");varr=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){varn=this;return"[object Array]"!=p.call(t)?n.reject(TypeError("Not an array")):newn(function(e,o){if("function"!=typeofe||"function"!=typeofo)throwTypeError("Not a function");c(n,t,function(t,n){e(n)},o)})}),a}); |
| 5 | + |
| 6 | +(functionUMD(name,context,definition){ |
| 7 | +// special form of UMD for polyfilling across evironments |
| 8 | +context[name]=context[name]||definition(); |
| 9 | +if(typeofmodule!="undefined"&&module.exports){module.exports=context[name];} |
| 10 | +elseif(typeofdefine=="function"&&define.amd){define(function$AMD$(){returncontext[name];});} |
| 11 | +})("Promise",typeofglobal!="undefined" ?global :this,functionDEF(){ |
| 12 | +/*jshint validthis:true */ |
| 13 | +"use strict"; |
| 14 | + |
| 15 | +varbuiltInProp,cycle,scheduling_queue, |
| 16 | +ToString=Object.prototype.toString, |
| 17 | +timer=(typeofsetImmediate!="undefined") ? |
| 18 | +functiontimer(fn){returnsetImmediate(fn);} : |
| 19 | +setTimeout |
| 20 | +; |
| 21 | + |
| 22 | +// dammit, IE8. |
| 23 | +try{ |
| 24 | +Object.defineProperty({},"x",{}); |
| 25 | +builtInProp=functionbuiltInProp(obj,name,val,config){ |
| 26 | +returnObject.defineProperty(obj,name,{ |
| 27 | +value:val, |
| 28 | +writable:true, |
| 29 | +configurable:config!==false |
| 30 | +}); |
| 31 | +}; |
| 32 | +} |
| 33 | +catch(err){ |
| 34 | +builtInProp=functionbuiltInProp(obj,name,val){ |
| 35 | +obj[name]=val; |
| 36 | +returnobj; |
| 37 | +}; |
| 38 | +} |
| 39 | + |
| 40 | +// Note: using a queue instead of array for efficiency |
| 41 | +scheduling_queue=(functionQueue(){ |
| 42 | +varfirst,last,item; |
| 43 | + |
| 44 | +functionItem(fn,self){ |
| 45 | +this.fn=fn; |
| 46 | +this.self=self; |
| 47 | +this.next=void0; |
| 48 | +} |
| 49 | + |
| 50 | +return{ |
| 51 | +add:functionadd(fn,self){ |
| 52 | +item=newItem(fn,self); |
| 53 | +if(last){ |
| 54 | +last.next=item; |
| 55 | +} |
| 56 | +else{ |
| 57 | +first=item; |
| 58 | +} |
| 59 | +last=item; |
| 60 | +item=void0; |
| 61 | +}, |
| 62 | +drain:functiondrain(){ |
| 63 | +varf=first; |
| 64 | +first=last=cycle=void0; |
| 65 | + |
| 66 | +while(f){ |
| 67 | +f.fn.call(f.self); |
| 68 | +f=f.next; |
| 69 | +} |
| 70 | +} |
| 71 | +}; |
| 72 | +})(); |
| 73 | + |
| 74 | +functionschedule(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 | +functionisThenable(o){ |
| 83 | +var_then,o_type=typeofo; |
| 84 | + |
| 85 | +if(o!=null&& |
| 86 | +( |
| 87 | +o_type=="object"||o_type=="function" |
| 88 | +) |
| 89 | +){ |
| 90 | +_then=o.then; |
| 91 | +} |
| 92 | +returntypeof_then=="function" ?_then :false; |
| 93 | +} |
| 94 | + |
| 95 | +functionnotify(){ |
| 96 | +for(vari=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 | +functionnotifyIsolated(self,cb,chain){ |
| 110 | +varret,_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(void0,self.msg); |
| 121 | +} |
| 122 | + |
| 123 | +if(ret===chain.promise){ |
| 124 | +chain.reject(TypeError("Promise-chain cycle")); |
| 125 | +} |
| 126 | +elseif(_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 | +functionresolve(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 | +vardef_wrapper=newMakeDefWrapper(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(newMakeDefWrapper(self),err); |
| 177 | +} |
| 178 | +} |
| 179 | + |
| 180 | +functionreject(msg){ |
| 181 | +varself=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 | +functioniteratePromises(Constructor,arr,resolver,rejecter){ |
| 201 | +for(varidx=0;idx<arr.length;idx++){ |
| 202 | +(functionIIFE(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 | +functionMakeDefWrapper(self){ |
| 215 | +this.def=self; |
| 216 | +this.triggered=false; |
| 217 | +} |
| 218 | + |
| 219 | +functionMakeDef(self){ |
| 220 | +this.promise=self; |
| 221 | +this.state=0; |
| 222 | +this.triggered=false; |
| 223 | +this.chain=[]; |
| 224 | +this.msg=void0; |
| 225 | +} |
| 226 | + |
| 227 | +functionPromise(executor){ |
| 228 | +if(typeofexecutor!="function"){ |
| 229 | +throwTypeError("Not a function"); |
| 230 | +} |
| 231 | + |
| 232 | +if(this.__NPO__!==0){ |
| 233 | +throwTypeError("Not a promise"); |
| 234 | +} |
| 235 | + |
| 236 | +// instance shadowing the inherited "brand" |
| 237 | +// to signal an already "initialized" promise |
| 238 | +this.__NPO__=1; |
| 239 | + |
| 240 | +vardef=newMakeDef(this); |
| 241 | + |
| 242 | +this["then"]=functionthen(success,failure){ |
| 243 | +varo={ |
| 244 | +success:typeofsuccess=="function" ?success :true, |
| 245 | +failure:typeoffailure=="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=newthis.constructor(functionextractChain(resolve,reject){ |
| 251 | +if(typeofresolve!="function"||typeofreject!="function"){ |
| 252 | +throwTypeError("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 | +returno.promise; |
| 265 | +}; |
| 266 | +this["catch"]=function$catch$(failure){ |
| 267 | +returnthis.then(void0,failure); |
| 268 | +}; |
| 269 | + |
| 270 | +try{ |
| 271 | +executor.call( |
| 272 | +void0, |
| 273 | +functionpublicResolve(msg){ |
| 274 | +resolve.call(def,msg); |
| 275 | +}, |
| 276 | +functionpublicReject(msg){ |
| 277 | +reject.call(def,msg); |
| 278 | +} |
| 279 | +); |
| 280 | +} |
| 281 | +catch(err){ |
| 282 | +reject.call(def,err); |
| 283 | +} |
| 284 | +} |
| 285 | + |
| 286 | +varPromisePrototype=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",functionPromise$resolve(msg){ |
| 299 | +varConstructor=this; |
| 300 | + |
| 301 | +// spec mandated checks |
| 302 | +// note: best "isPromise" check that's practical for now |
| 303 | +if(msg&&typeofmsg=="object"&&msg.__NPO__===1){ |
| 304 | +returnmsg; |
| 305 | +} |
| 306 | + |
| 307 | +returnnewConstructor(functionexecutor(resolve,reject){ |
| 308 | +if(typeofresolve!="function"||typeofreject!="function"){ |
| 309 | +throwTypeError("Not a function"); |
| 310 | +} |
| 311 | + |
| 312 | +resolve(msg); |
| 313 | +}); |
| 314 | +}); |
| 315 | + |
| 316 | +builtInProp(Promise,"reject",functionPromise$reject(msg){ |
| 317 | +returnnewthis(functionexecutor(resolve,reject){ |
| 318 | +if(typeofresolve!="function"||typeofreject!="function"){ |
| 319 | +throwTypeError("Not a function"); |
| 320 | +} |
| 321 | + |
| 322 | +reject(msg); |
| 323 | +}); |
| 324 | +}); |
| 325 | + |
| 326 | +builtInProp(Promise,"all",functionPromise$all(arr){ |
| 327 | +varConstructor=this; |
| 328 | + |
| 329 | +// spec mandated checks |
| 330 | +if(ToString.call(arr)!="[object Array]"){ |
| 331 | +returnConstructor.reject(TypeError("Not an array")); |
| 332 | +} |
| 333 | +if(arr.length===0){ |
| 334 | +returnConstructor.resolve([]); |
| 335 | +} |
| 336 | + |
| 337 | +returnnewConstructor(functionexecutor(resolve,reject){ |
| 338 | +if(typeofresolve!="function"||typeofreject!="function"){ |
| 339 | +throwTypeError("Not a function"); |
| 340 | +} |
| 341 | + |
| 342 | +varlen=arr.length,msgs=Array(len),count=0; |
| 343 | + |
| 344 | +iteratePromises(Constructor,arr,functionresolver(idx,msg){ |
| 345 | +msgs[idx]=msg; |
| 346 | +if(++count===len){ |
| 347 | +resolve(msgs); |
| 348 | +} |
| 349 | +},reject); |
| 350 | +}); |
| 351 | +}); |
| 352 | + |
| 353 | +builtInProp(Promise,"race",functionPromise$race(arr){ |
| 354 | +varConstructor=this; |
| 355 | + |
| 356 | +// spec mandated checks |
| 357 | +if(ToString.call(arr)!="[object Array]"){ |
| 358 | +returnConstructor.reject(TypeError("Not an array")); |
| 359 | +} |
| 360 | + |
| 361 | +returnnewConstructor(functionexecutor(resolve,reject){ |
| 362 | +if(typeofresolve!="function"||typeofreject!="function"){ |
| 363 | +throwTypeError("Not a function"); |
| 364 | +} |
| 365 | + |
| 366 | +iteratePromises(Constructor,arr,functionresolver(idx,msg){ |
| 367 | +resolve(msg); |
| 368 | +},reject); |
| 369 | +}); |
| 370 | +}); |
| 371 | + |
| 372 | +returnPromise; |
| 373 | +}); |