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

Remove PDFWorkerUtil and move its contents into PDFWorker instead #18507

Merged
merged 1 commit into from
Jul 29, 2024
Merged
Show file tree
Hide file tree
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
98 changes: 50 additions & 48 deletions src/display/api.js
Original file line number Diff line number Diff line change
Expand Up @@ -1998,47 +1998,6 @@ class LoopbackPort {
* the constants from {@link VerbosityLevel} should be used.
*/

const PDFWorkerUtil = {
isWorkerDisabled: false,
fakeWorkerId: 0,
};
if (typeof PDFJSDev === "undefined" || PDFJSDev.test("GENERIC")) {
if (isNodeJS) {
// Workers aren't supported in Node.js, force-disabling them there.
PDFWorkerUtil.isWorkerDisabled = true;

GlobalWorkerOptions.workerSrc ||= PDFJSDev.test("LIB")
? "../pdf.worker.js"
: "./pdf.worker.mjs";
}

// Check if URLs have the same origin. For non-HTTP based URLs, returns false.
PDFWorkerUtil.isSameOrigin = function (baseUrl, otherUrl) {
let base;
try {
base = new URL(baseUrl);
if (!base.origin || base.origin === "null") {
return false; // non-HTTP url
}
} catch {
return false;
}

const other = new URL(otherUrl, base);
return base.origin === other.origin;
};

PDFWorkerUtil.createCDNWrapper = function (url) {
// We will rely on blob URL's property to specify origin.
// We want this function to fail in case if createObjectURL or Blob do not
// exist or fail for some reason -- our Worker creation will fail anyway.
const wrapper = `await import("${url}");`;
return URL.createObjectURL(
new Blob([wrapper], { type: "text/javascript" })
);
};
}

/**
* PDF.js web worker abstraction that controls the instantiation of PDF
* documents. Message handlers are used to pass information from the main
Expand All @@ -2048,8 +2007,52 @@ if (typeof PDFJSDev === "undefined" || PDFJSDev.test("GENERIC")) {
* @param {PDFWorkerParameters} params - The worker initialization parameters.
*/
class PDFWorker {
static #fakeWorkerId = 0;

static #isWorkerDisabled = false;

static #workerPorts;

static {
if (typeof PDFJSDev === "undefined" || PDFJSDev.test("GENERIC")) {
if (isNodeJS) {
// Workers aren't supported in Node.js, force-disabling them there.
this.#isWorkerDisabled = true;

GlobalWorkerOptions.workerSrc ||= PDFJSDev.test("LIB")
? "../pdf.worker.js"
: "./pdf.worker.mjs";
}

// Check if URLs have the same origin. For non-HTTP based URLs, returns
// false.
this._isSameOrigin = (baseUrl, otherUrl) => {
let base;
try {
base = new URL(baseUrl);
if (!base.origin || base.origin === "null") {
return false; // non-HTTP url
}
} catch {
return false;
}
const other = new URL(otherUrl, base);
return base.origin === other.origin;
};

this._createCDNWrapper = url => {
// We will rely on blob URL's property to specify origin.
// We want this function to fail in case if createObjectURL or Blob do
// not exist or fail for some reason -- our Worker creation will fail
// anyway.
const wrapper = `await import("${url}");`;
return URL.createObjectURL(
new Blob([wrapper], { type: "text/javascript" })
);
};
}
}

constructor({
name = null,
port = null,
Expand Down Expand Up @@ -2138,7 +2141,7 @@ class PDFWorker {
// Right now, the requirement is, that an Uint8Array is still an
// Uint8Array as it arrives on the worker.
if (
PDFWorkerUtil.isWorkerDisabled ||
PDFWorker.#isWorkerDisabled ||
PDFWorker.#mainThreadWorkerMessageHandler
) {
this._setupFakeWorker();
Expand All @@ -2152,9 +2155,9 @@ class PDFWorker {
if (
typeof PDFJSDev !== "undefined" &&
PDFJSDev.test("GENERIC") &&
!PDFWorkerUtil.isSameOrigin(window.location.href, workerSrc)
!PDFWorker._isSameOrigin(window.location.href, workerSrc)
) {
workerSrc = PDFWorkerUtil.createCDNWrapper(
workerSrc = PDFWorker._createCDNWrapper(
new URL(workerSrc, window.location).href
);
}
Expand Down Expand Up @@ -2234,9 +2237,9 @@ class PDFWorker {
}

_setupFakeWorker() {
if (!PDFWorkerUtil.isWorkerDisabled) {
if (!PDFWorker.#isWorkerDisabled) {
warn("Setting up fake worker.");
PDFWorkerUtil.isWorkerDisabled = true;
PDFWorker.#isWorkerDisabled = true;
}

PDFWorker._setupFakeWorkerGlobal
Expand All @@ -2249,7 +2252,7 @@ class PDFWorker {
this._port = port;

// All fake workers use the same port, making id unique.
const id = `fake${PDFWorkerUtil.fakeWorkerId++}`;
const id = `fake${PDFWorker.#fakeWorkerId++}`;

// If the main thread is our worker, setup the handling for the
// messages -- the main thread sends to it self.
Expand Down Expand Up @@ -3470,7 +3473,6 @@ export {
PDFDocumentProxy,
PDFPageProxy,
PDFWorker,
PDFWorkerUtil,
RenderTask,
version,
};
55 changes: 25 additions & 30 deletions test/unit/api_spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,6 @@ import {
PDFDocumentProxy,
PDFPageProxy,
PDFWorker,
PDFWorkerUtil,
RenderTask,
} from "../../src/display/api.js";
import {
Expand Down Expand Up @@ -929,6 +928,31 @@ describe("api", function () {
expect(typeof workerSrc).toEqual("string");
expect(workerSrc).toEqual(GlobalWorkerOptions.workerSrc);
});

describe("isSameOrigin", function () {
it("handles invalid base URLs", function () {
// The base URL is not valid.
expect(PDFWorker._isSameOrigin("/foo", "/bar")).toEqual(false);

// The base URL has no origin.
expect(PDFWorker._isSameOrigin("blob:foo", "/bar")).toEqual(false);
});

it("correctly checks if the origin of both URLs matches", function () {
expect(
PDFWorker._isSameOrigin(
"https://www.mozilla.org/foo",
"https://www.mozilla.org/bar"
)
).toEqual(true);
expect(
PDFWorker._isSameOrigin(
"https://www.mozilla.org/foo",
"https://www.example.com/bar"
)
).toEqual(false);
});
});
});

describe("GlobalWorkerOptions", function () {
Expand Down Expand Up @@ -4885,33 +4909,4 @@ Caron Broadcasting, Inc., an Ohio corporation (“Lessee”).`)
}
);
});

describe("PDFWorkerUtil", function () {
describe("isSameOrigin", function () {
const { isSameOrigin } = PDFWorkerUtil;

it("handles invalid base URLs", function () {
// The base URL is not valid.
expect(isSameOrigin("/foo", "/bar")).toEqual(false);

// The base URL has no origin.
expect(isSameOrigin("blob:foo", "/bar")).toEqual(false);
});

it("correctly checks if the origin of both URLs matches", function () {
expect(
isSameOrigin(
"https://www.mozilla.org/foo",
"https://www.mozilla.org/bar"
)
).toEqual(true);
expect(
isSameOrigin(
"https://www.mozilla.org/foo",
"https://www.example.com/bar"
)
).toEqual(false);
});
});
});
});