Bez popisu

npo.js 7.9KB

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