syncpromise.js 4.2 KB

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