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