[api-minor] Only use Workers when postMessage
transfers are supported (PR 11123 follow-up)
Given that all modern browsers now support `postMessage` transfers, and have for years, it no longer seems necessary for the PDF.js library to support using Workers unless the `postMessage` transfers functionality is available. This patch is a follow-up to PR 11123, which made it impossible to *manually* disable `postMessage` transfers for performance reasons (since it increases memory usage), which hasn't caused any bug reports as far as I know.[1] Hence we'll now only support *proper* Worker implementations, with fully working `postMessage` transfers, and fallback to using "fake" Workers otherwise. --- [1] At the time of that PR we still "supported" IE, which is why this code was left intact.
This commit is contained in:
parent
9f4a2cf5ce
commit
6f22327e61
@ -75,16 +75,9 @@ class WorkerMessageHandler {
|
|||||||
}
|
}
|
||||||
testMessageProcessed = true;
|
testMessageProcessed = true;
|
||||||
|
|
||||||
// check if Uint8Array can be sent to worker
|
// Ensure that `TypedArray`s can be sent to the worker,
|
||||||
if (!(data instanceof Uint8Array)) {
|
// and that `postMessage` transfers are supported.
|
||||||
handler.send("test", null);
|
handler.send("test", data instanceof Uint8Array && data[0] === 255);
|
||||||
return;
|
|
||||||
}
|
|
||||||
// making sure postMessage transfers are working
|
|
||||||
const supportTransfers = data[0] === 255;
|
|
||||||
handler.postMessageTransfers = supportTransfers;
|
|
||||||
|
|
||||||
handler.send("test", { supportTransfers });
|
|
||||||
});
|
});
|
||||||
|
|
||||||
handler.on("configure", function wphConfigure(data) {
|
handler.on("configure", function wphConfigure(data) {
|
||||||
@ -156,10 +149,6 @@ class WorkerMessageHandler {
|
|||||||
const workerHandlerName = docParams.docId + "_worker";
|
const workerHandlerName = docParams.docId + "_worker";
|
||||||
let handler = new MessageHandler(workerHandlerName, docId, port);
|
let handler = new MessageHandler(workerHandlerName, docId, port);
|
||||||
|
|
||||||
// Ensure that postMessage transfers are always correctly enabled/disabled,
|
|
||||||
// to prevent "DataCloneError" in browsers without transfers support.
|
|
||||||
handler.postMessageTransfers = docParams.postMessageTransfers;
|
|
||||||
|
|
||||||
function ensureNotTerminated() {
|
function ensureNotTerminated() {
|
||||||
if (terminated) {
|
if (terminated) {
|
||||||
throw new Error("Worker was terminated");
|
throw new Error("Worker was terminated");
|
||||||
|
@ -439,7 +439,6 @@ function getDocument(src) {
|
|||||||
workerId,
|
workerId,
|
||||||
worker.port
|
worker.port
|
||||||
);
|
);
|
||||||
messageHandler.postMessageTransfers = worker.postMessageTransfers;
|
|
||||||
const transport = new WorkerTransport(
|
const transport = new WorkerTransport(
|
||||||
messageHandler,
|
messageHandler,
|
||||||
task,
|
task,
|
||||||
@ -498,7 +497,6 @@ async function _fetchDocument(worker, source, pdfDataRangeTransport, docId) {
|
|||||||
},
|
},
|
||||||
maxImageSize: source.maxImageSize,
|
maxImageSize: source.maxImageSize,
|
||||||
disableFontFace: source.disableFontFace,
|
disableFontFace: source.disableFontFace,
|
||||||
postMessageTransfers: worker.postMessageTransfers,
|
|
||||||
docBaseUrl: source.docBaseUrl,
|
docBaseUrl: source.docBaseUrl,
|
||||||
ignoreErrors: source.ignoreErrors,
|
ignoreErrors: source.ignoreErrors,
|
||||||
isEvalSupported: source.isEvalSupported,
|
isEvalSupported: source.isEvalSupported,
|
||||||
@ -2079,7 +2077,6 @@ class PDFWorker {
|
|||||||
|
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.destroyed = false;
|
this.destroyed = false;
|
||||||
this.postMessageTransfers = true;
|
|
||||||
this.verbosity = verbosity;
|
this.verbosity = verbosity;
|
||||||
|
|
||||||
this._readyCapability = createPromiseCapability();
|
this._readyCapability = createPromiseCapability();
|
||||||
@ -2188,13 +2185,10 @@ class PDFWorker {
|
|||||||
return; // worker was destroyed
|
return; // worker was destroyed
|
||||||
}
|
}
|
||||||
if (data) {
|
if (data) {
|
||||||
// supportTypedArray
|
|
||||||
this._messageHandler = messageHandler;
|
this._messageHandler = messageHandler;
|
||||||
this._port = worker;
|
this._port = worker;
|
||||||
this._webWorker = worker;
|
this._webWorker = worker;
|
||||||
if (!data.supportTransfers) {
|
|
||||||
this.postMessageTransfers = false;
|
|
||||||
}
|
|
||||||
this._readyCapability.resolve();
|
this._readyCapability.resolve();
|
||||||
// Send global setting, e.g. verbosity level.
|
// Send global setting, e.g. verbosity level.
|
||||||
messageHandler.send("configure", {
|
messageHandler.send("configure", {
|
||||||
@ -2222,7 +2216,7 @@ class PDFWorker {
|
|||||||
});
|
});
|
||||||
|
|
||||||
const sendTest = () => {
|
const sendTest = () => {
|
||||||
const testObj = new Uint8Array([this.postMessageTransfers ? 255 : 0]);
|
const testObj = new Uint8Array([255]);
|
||||||
// Some versions of Opera throw a DATA_CLONE_ERR on serializing the
|
// Some versions of Opera throw a DATA_CLONE_ERR on serializing the
|
||||||
// typed array. Also, checking if we can use transfers.
|
// typed array. Also, checking if we can use transfers.
|
||||||
try {
|
try {
|
||||||
|
@ -83,7 +83,6 @@ class MessageHandler {
|
|||||||
this.comObj = comObj;
|
this.comObj = comObj;
|
||||||
this.callbackId = 1;
|
this.callbackId = 1;
|
||||||
this.streamId = 1;
|
this.streamId = 1;
|
||||||
this.postMessageTransfers = true;
|
|
||||||
this.streamSinks = Object.create(null);
|
this.streamSinks = Object.create(null);
|
||||||
this.streamControllers = Object.create(null);
|
this.streamControllers = Object.create(null);
|
||||||
this.callbackCapabilities = Object.create(null);
|
this.callbackCapabilities = Object.create(null);
|
||||||
@ -180,7 +179,7 @@ class MessageHandler {
|
|||||||
* @param {Array} [transfers] - List of transfers/ArrayBuffers.
|
* @param {Array} [transfers] - List of transfers/ArrayBuffers.
|
||||||
*/
|
*/
|
||||||
send(actionName, data, transfers) {
|
send(actionName, data, transfers) {
|
||||||
this._postMessage(
|
this.comObj.postMessage(
|
||||||
{
|
{
|
||||||
sourceName: this.sourceName,
|
sourceName: this.sourceName,
|
||||||
targetName: this.targetName,
|
targetName: this.targetName,
|
||||||
@ -204,7 +203,7 @@ class MessageHandler {
|
|||||||
const capability = createPromiseCapability();
|
const capability = createPromiseCapability();
|
||||||
this.callbackCapabilities[callbackId] = capability;
|
this.callbackCapabilities[callbackId] = capability;
|
||||||
try {
|
try {
|
||||||
this._postMessage(
|
this.comObj.postMessage(
|
||||||
{
|
{
|
||||||
sourceName: this.sourceName,
|
sourceName: this.sourceName,
|
||||||
targetName: this.targetName,
|
targetName: this.targetName,
|
||||||
@ -247,7 +246,7 @@ class MessageHandler {
|
|||||||
cancelCall: null,
|
cancelCall: null,
|
||||||
isClosed: false,
|
isClosed: false,
|
||||||
};
|
};
|
||||||
this._postMessage(
|
comObj.postMessage(
|
||||||
{
|
{
|
||||||
sourceName,
|
sourceName,
|
||||||
targetName,
|
targetName,
|
||||||
@ -322,7 +321,7 @@ class MessageHandler {
|
|||||||
this.sinkCapability = createPromiseCapability();
|
this.sinkCapability = createPromiseCapability();
|
||||||
this.ready = this.sinkCapability.promise;
|
this.ready = this.sinkCapability.promise;
|
||||||
}
|
}
|
||||||
self._postMessage(
|
comObj.postMessage(
|
||||||
{
|
{
|
||||||
sourceName,
|
sourceName,
|
||||||
targetName,
|
targetName,
|
||||||
@ -549,20 +548,6 @@ class MessageHandler {
|
|||||||
delete this.streamControllers[streamId];
|
delete this.streamControllers[streamId];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Sends raw message to the comObj.
|
|
||||||
* @param {Object} message - Raw message.
|
|
||||||
* @param transfers List of transfers/ArrayBuffers, or undefined.
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
_postMessage(message, transfers) {
|
|
||||||
if (transfers && this.postMessageTransfers) {
|
|
||||||
this.comObj.postMessage(message, transfers);
|
|
||||||
} else {
|
|
||||||
this.comObj.postMessage(message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
destroy() {
|
destroy() {
|
||||||
this.comObj.removeEventListener("message", this._onComObjOnMessage);
|
this.comObj.removeEventListener("message", this._onComObjOnMessage);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user