Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve some old code in the src/display/api.js file #18250

Merged
merged 5 commits into from
Jun 15, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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