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() {
|
(function checkPromise() {
|
||||||
if (globalScope.Promise) {
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
globalScope.Promise = require('core-js/fn/promise');
|
||||||
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;
|
|
||||||
})();
|
})();
|
||||||
|
|
||||||
(function checkWeakMap() {
|
(function checkWeakMap() {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user