Skip to content

Commit

Permalink
Merge pull request #18250 from Snuffleupagus/api-misc-fixes
Browse files Browse the repository at this point in the history
Improve some old code in the `src/display/api.js` file
  • Loading branch information
timvandermeij authored Jun 15, 2024
2 parents ebb2db7 + f3f88ee commit 2effc96
Showing 1 changed file with 94 additions and 104 deletions.
198 changes: 94 additions & 104 deletions src/display/api.js
Original file line number Diff line number Diff line change
Expand Up @@ -229,22 +229,14 @@ const DefaultStandardFontDataFactory =
* already populated with data, or a parameter object.
* @returns {PDFDocumentLoadingTask}
*/
function getDocument(src) {
function getDocument(src = {}) {
if (typeof PDFJSDev === "undefined" || PDFJSDev.test("GENERIC")) {
if (typeof src === "string" || src instanceof URL) {
src = { url: src };
} else if (src instanceof ArrayBuffer || ArrayBuffer.isView(src)) {
src = { data: src };
}
}
if (typeof src !== "object") {
throw new Error("Invalid parameter in getDocument, need parameter object.");
}
if (!src.url && !src.data && !src.range) {
throw new Error(
"Invalid parameter object: need either .data, .range or .url"
);
}
const task = new PDFDocumentLoadingTask();
const { docId } = task;

Expand Down Expand Up @@ -423,6 +415,9 @@ function getDocument(src) {
if (typeof PDFJSDev !== "undefined" && PDFJSDev.test("MOZCENTRAL")) {
throw new Error("Not implemented: createPDFNetworkStream");
}
if (!url) {
throw new Error("getDocument - no `url` parameter provided.");
}
const createPDFNetworkStream = params => {
if (
typeof PDFJSDev !== "undefined" &&
Expand Down Expand Up @@ -2091,6 +2086,14 @@ class PDFWorker {
return this._readyCapability.promise;
}

#resolve() {
this._readyCapability.resolve();
// Send global setting, e.g. verbosity level.
this._messageHandler.send("configure", {
verbosity: this.verbosity,
});
}

/**
* The current `workerPort`, when it exists.
* @type {Worker}
Expand All @@ -2117,115 +2120,107 @@ class PDFWorker {
// Ignoring "ready" event -- MessageHandler should already be initialized
// and ready to accept messages.
});
this._readyCapability.resolve();
// Send global setting, e.g. verbosity level.
this._messageHandler.send("configure", {
verbosity: this.verbosity,
});
this.#resolve();
}

_initialize() {
// If worker support isn't disabled explicit and the browser has worker
// support, create a new web worker and test if it/the browser fulfills
// all requirements to run parts of pdf.js in a web worker.
// Right now, the requirement is, that an Uint8Array is still an
// Uint8Array as it arrives on the worker. (Chrome added this with v.15.)
// Uint8Array as it arrives on the worker.
if (
!PDFWorkerUtil.isWorkerDisabled &&
!PDFWorker.#mainThreadWorkerMessageHandler
PDFWorkerUtil.isWorkerDisabled ||
PDFWorker.#mainThreadWorkerMessageHandler
) {
let { workerSrc } = PDFWorker;

try {
// Wraps workerSrc path into blob URL, if the former does not belong
// to the same origin.
if (
typeof PDFJSDev !== "undefined" &&
PDFJSDev.test("GENERIC") &&
!PDFWorkerUtil.isSameOrigin(window.location.href, workerSrc)
) {
workerSrc = PDFWorkerUtil.createCDNWrapper(
new URL(workerSrc, window.location).href
);
}
this._setupFakeWorker();
return;
}
let { workerSrc } = PDFWorker;

const worker = new Worker(workerSrc, { type: "module" });
const messageHandler = new MessageHandler("main", "worker", worker);
const terminateEarly = () => {
worker.removeEventListener("error", onWorkerError);
messageHandler.destroy();
worker.terminate();
if (this.destroyed) {
this._readyCapability.reject(new Error("Worker was destroyed"));
} else {
// Fall back to fake worker if the termination is caused by an
// error (e.g. NetworkError / SecurityError).
this._setupFakeWorker();
}
};
try {
// Wraps workerSrc path into blob URL, if the former does not belong
// to the same origin.
if (
typeof PDFJSDev !== "undefined" &&
PDFJSDev.test("GENERIC") &&
!PDFWorkerUtil.isSameOrigin(window.location.href, workerSrc)
) {
workerSrc = PDFWorkerUtil.createCDNWrapper(
new URL(workerSrc, window.location).href
);
}

const worker = new Worker(workerSrc, { type: "module" });
const messageHandler = new MessageHandler("main", "worker", worker);
const terminateEarly = () => {
ac.abort();
messageHandler.destroy();
worker.terminate();
if (this.destroyed) {
this._readyCapability.reject(new Error("Worker was destroyed"));
} else {
// Fall back to fake worker if the termination is caused by an
// error (e.g. NetworkError / SecurityError).
this._setupFakeWorker();
}
};

const onWorkerError = () => {
const ac = new AbortController();
worker.addEventListener(
"error",
() => {
if (!this._webWorker) {
// Worker failed to initialize due to an error. Clean up and fall
// back to the fake worker.
terminateEarly();
}
};
worker.addEventListener("error", onWorkerError);
},
{ signal: ac.signal }
);

messageHandler.on("test", data => {
worker.removeEventListener("error", onWorkerError);
if (this.destroyed) {
terminateEarly();
return; // worker was destroyed
}
if (data) {
this._messageHandler = messageHandler;
this._port = worker;
this._webWorker = worker;

this._readyCapability.resolve();
// Send global setting, e.g. verbosity level.
messageHandler.send("configure", {
verbosity: this.verbosity,
});
} else {
this._setupFakeWorker();
messageHandler.destroy();
worker.terminate();
}
});
messageHandler.on("test", data => {
ac.abort();
if (this.destroyed || !data) {
terminateEarly();
return;
}
this._messageHandler = messageHandler;
this._port = worker;
this._webWorker = worker;

messageHandler.on("ready", data => {
worker.removeEventListener("error", onWorkerError);
if (this.destroyed) {
terminateEarly();
return; // worker was destroyed
}
try {
sendTest();
} catch {
// We need fallback to a faked worker.
this._setupFakeWorker();
}
});
this.#resolve();
});

const sendTest = () => {
const testObj = new Uint8Array();
// Ensure that we can use `postMessage` transfers.
messageHandler.send("test", testObj, [testObj.buffer]);
};
messageHandler.on("ready", data => {
ac.abort();
if (this.destroyed) {
terminateEarly();
return;
}
try {
sendTest();
} catch {
// We need fallback to a faked worker.
this._setupFakeWorker();
}
});

// It might take time for the worker to initialize. We will try to send
// the "test" message immediately, and once the "ready" message arrives.
// The worker shall process only the first received "test" message.
sendTest();
return;
} catch {
info("The worker has been disabled.");
}
const sendTest = () => {
const testObj = new Uint8Array();
// Ensure that we can use `postMessage` transfers.
messageHandler.send("test", testObj, [testObj.buffer]);
};

// It might take time for the worker to initialize. We will try to send
// the "test" message immediately, and once the "ready" message arrives.
// The worker shall process only the first received "test" message.
sendTest();
return;
} catch {
info("The worker has been disabled.");
}
// Either workers are disabled, not supported or have thrown an exception.
// Either workers are not supported or have thrown an exception.
// Thus, we fallback to a faked worker.
this._setupFakeWorker();
}
Expand Down Expand Up @@ -2253,13 +2248,8 @@ class PDFWorker {
const workerHandler = new MessageHandler(id + "_worker", id, port);
WorkerMessageHandler.setup(workerHandler, port);

const messageHandler = new MessageHandler(id, id + "_worker", port);
this._messageHandler = messageHandler;
this._readyCapability.resolve();
// Send global setting, e.g. verbosity level.
messageHandler.send("configure", {
verbosity: this.verbosity,
});
this._messageHandler = new MessageHandler(id, id + "_worker", port);
this.#resolve();
})
.catch(reason => {
this._readyCapability.reject(
Expand Down

0 comments on commit 2effc96

Please sign in to comment.