197 lines
4.3 KiB
JavaScript
197 lines
4.3 KiB
JavaScript
Object.defineProperty(exports, '__esModule', { value: true });
|
|
|
|
const is = require('./is.js');
|
|
|
|
/* eslint-disable @typescript-eslint/explicit-function-return-type */
|
|
|
|
/** SyncPromise internal states */
|
|
var States; (function (States) {
|
|
/** Pending */
|
|
const PENDING = 0; States[States["PENDING"] = PENDING] = "PENDING";
|
|
/** Resolved / OK */
|
|
const RESOLVED = 1; States[States["RESOLVED"] = RESOLVED] = "RESOLVED";
|
|
/** Rejected / Error */
|
|
const REJECTED = 2; States[States["REJECTED"] = REJECTED] = "REJECTED";
|
|
})(States || (States = {}));
|
|
|
|
// Overloads so we can call resolvedSyncPromise without arguments and generic argument
|
|
|
|
/**
|
|
* Creates a resolved sync promise.
|
|
*
|
|
* @param value the value to resolve the promise with
|
|
* @returns the resolved sync promise
|
|
*/
|
|
function resolvedSyncPromise(value) {
|
|
return new SyncPromise(resolve => {
|
|
resolve(value);
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Creates a rejected sync promise.
|
|
*
|
|
* @param value the value to reject the promise with
|
|
* @returns the rejected sync promise
|
|
*/
|
|
function rejectedSyncPromise(reason) {
|
|
return new SyncPromise((_, reject) => {
|
|
reject(reason);
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Thenable class that behaves like a Promise and follows it's interface
|
|
* but is not async internally
|
|
*/
|
|
class SyncPromise {
|
|
|
|
constructor(
|
|
executor,
|
|
) {SyncPromise.prototype.__init.call(this);SyncPromise.prototype.__init2.call(this);SyncPromise.prototype.__init3.call(this);SyncPromise.prototype.__init4.call(this);
|
|
this._state = States.PENDING;
|
|
this._handlers = [];
|
|
|
|
try {
|
|
executor(this._resolve, this._reject);
|
|
} catch (e) {
|
|
this._reject(e);
|
|
}
|
|
}
|
|
|
|
/** JSDoc */
|
|
then(
|
|
onfulfilled,
|
|
onrejected,
|
|
) {
|
|
return new SyncPromise((resolve, reject) => {
|
|
this._handlers.push([
|
|
false,
|
|
result => {
|
|
if (!onfulfilled) {
|
|
// TODO: ¯\_(ツ)_/¯
|
|
// TODO: FIXME
|
|
resolve(result );
|
|
} else {
|
|
try {
|
|
resolve(onfulfilled(result));
|
|
} catch (e) {
|
|
reject(e);
|
|
}
|
|
}
|
|
},
|
|
reason => {
|
|
if (!onrejected) {
|
|
reject(reason);
|
|
} else {
|
|
try {
|
|
resolve(onrejected(reason));
|
|
} catch (e) {
|
|
reject(e);
|
|
}
|
|
}
|
|
},
|
|
]);
|
|
this._executeHandlers();
|
|
});
|
|
}
|
|
|
|
/** JSDoc */
|
|
catch(
|
|
onrejected,
|
|
) {
|
|
return this.then(val => val, onrejected);
|
|
}
|
|
|
|
/** JSDoc */
|
|
finally(onfinally) {
|
|
return new SyncPromise((resolve, reject) => {
|
|
let val;
|
|
let isRejected;
|
|
|
|
return this.then(
|
|
value => {
|
|
isRejected = false;
|
|
val = value;
|
|
if (onfinally) {
|
|
onfinally();
|
|
}
|
|
},
|
|
reason => {
|
|
isRejected = true;
|
|
val = reason;
|
|
if (onfinally) {
|
|
onfinally();
|
|
}
|
|
},
|
|
).then(() => {
|
|
if (isRejected) {
|
|
reject(val);
|
|
return;
|
|
}
|
|
|
|
resolve(val );
|
|
});
|
|
});
|
|
}
|
|
|
|
/** JSDoc */
|
|
__init() {this._resolve = (value) => {
|
|
this._setResult(States.RESOLVED, value);
|
|
};}
|
|
|
|
/** JSDoc */
|
|
__init2() {this._reject = (reason) => {
|
|
this._setResult(States.REJECTED, reason);
|
|
};}
|
|
|
|
/** JSDoc */
|
|
__init3() {this._setResult = (state, value) => {
|
|
if (this._state !== States.PENDING) {
|
|
return;
|
|
}
|
|
|
|
if (is.isThenable(value)) {
|
|
void (value ).then(this._resolve, this._reject);
|
|
return;
|
|
}
|
|
|
|
this._state = state;
|
|
this._value = value;
|
|
|
|
this._executeHandlers();
|
|
};}
|
|
|
|
/** JSDoc */
|
|
__init4() {this._executeHandlers = () => {
|
|
if (this._state === States.PENDING) {
|
|
return;
|
|
}
|
|
|
|
const cachedHandlers = this._handlers.slice();
|
|
this._handlers = [];
|
|
|
|
cachedHandlers.forEach(handler => {
|
|
if (handler[0]) {
|
|
return;
|
|
}
|
|
|
|
if (this._state === States.RESOLVED) {
|
|
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
|
handler[1](this._value );
|
|
}
|
|
|
|
if (this._state === States.REJECTED) {
|
|
handler[2](this._value);
|
|
}
|
|
|
|
handler[0] = true;
|
|
});
|
|
};}
|
|
}
|
|
|
|
exports.SyncPromise = SyncPromise;
|
|
exports.rejectedSyncPromise = rejectedSyncPromise;
|
|
exports.resolvedSyncPromise = resolvedSyncPromise;
|
|
//# sourceMappingURL=syncpromise.js.map
|