pdf.js/src/display/node_utils.js
Jonas Jenwald 3d4e8bb17e Add a basic navigator polyfill for older Node.js versions
Modern Node.js versions now include a `navigator` implementation, with a few basic properties, that's actually enough for the PDF.js use-cases; please see https://nodejs.org/api/globals.html#navigator
Unfortunately we still support Node.js version `20`, hence we add a basic polyfill since that allows simplifying the code slightly.
2025-04-28 13:07:12 +02:00

136 lines
3.5 KiB
JavaScript

/* Copyright 2020 Mozilla Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/* globals process */
import { isNodeJS, warn } from "../shared/util.js";
import { BaseCanvasFactory } from "./canvas_factory.js";
import { BaseCMapReaderFactory } from "./cmap_reader_factory.js";
import { BaseFilterFactory } from "./filter_factory.js";
import { BaseStandardFontDataFactory } from "./standard_fontdata_factory.js";
import { BaseWasmFactory } from "./wasm_factory.js";
if (typeof PDFJSDev !== "undefined" && PDFJSDev.test("MOZCENTRAL")) {
throw new Error(
'Module "./node_utils.js" shall not be used with MOZCENTRAL builds.'
);
}
if (isNodeJS) {
if (typeof PDFJSDev === "undefined" || PDFJSDev.test("SKIP_BABEL")) {
warn("Please use the `legacy` build in Node.js environments.");
} else {
let canvas;
try {
const require = process
.getBuiltinModule("module")
.createRequire(import.meta.url);
try {
canvas = require("@napi-rs/canvas");
} catch (ex) {
warn(`Cannot load "@napi-rs/canvas" package: "${ex}".`);
}
} catch (ex) {
warn(`Cannot access the \`require\` function: "${ex}".`);
}
if (!globalThis.DOMMatrix) {
if (canvas?.DOMMatrix) {
globalThis.DOMMatrix = canvas.DOMMatrix;
} else {
warn("Cannot polyfill `DOMMatrix`, rendering may be broken.");
}
}
if (!globalThis.ImageData) {
if (canvas?.ImageData) {
globalThis.ImageData = canvas.ImageData;
} else {
warn("Cannot polyfill `ImageData`, rendering may be broken.");
}
}
if (!globalThis.Path2D) {
if (canvas?.Path2D) {
globalThis.Path2D = canvas.Path2D;
} else {
warn("Cannot polyfill `Path2D`, rendering may be broken.");
}
}
if (!globalThis.navigator?.language) {
globalThis.navigator = {
language: "en-US",
platform: "",
userAgent: "",
};
}
}
}
async function fetchData(url) {
const fs = process.getBuiltinModule("fs");
const data = await fs.promises.readFile(url);
return new Uint8Array(data);
}
class NodeFilterFactory extends BaseFilterFactory {}
class NodeCanvasFactory extends BaseCanvasFactory {
/**
* @ignore
*/
_createCanvas(width, height) {
const require = process
.getBuiltinModule("module")
.createRequire(import.meta.url);
const canvas = require("@napi-rs/canvas");
return canvas.createCanvas(width, height);
}
}
class NodeCMapReaderFactory extends BaseCMapReaderFactory {
/**
* @ignore
*/
async _fetch(url) {
return fetchData(url);
}
}
class NodeStandardFontDataFactory extends BaseStandardFontDataFactory {
/**
* @ignore
*/
async _fetch(url) {
return fetchData(url);
}
}
class NodeWasmFactory extends BaseWasmFactory {
/**
* @ignore
*/
async _fetch(url) {
return fetchData(url);
}
}
export {
fetchData,
NodeCanvasFactory,
NodeCMapReaderFactory,
NodeFilterFactory,
NodeStandardFontDataFactory,
NodeWasmFactory,
};