UNPKG

lie-ts

Version:

The Smallest & Fastest TS Promise lib.

361 lines (360 loc) 10.3 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); // stolen from https://github.com/Octane/setImmediate // convertd to NodeJS friendly syntax var uid = 0; var storage = {}; var slice = Array.prototype.slice; var message = 'setMsg'; var canPost = typeof window !== 'undefined' && window.postMessage && window.addEventListener; var fastApply = function (args) { return args[0].apply(null, slice.call(args, 1)); }; var callback = function (event) { var key = event.data; var data; if (typeof key == 'string' && key.indexOf(message) === 0) { data = storage[key]; if (data) { delete storage[key]; fastApply(data); } } }; if (canPost) { window.addEventListener('message', callback); } var setImmediatePolyfill = function () { var args = []; for (var _i = 0; _i < arguments.length; _i++) { args[_i] = arguments[_i]; } var id = uid++; var key = message + id; storage[key] = args; window.postMessage(key, '*'); return id; }; exports.setFast = (function () { return canPost ? setImmediatePolyfill : // built in window messaging (pretty fast, not bad) function () { var args = []; for (var _i = 0; _i < arguments.length; _i++) { args[_i] = arguments[_i]; } setTimeout(function () { fastApply(args); }, 0); }; })(); var _INTERNAL = function () { }; var _REJECTED = ['R']; var _FULFILLED = ['F']; var _PENDING = ['P']; var Promise = /** @class */ (function () { function Promise(resolver) { this._state = _PENDING; this._queue = []; this._outcome = void 0; if (resolver !== _INTERNAL) { _safelyResolveThenable(this, resolver); } } Promise.doPolyFill = function () { if (typeof global !== "undefined") { if (!global["Promise"]) { global["Promise"] = this; } } if (typeof window !== "undefined") { if (!window["Promise"]) { window["Promise"] = this; } } }; Promise.prototype.catch = function (onRejected) { return this.then(function () { }, onRejected); }; Promise.prototype.then = function (onFulfilled, onRejected) { if (typeof onFulfilled !== 'function' && this._state === _FULFILLED || typeof onRejected !== 'function' && this._state === _REJECTED) { return this; } var promise = new Promise(_INTERNAL); if (this._state !== _PENDING) { var resolver = this._state === _FULFILLED ? onFulfilled : onRejected; _unwrap(promise, resolver, this._outcome); } else { this._queue.push(new _QueueItem(promise, onFulfilled, onRejected)); } return promise; }; /** * * @static * @param {any} value * @returns * * @memberOf Promise */ Promise.resolve = function (value) { if (value instanceof this) return value; return _handlers._resolve(new Promise(_INTERNAL), value); }; /** * * @static * @param {any} reason * @returns * * @memberOf Promise */ Promise.reject = function (reason) { return _handlers._reject(new Promise(_INTERNAL), reason); }; Promise.all = function (iterable) { var t = this; return new Promise(function (resolve, reject) { var results = []; if (!iterable.length) { resolve([]); return; } var maybeReturn = function (index, success, failure) { if (failure !== undefined) { results.push(failure); } else { results.push(success); } if (results.length == iterable.length) { resolve(results); } }; var _loop_1 = function (i) { iterable[i].then(function (res) { maybeReturn(i, res, undefined); }).catch(function (e) { maybeReturn(i, undefined, e); }); }; for (var i = 0; i < iterable.length; i++) { _loop_1(i); } }); }; Promise.race = function (iterable) { var self = this; var len = iterable.length; var called = false; var i = -1; var promise = new Promise(_INTERNAL); if (Array.isArray(iterable) !== false) { return this.reject(new TypeError()); } function resolver(value) { self.resolve(value).then(function (response) { if (!called) { called = true; _handlers._resolve(promise, response); } }, function (error) { if (!called) { called = true; _handlers._reject(promise, error); } }); } if (!len) { return this.resolve([]); } while (++i < len) { resolver(iterable[i]); } return promise; }; return Promise; }()); exports.Promise = Promise; /** * @internal * * @export * @class _QueueItem */ var _QueueItem = /** @class */ (function () { function _QueueItem(promise, onFulfilled, onRejected) { this._promise = promise; if (typeof onFulfilled === 'function') { this._onFulfilled = onFulfilled; this._callFulfilled = this._otherCallFulfilled; } if (typeof onRejected === 'function') { this._onRejected = onRejected; this._callRejected = this._otherCallRejected; } } _QueueItem.prototype._callFulfilled = function (value) { _handlers._resolve(this._promise, value); }; ; _QueueItem.prototype._otherCallFulfilled = function (value) { _unwrap(this._promise, this._onFulfilled, value); }; ; _QueueItem.prototype._callRejected = function (value) { _handlers._reject(this._promise, value); }; ; _QueueItem.prototype._otherCallRejected = function (value) { _unwrap(this._promise, this._onRejected, value); }; ; return _QueueItem; }()); exports._QueueItem = _QueueItem; /** * * @internal * @param {any} promise * @param {any} func * @param {any} value */ function _unwrap(promise, func, value) { exports.setFast(function () { var returnValue; try { returnValue = func.apply(null, value); } catch (e) { return _handlers._reject(promise, e); } if (returnValue === promise) { _handlers._reject(promise, new TypeError()); } else { _handlers._resolve(promise, returnValue); } return null; }); } /** * * @internal * @class _handlers */ var _handlers = /** @class */ (function () { function _handlers() { } _handlers._resolve = function (self, value) { var result = _tryCatch(_getThen, value); var thenable = result._value; var i = -1; var len = self._queue.length; if (result._status === 'error') { return _handlers._reject(self, result._value); } if (thenable) { _safelyResolveThenable(self, thenable); } else { self._state = _FULFILLED; self._outcome = value; while (++i < len) { self._queue[i]._callFulfilled(value); } } return self; }; ; _handlers._reject = function (self, error) { self._state = _REJECTED; self._outcome = error; var i = -1; var len = self._queue.length; while (++i < len) { self._queue[i]._callRejected(error); } return self; }; ; return _handlers; }()); /** * * @internal * @param {any} obj * @returns */ function _getThen(obj) { // Make sure we only access the accessor once as required by the spec var then = obj && obj.then; if (obj && (typeof obj === 'object' || typeof obj === 'function') && typeof then === 'function') { return function appyThen() { then.apply(obj, arguments); }; } else { return null; } } /** * * @internal * @param {Promise<any>} self * @param {(onSuccess:(...T) => void, onFail:(...T) => void) => void} thenable */ function _safelyResolveThenable(self, thenable) { // Either fulfill, reject or reject with error var called = false; function onError() { var value = []; for (var _i = 0; _i < arguments.length; _i++) { value[_i] = arguments[_i]; } if (called) { return; } called = true; _handlers._reject(self, value); } function onSuccess() { var value = []; for (var _i = 0; _i < arguments.length; _i++) { value[_i] = arguments[_i]; } if (called) { return; } called = true; _handlers._resolve(self, value); } function tryToUnwrap() { thenable(onSuccess, onError); } var result = _tryCatch(tryToUnwrap); if (result._status === 'error') { onError(result._value); } } /** * * @internal * @param {any} func * @param {*} [values] * @returns */ function _tryCatch(func, values) { var out = { _status: null, _value: null }; try { out._value = func(values); out._status = 'success'; } catch (e) { out._status = 'error'; out._value = e; } return out; }