Replace our Promise
polyfill with the one from core-js
Since we're already using core-js elsewhere in `compatibility.js`, we can reduce the amount of code we need to maintain ourselves. https://github.com/zloirock/core-js#ecmascript-6-promise
This commit is contained in:
parent
56c14e27e6
commit
8684aa0ee5
@ -862,333 +862,11 @@ PDFJS.compatibilityChecked = true;
|
||||
};
|
||||
})();
|
||||
|
||||
/**
|
||||
* Polyfill for Promises:
|
||||
* The following promise implementation tries to generally implement the
|
||||
* Promise/A+ spec. Some notable differences from other promise libraries are:
|
||||
* - There currently isn't a separate deferred and promise object.
|
||||
* - Unhandled rejections eventually show an error if they aren't handled.
|
||||
*
|
||||
* Based off of the work in:
|
||||
* https://bugzilla.mozilla.org/show_bug.cgi?id=810490
|
||||
*/
|
||||
(function checkPromise() {
|
||||
if (globalScope.Promise) {
|
||||
// Promises existing in the DOM/Worker, checking presence of all/resolve
|
||||
if (typeof globalScope.Promise.all !== 'function') {
|
||||
globalScope.Promise.all = function (iterable) {
|
||||
var count = 0, results = [], resolve, reject;
|
||||
var promise = new globalScope.Promise(function (resolve_, reject_) {
|
||||
resolve = resolve_;
|
||||
reject = reject_;
|
||||
});
|
||||
iterable.forEach(function (p, i) {
|
||||
count++;
|
||||
p.then(function (result) {
|
||||
results[i] = result;
|
||||
count--;
|
||||
if (count === 0) {
|
||||
resolve(results);
|
||||
}
|
||||
}, reject);
|
||||
});
|
||||
if (count === 0) {
|
||||
resolve(results);
|
||||
}
|
||||
return promise;
|
||||
};
|
||||
}
|
||||
if (typeof globalScope.Promise.resolve !== 'function') {
|
||||
globalScope.Promise.resolve = function (value) {
|
||||
return new globalScope.Promise(function (resolve) {
|
||||
resolve(value);
|
||||
});
|
||||
};
|
||||
}
|
||||
if (typeof globalScope.Promise.reject !== 'function') {
|
||||
globalScope.Promise.reject = function (reason) {
|
||||
return new globalScope.Promise(function (resolve, reject) {
|
||||
reject(reason);
|
||||
});
|
||||
};
|
||||
}
|
||||
if (typeof globalScope.Promise.prototype.catch !== 'function') {
|
||||
globalScope.Promise.prototype.catch = function (onReject) {
|
||||
return globalScope.Promise.prototype.then(undefined, onReject);
|
||||
};
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
var STATUS_PENDING = 0;
|
||||
var STATUS_RESOLVED = 1;
|
||||
var STATUS_REJECTED = 2;
|
||||
|
||||
// In an attempt to avoid silent exceptions, unhandled rejections are
|
||||
// tracked and if they aren't handled in a certain amount of time an
|
||||
// error is logged.
|
||||
var REJECTION_TIMEOUT = 500;
|
||||
|
||||
var HandlerManager = {
|
||||
handlers: [],
|
||||
running: false,
|
||||
unhandledRejections: [],
|
||||
pendingRejectionCheck: false,
|
||||
|
||||
scheduleHandlers: function scheduleHandlers(promise) {
|
||||
if (promise._status === STATUS_PENDING) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.handlers = this.handlers.concat(promise._handlers);
|
||||
promise._handlers = [];
|
||||
|
||||
if (this.running) {
|
||||
return;
|
||||
}
|
||||
this.running = true;
|
||||
|
||||
setTimeout(this.runHandlers.bind(this), 0);
|
||||
},
|
||||
|
||||
runHandlers: function runHandlers() {
|
||||
var RUN_TIMEOUT = 1; // ms
|
||||
var timeoutAt = Date.now() + RUN_TIMEOUT;
|
||||
while (this.handlers.length > 0) {
|
||||
var handler = this.handlers.shift();
|
||||
|
||||
var nextStatus = handler.thisPromise._status;
|
||||
var nextValue = handler.thisPromise._value;
|
||||
|
||||
try {
|
||||
if (nextStatus === STATUS_RESOLVED) {
|
||||
if (typeof handler.onResolve === 'function') {
|
||||
nextValue = handler.onResolve(nextValue);
|
||||
}
|
||||
} else if (typeof handler.onReject === 'function') {
|
||||
nextValue = handler.onReject(nextValue);
|
||||
nextStatus = STATUS_RESOLVED;
|
||||
|
||||
if (handler.thisPromise._unhandledRejection) {
|
||||
this.removeUnhandeledRejection(handler.thisPromise);
|
||||
}
|
||||
}
|
||||
} catch (ex) {
|
||||
nextStatus = STATUS_REJECTED;
|
||||
nextValue = ex;
|
||||
}
|
||||
|
||||
handler.nextPromise._updateStatus(nextStatus, nextValue);
|
||||
if (Date.now() >= timeoutAt) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (this.handlers.length > 0) {
|
||||
setTimeout(this.runHandlers.bind(this), 0);
|
||||
return;
|
||||
}
|
||||
|
||||
this.running = false;
|
||||
},
|
||||
|
||||
addUnhandledRejection: function addUnhandledRejection(promise) {
|
||||
this.unhandledRejections.push({
|
||||
promise,
|
||||
time: Date.now(),
|
||||
});
|
||||
this.scheduleRejectionCheck();
|
||||
},
|
||||
|
||||
removeUnhandeledRejection: function removeUnhandeledRejection(promise) {
|
||||
promise._unhandledRejection = false;
|
||||
for (var i = 0; i < this.unhandledRejections.length; i++) {
|
||||
if (this.unhandledRejections[i].promise === promise) {
|
||||
this.unhandledRejections.splice(i);
|
||||
i--;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
scheduleRejectionCheck: function scheduleRejectionCheck() {
|
||||
if (this.pendingRejectionCheck) {
|
||||
return;
|
||||
}
|
||||
this.pendingRejectionCheck = true;
|
||||
setTimeout(() => {
|
||||
this.pendingRejectionCheck = false;
|
||||
var now = Date.now();
|
||||
for (var i = 0; i < this.unhandledRejections.length; i++) {
|
||||
if (now - this.unhandledRejections[i].time > REJECTION_TIMEOUT) {
|
||||
var unhandled = this.unhandledRejections[i].promise._value;
|
||||
var msg = 'Unhandled rejection: ' + unhandled;
|
||||
if (unhandled.stack) {
|
||||
msg += '\n' + unhandled.stack;
|
||||
}
|
||||
// Raising and catching the error, so debugger can break on it.
|
||||
try {
|
||||
throw new Error(msg);
|
||||
} catch (_) {
|
||||
console.warn(msg);
|
||||
}
|
||||
this.unhandledRejections.splice(i);
|
||||
i--;
|
||||
}
|
||||
}
|
||||
if (this.unhandledRejections.length) {
|
||||
this.scheduleRejectionCheck();
|
||||
}
|
||||
}, REJECTION_TIMEOUT);
|
||||
},
|
||||
};
|
||||
|
||||
var Promise = function Promise(resolver) {
|
||||
this._status = STATUS_PENDING;
|
||||
this._handlers = [];
|
||||
try {
|
||||
resolver.call(this, this._resolve.bind(this), this._reject.bind(this));
|
||||
} catch (e) {
|
||||
this._reject(e);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Builds a promise that is resolved when all the passed in promises are
|
||||
* resolved.
|
||||
* @param {array} promises array of data and/or promises to wait for.
|
||||
* @return {Promise} New dependent promise.
|
||||
*/
|
||||
Promise.all = function Promise_all(promises) {
|
||||
var resolveAll, rejectAll;
|
||||
var deferred = new Promise(function (resolve, reject) {
|
||||
resolveAll = resolve;
|
||||
rejectAll = reject;
|
||||
});
|
||||
var unresolved = promises.length;
|
||||
var results = [];
|
||||
if (unresolved === 0) {
|
||||
resolveAll(results);
|
||||
return deferred;
|
||||
}
|
||||
function reject(reason) {
|
||||
if (deferred._status === STATUS_REJECTED) {
|
||||
return;
|
||||
}
|
||||
results = [];
|
||||
rejectAll(reason);
|
||||
}
|
||||
for (var i = 0, ii = promises.length; i < ii; ++i) {
|
||||
var promise = promises[i];
|
||||
var resolve = (function(i) {
|
||||
return function(value) {
|
||||
if (deferred._status === STATUS_REJECTED) {
|
||||
return;
|
||||
}
|
||||
results[i] = value;
|
||||
unresolved--;
|
||||
if (unresolved === 0) {
|
||||
resolveAll(results);
|
||||
}
|
||||
};
|
||||
})(i);
|
||||
if (Promise.isPromise(promise)) {
|
||||
promise.then(resolve, reject);
|
||||
} else {
|
||||
resolve(promise);
|
||||
}
|
||||
}
|
||||
return deferred;
|
||||
};
|
||||
|
||||
/**
|
||||
* Checks if the value is likely a promise (has a 'then' function).
|
||||
* @return {boolean} true if value is thenable
|
||||
*/
|
||||
Promise.isPromise = function Promise_isPromise(value) {
|
||||
return value && typeof value.then === 'function';
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates resolved promise
|
||||
* @param value resolve value
|
||||
* @returns {Promise}
|
||||
*/
|
||||
Promise.resolve = function Promise_resolve(value) {
|
||||
return new Promise(function (resolve) {
|
||||
resolve(value);
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates rejected promise
|
||||
* @param reason rejection value
|
||||
* @returns {Promise}
|
||||
*/
|
||||
Promise.reject = function Promise_reject(reason) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
reject(reason);
|
||||
});
|
||||
};
|
||||
|
||||
Promise.prototype = {
|
||||
_status: null,
|
||||
_value: null,
|
||||
_handlers: null,
|
||||
_unhandledRejection: null,
|
||||
|
||||
_updateStatus: function Promise__updateStatus(status, value) {
|
||||
if (this._status === STATUS_RESOLVED ||
|
||||
this._status === STATUS_REJECTED) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (status === STATUS_RESOLVED &&
|
||||
Promise.isPromise(value)) {
|
||||
value.then(this._updateStatus.bind(this, STATUS_RESOLVED),
|
||||
this._updateStatus.bind(this, STATUS_REJECTED));
|
||||
return;
|
||||
}
|
||||
|
||||
this._status = status;
|
||||
this._value = value;
|
||||
|
||||
if (status === STATUS_REJECTED && this._handlers.length === 0) {
|
||||
this._unhandledRejection = true;
|
||||
HandlerManager.addUnhandledRejection(this);
|
||||
}
|
||||
|
||||
HandlerManager.scheduleHandlers(this);
|
||||
},
|
||||
|
||||
_resolve: function Promise_resolve(value) {
|
||||
this._updateStatus(STATUS_RESOLVED, value);
|
||||
},
|
||||
|
||||
_reject: function Promise_reject(reason) {
|
||||
this._updateStatus(STATUS_REJECTED, reason);
|
||||
},
|
||||
|
||||
then: function Promise_then(onResolve, onReject) {
|
||||
var nextPromise = new Promise(function (resolve, reject) {
|
||||
this.resolve = resolve;
|
||||
this.reject = reject;
|
||||
});
|
||||
this._handlers.push({
|
||||
thisPromise: this,
|
||||
onResolve,
|
||||
onReject,
|
||||
nextPromise,
|
||||
});
|
||||
HandlerManager.scheduleHandlers(this);
|
||||
return nextPromise;
|
||||
},
|
||||
|
||||
catch: function Promise_catch(onReject) {
|
||||
return this.then(undefined, onReject);
|
||||
},
|
||||
};
|
||||
|
||||
globalScope.Promise = Promise;
|
||||
globalScope.Promise = require('core-js/fn/promise');
|
||||
})();
|
||||
|
||||
(function checkWeakMap() {
|
||||
|
Loading…
Reference in New Issue
Block a user