promise.js 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  1. "use strict";
  2. /* This is minimal implementation of the Nodent runtime that _requires_ external support for Promise, either as a
  3. * platform-supplied global, or by setting $asyncbind.Promise once the runtime is loaded but before it is called,eg:
  4. *
  5. * var _asyncRuntime = require('nodent-runtime/promise') ;
  6. * _asyncRuntime.$asyncbind.Promise = MyPromiseImpl ;
  7. *
  8. * $asyncbind has multiple uses, depending on the parameter list. 'this' is always a function to be bound
  9. */
  10. function $asyncbind(self,catcher) {
  11. "use strict";
  12. var resolver = this;
  13. switch (catcher) {
  14. case true:
  15. case 0:
  16. return new ($asyncbind.Promise)(self);
  17. case undefined:
  18. return function boundThen() {
  19. return resolver.apply(self,arguments);
  20. }
  21. default:
  22. return function(){
  23. try {
  24. return resolver.apply(self,arguments);
  25. } catch(ex) {
  26. return catcher(ex);
  27. }
  28. }
  29. }
  30. } ;
  31. function $asyncspawn(promiseProvider,self) {
  32. if (!(this instanceof Function)) return ;
  33. var genF = this ;
  34. return new promiseProvider(function enough(resolve, reject) {
  35. var gen = genF.call(self, resolve, reject);
  36. function step(fn,arg) {
  37. var next;
  38. try {
  39. next = fn.call(gen,arg);
  40. if(next.done) {
  41. if (next.value !== resolve) {
  42. if (next.value && next.value===next.value.then)
  43. return next.value(resolve,reject) ;
  44. resolve && resolve(next.value);
  45. resolve = null ;
  46. }
  47. return;
  48. }
  49. if (next.value.then) {
  50. next.value.then(function(v) {
  51. step(gen.next,v);
  52. }, function(e) {
  53. step(gen.throw,e);
  54. });
  55. } else {
  56. step(gen.next,next.value);
  57. }
  58. } catch(e) {
  59. reject && reject(e);
  60. reject = null ;
  61. return;
  62. }
  63. }
  64. step(gen.next);
  65. });
  66. }
  67. function trampoline(t,x,s,e,u){
  68. return function b(q) {
  69. while (q) {
  70. if (q.then) {
  71. q = q.then(b, e) ;
  72. return u?undefined:q;
  73. }
  74. try {
  75. if (q.pop) {
  76. if (q.length)
  77. return q.pop() ? x.call(t) : q;
  78. q = s;
  79. } else
  80. q = q.call(t)
  81. } catch (r) {
  82. return e(r);
  83. }
  84. }
  85. }
  86. };
  87. /*$asyncbind.LazyThenable = $asyncbind.EagerThenable = $asyncbind.Thenable = */
  88. try {
  89. $asyncbind.Promise = Promise;
  90. } catch (ex) {
  91. // No global Promise is defined - maybe the caller will set one.
  92. }
  93. $asyncbind.trampoline = trampoline ;
  94. // Export async bindings
  95. module.exports = {
  96. $asyncbind:$asyncbind,
  97. $asyncspawn:$asyncspawn
  98. };