syncpromise.js 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196
  1. Object.defineProperty(exports, '__esModule', { value: true });
  2. const is = require('./is.js');
  3. /* eslint-disable @typescript-eslint/explicit-function-return-type */
  4. /** SyncPromise internal states */
  5. var States; (function (States) {
  6. /** Pending */
  7. const PENDING = 0; States[States["PENDING"] = PENDING] = "PENDING";
  8. /** Resolved / OK */
  9. const RESOLVED = 1; States[States["RESOLVED"] = RESOLVED] = "RESOLVED";
  10. /** Rejected / Error */
  11. const REJECTED = 2; States[States["REJECTED"] = REJECTED] = "REJECTED";
  12. })(States || (States = {}));
  13. // Overloads so we can call resolvedSyncPromise without arguments and generic argument
  14. /**
  15. * Creates a resolved sync promise.
  16. *
  17. * @param value the value to resolve the promise with
  18. * @returns the resolved sync promise
  19. */
  20. function resolvedSyncPromise(value) {
  21. return new SyncPromise(resolve => {
  22. resolve(value);
  23. });
  24. }
  25. /**
  26. * Creates a rejected sync promise.
  27. *
  28. * @param value the value to reject the promise with
  29. * @returns the rejected sync promise
  30. */
  31. function rejectedSyncPromise(reason) {
  32. return new SyncPromise((_, reject) => {
  33. reject(reason);
  34. });
  35. }
  36. /**
  37. * Thenable class that behaves like a Promise and follows it's interface
  38. * but is not async internally
  39. */
  40. class SyncPromise {
  41. constructor(
  42. executor,
  43. ) {SyncPromise.prototype.__init.call(this);SyncPromise.prototype.__init2.call(this);SyncPromise.prototype.__init3.call(this);SyncPromise.prototype.__init4.call(this);
  44. this._state = States.PENDING;
  45. this._handlers = [];
  46. try {
  47. executor(this._resolve, this._reject);
  48. } catch (e) {
  49. this._reject(e);
  50. }
  51. }
  52. /** JSDoc */
  53. then(
  54. onfulfilled,
  55. onrejected,
  56. ) {
  57. return new SyncPromise((resolve, reject) => {
  58. this._handlers.push([
  59. false,
  60. result => {
  61. if (!onfulfilled) {
  62. // TODO: ¯\_(ツ)_/¯
  63. // TODO: FIXME
  64. resolve(result );
  65. } else {
  66. try {
  67. resolve(onfulfilled(result));
  68. } catch (e) {
  69. reject(e);
  70. }
  71. }
  72. },
  73. reason => {
  74. if (!onrejected) {
  75. reject(reason);
  76. } else {
  77. try {
  78. resolve(onrejected(reason));
  79. } catch (e) {
  80. reject(e);
  81. }
  82. }
  83. },
  84. ]);
  85. this._executeHandlers();
  86. });
  87. }
  88. /** JSDoc */
  89. catch(
  90. onrejected,
  91. ) {
  92. return this.then(val => val, onrejected);
  93. }
  94. /** JSDoc */
  95. finally(onfinally) {
  96. return new SyncPromise((resolve, reject) => {
  97. let val;
  98. let isRejected;
  99. return this.then(
  100. value => {
  101. isRejected = false;
  102. val = value;
  103. if (onfinally) {
  104. onfinally();
  105. }
  106. },
  107. reason => {
  108. isRejected = true;
  109. val = reason;
  110. if (onfinally) {
  111. onfinally();
  112. }
  113. },
  114. ).then(() => {
  115. if (isRejected) {
  116. reject(val);
  117. return;
  118. }
  119. resolve(val );
  120. });
  121. });
  122. }
  123. /** JSDoc */
  124. __init() {this._resolve = (value) => {
  125. this._setResult(States.RESOLVED, value);
  126. };}
  127. /** JSDoc */
  128. __init2() {this._reject = (reason) => {
  129. this._setResult(States.REJECTED, reason);
  130. };}
  131. /** JSDoc */
  132. __init3() {this._setResult = (state, value) => {
  133. if (this._state !== States.PENDING) {
  134. return;
  135. }
  136. if (is.isThenable(value)) {
  137. void (value ).then(this._resolve, this._reject);
  138. return;
  139. }
  140. this._state = state;
  141. this._value = value;
  142. this._executeHandlers();
  143. };}
  144. /** JSDoc */
  145. __init4() {this._executeHandlers = () => {
  146. if (this._state === States.PENDING) {
  147. return;
  148. }
  149. const cachedHandlers = this._handlers.slice();
  150. this._handlers = [];
  151. cachedHandlers.forEach(handler => {
  152. if (handler[0]) {
  153. return;
  154. }
  155. if (this._state === States.RESOLVED) {
  156. // eslint-disable-next-line @typescript-eslint/no-floating-promises
  157. handler[1](this._value );
  158. }
  159. if (this._state === States.REJECTED) {
  160. handler[2](this._value);
  161. }
  162. handler[0] = true;
  163. });
  164. };}
  165. }
  166. exports.SyncPromise = SyncPromise;
  167. exports.rejectedSyncPromise = rejectedSyncPromise;
  168. exports.resolvedSyncPromise = resolvedSyncPromise;
  169. //# sourceMappingURL=syncpromise.js.map