diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5206c17f33782..af41ebc961c9f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -23,6 +23,7 @@ jobs: uses: actions/setup-node@v4 with: node-version: ${{ matrix.node-version }} + check-latest: true - name: Install dependencies run: npm ci diff --git a/.github/workflows/font_tests.yml b/.github/workflows/font_tests.yml index ff8353b371ae8..a742e385ffb28 100644 --- a/.github/workflows/font_tests.yml +++ b/.github/workflows/font_tests.yml @@ -44,6 +44,7 @@ jobs: uses: actions/setup-node@v4 with: node-version: ${{ matrix.node-version }} + check-latest: true - name: Install dependencies run: npm ci diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 99b224c6ab9d3..a11439b8557b5 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -23,6 +23,7 @@ jobs: uses: actions/setup-node@v4 with: node-version: ${{ matrix.node-version }} + check-latest: true - name: Install dependencies run: npm ci diff --git a/.github/workflows/types_tests.yml b/.github/workflows/types_tests.yml index f0b96a3be1a1f..c0f68c86e0213 100644 --- a/.github/workflows/types_tests.yml +++ b/.github/workflows/types_tests.yml @@ -23,6 +23,7 @@ jobs: uses: actions/setup-node@v4 with: node-version: ${{ matrix.node-version }} + check-latest: true - name: Install dependencies run: npm ci diff --git a/src/display/api.js b/src/display/api.js index d6dd653740755..61b478220e41b 100644 --- a/src/display/api.js +++ b/src/display/api.js @@ -59,7 +59,6 @@ import { NodeCanvasFactory, NodeCMapReaderFactory, NodeFilterFactory, - NodePackages, NodeStandardFontDataFactory, } from "display-node_utils"; import { CanvasGraphics } from "./canvas.js"; @@ -2107,14 +2106,6 @@ class PDFWorker { * @type {Promise} */ get promise() { - if ( - typeof PDFJSDev !== "undefined" && - PDFJSDev.test("GENERIC") && - isNodeJS - ) { - // Ensure that all Node.js packages/polyfills have loaded. - return Promise.all([NodePackages.promise, this._readyCapability.promise]); - } return this._readyCapability.promise; } diff --git a/src/display/node_stream.js b/src/display/node_stream.js index 6808488d62f84..069f025da52ff 100644 --- a/src/display/node_stream.js +++ b/src/display/node_stream.js @@ -12,6 +12,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +/* globals process */ import { AbortException, assert, MissingPDFException } from "../shared/util.js"; import { @@ -19,7 +20,6 @@ import { extractFilenameFromHeader, validateRangeRequestCapabilities, } from "./network_utils.js"; -import { NodePackages } from "./node_utils.js"; if (typeof PDFJSDev !== "undefined" && PDFJSDev.test("MOZCENTRAL")) { throw new Error( @@ -33,16 +33,16 @@ function parseUrlOrPath(sourceUrl) { if (urlRegex.test(sourceUrl)) { return new URL(sourceUrl); } - const url = NodePackages.get("url"); + const url = process.getBuiltinModule("url"); return new URL(url.pathToFileURL(sourceUrl)); } function createRequest(url, headers, callback) { if (url.protocol === "http:") { - const http = NodePackages.get("http"); + const http = process.getBuiltinModule("http"); return http.request(url, { headers }, callback); } - const https = NodePackages.get("https"); + const https = process.getBuiltinModule("https"); return https.request(url, { headers }, callback); } @@ -365,7 +365,7 @@ class PDFNodeStreamFsFullReader extends BaseFullReader { constructor(stream) { super(stream); - const fs = NodePackages.get("fs"); + const fs = process.getBuiltinModule("fs"); fs.promises.lstat(this._url).then( stat => { // Setting right content length. @@ -389,7 +389,7 @@ class PDFNodeStreamFsRangeReader extends BaseRangeReader { constructor(stream, start, end) { super(stream); - const fs = NodePackages.get("fs"); + const fs = process.getBuiltinModule("fs"); this._setReadableStream( fs.createReadStream(this._url, { start, end: end - 1 }) ); diff --git a/src/display/node_utils.js b/src/display/node_utils.js index aca4ad750fad7..854b71dfc60df 100644 --- a/src/display/node_utils.js +++ b/src/display/node_utils.js @@ -12,6 +12,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ +/* globals process */ import { BaseCanvasFactory, @@ -27,90 +28,51 @@ if (typeof PDFJSDev !== "undefined" && PDFJSDev.test("MOZCENTRAL")) { ); } -if (isNodeJS) { - // eslint-disable-next-line no-var - var packageCapability = Promise.withResolvers(); - // eslint-disable-next-line no-var - var packageMap = null; - - const loadPackages = async () => { - // Native packages. - const fs = await __non_webpack_import__("fs"), - http = await __non_webpack_import__("http"), - https = await __non_webpack_import__("https"), - url = await __non_webpack_import__("url"); - - // Optional, third-party, packages. - let canvas, path2d; - if (typeof PDFJSDev !== "undefined" && !PDFJSDev.test("SKIP_BABEL")) { - try { - canvas = await __non_webpack_import__("canvas"); - } catch {} - try { - path2d = await __non_webpack_import__("path2d"); - } catch {} - } - - return new Map(Object.entries({ fs, http, https, url, canvas, path2d })); - }; - - loadPackages().then( - map => { - packageMap = map; - packageCapability.resolve(); - - if (typeof PDFJSDev === "undefined" || PDFJSDev.test("SKIP_BABEL")) { - return; - } - if (!globalThis.DOMMatrix) { - const DOMMatrix = map.get("canvas")?.DOMMatrix; - - if (DOMMatrix) { - globalThis.DOMMatrix = DOMMatrix; - } else { - warn("Cannot polyfill `DOMMatrix`, rendering may be broken."); - } - } - if (!globalThis.Path2D) { - const CanvasRenderingContext2D = - map.get("canvas")?.CanvasRenderingContext2D; - const applyPath2DToCanvasRenderingContext = - map.get("path2d")?.applyPath2DToCanvasRenderingContext; - const Path2D = map.get("path2d")?.Path2D; - - if ( - CanvasRenderingContext2D && - applyPath2DToCanvasRenderingContext && - Path2D - ) { - applyPath2DToCanvasRenderingContext(CanvasRenderingContext2D); - globalThis.Path2D = Path2D; - } else { - warn("Cannot polyfill `Path2D`, rendering may be broken."); - } - } - }, - reason => { - warn(`loadPackages: ${reason}`); - - packageMap = new Map(); - packageCapability.resolve(); +if ( + typeof PDFJSDev !== "undefined" && + !PDFJSDev.test("SKIP_BABEL") && + isNodeJS +) { + let canvas, path2d; + try { + const require = process + .getBuiltinModule("module") + .createRequire(import.meta.url); + + canvas = require("canvas"); + path2d = require("path2d"); + } catch {} + + if (!globalThis.DOMMatrix) { + const DOMMatrix = canvas?.DOMMatrix; + + if (DOMMatrix) { + globalThis.DOMMatrix = DOMMatrix; + } else { + warn("Cannot polyfill `DOMMatrix`, rendering may be broken."); } - ); -} - -class NodePackages { - static get promise() { - return packageCapability.promise; } - - static get(name) { - return packageMap?.get(name); + if (!globalThis.Path2D) { + const CanvasRenderingContext2D = canvas?.CanvasRenderingContext2D; + const applyPath2DToCanvasRenderingContext = + path2d?.applyPath2DToCanvasRenderingContext; + const Path2D = path2d?.Path2D; + + if ( + CanvasRenderingContext2D && + applyPath2DToCanvasRenderingContext && + Path2D + ) { + applyPath2DToCanvasRenderingContext(CanvasRenderingContext2D); + globalThis.Path2D = Path2D; + } else { + warn("Cannot polyfill `Path2D`, rendering may be broken."); + } } } const fetchData = function (url) { - const fs = NodePackages.get("fs"); + const fs = process.getBuiltinModule("fs"); return fs.promises.readFile(url).then(data => new Uint8Array(data)); }; @@ -121,7 +83,10 @@ class NodeCanvasFactory extends BaseCanvasFactory { * @ignore */ _createCanvas(width, height) { - const canvas = NodePackages.get("canvas"); + const require = process + .getBuiltinModule("module") + .createRequire(import.meta.url); + const canvas = require("canvas"); return canvas.createCanvas(width, height); } } @@ -148,6 +113,5 @@ export { NodeCanvasFactory, NodeCMapReaderFactory, NodeFilterFactory, - NodePackages, NodeStandardFontDataFactory, }; diff --git a/src/display/stubs.js b/src/display/stubs.js index 0b3b9a0bbb788..271f0d70015bc 100644 --- a/src/display/stubs.js +++ b/src/display/stubs.js @@ -16,7 +16,6 @@ const NodeCanvasFactory = null; const NodeCMapReaderFactory = null; const NodeFilterFactory = null; -const NodePackages = null; const NodeStandardFontDataFactory = null; const PDFFetchStream = null; const PDFNetworkStream = null; @@ -26,7 +25,6 @@ export { NodeCanvasFactory, NodeCMapReaderFactory, NodeFilterFactory, - NodePackages, NodeStandardFontDataFactory, PDFFetchStream, PDFNetworkStream, diff --git a/test/types/tsconfig.json b/test/types/tsconfig.json index 5cd8ef4507e20..772a382c71e4d 100644 --- a/test/types/tsconfig.json +++ b/test/types/tsconfig.json @@ -10,7 +10,7 @@ "module": "ESNext", "baseUrl": "./", "strict": true, - "types": [], + "types": ["node"], "lib": ["ESNext", "DOM"], "paths": { "pdfjs-dist": ["../../build/typestest"], diff --git a/test/unit/clitests_helper.js b/test/unit/clitests_helper.js index a5a1c788e2de0..d86eeacbbc2d3 100644 --- a/test/unit/clitests_helper.js +++ b/test/unit/clitests_helper.js @@ -18,7 +18,6 @@ import { setVerbosityLevel, VerbosityLevel, } from "../../src/shared/util.js"; -import { NodePackages } from "../../src/display/node_utils.js"; // Sets longer timeout, similar to `jasmine-boot.js`. jasmine.DEFAULT_TIMEOUT_INTERVAL = 30000; @@ -30,9 +29,6 @@ if (!isNodeJS) { ); } -// Ensure that all Node.js packages/polyfills have loaded. -await NodePackages.promise; - // Reduce the amount of console "spam", by ignoring `info`/`warn` calls, // when running the unit-tests in Node.js/Travis. setVerbosityLevel(VerbosityLevel.ERRORS); diff --git a/test/unit/node_stream_spec.js b/test/unit/node_stream_spec.js index 775131caa3f50..085164bb70526 100644 --- a/test/unit/node_stream_spec.js +++ b/test/unit/node_stream_spec.js @@ -24,11 +24,10 @@ if (!isNodeJS) { ); } -const url = await __non_webpack_import__("url"); - describe("node_stream", function () { let tempServer = null; + const url = process.getBuiltinModule("url"); const cwdURL = url.pathToFileURL(process.cwd()) + "/"; const pdf = new URL("./test/pdfs/tracemonkey.pdf", cwdURL).href; const pdfLength = 1016315; diff --git a/test/unit/test_utils.js b/test/unit/test_utils.js index 507fc15649f48..eb3f5ea04900f 100644 --- a/test/unit/test_utils.js +++ b/test/unit/test_utils.js @@ -18,13 +18,6 @@ import { NullStream, StringStream } from "../../src/core/stream.js"; import { Page, PDFDocument } from "../../src/core/document.js"; import { Ref } from "../../src/core/primitives.js"; -let fs, http; -if (isNodeJS) { - // Native packages. - fs = await __non_webpack_import__("fs"); - http = await __non_webpack_import__("http"); -} - const TEST_PDFS_PATH = isNodeJS ? "./test/pdfs/" : "../pdfs/"; const CMAP_URL = isNodeJS ? "./external/bcmaps/" : "../../external/bcmaps/"; @@ -45,6 +38,7 @@ class DOMFileReaderFactory { class NodeFileReaderFactory { static async fetch(params) { + const fs = process.getBuiltinModule("fs"); const data = await fs.promises.readFile(params.path); return new Uint8Array(data); } @@ -141,6 +135,8 @@ function createIdFactory(pageIndex) { function createTemporaryNodeServer() { assert(isNodeJS, "Should only be used in Node.js environments."); + const fs = process.getBuiltinModule("fs"), + http = process.getBuiltinModule("http"); // Create http server to serve pdf data for tests. const server = http .createServer((request, response) => {