Skip to content

Commit

Permalink
Remove PDFWorkerUtil and move its contents into PDFWorker instead
Browse files Browse the repository at this point in the history
This is possible thanks to features, i.e. private fields and in particular static initialization blocks, that didn't exist back when we started using classes in the code-base.
  • Loading branch information
Snuffleupagus committed Jul 29, 2024
1 parent 582866e commit c4fdb28
Show file tree
Hide file tree
Showing 2 changed files with 75 additions and 78 deletions.
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);
});
});
});
});

0 comments on commit c4fdb28

Please sign in to comment.