From 270b68feb9d6a2dd43c98be493cd5347d05a317d Mon Sep 17 00:00:00 2001 From: Jonas Jenwald Date: Fri, 24 Apr 2026 12:03:54 +0200 Subject: [PATCH] [api-major] Update the minimum supported browsers, and remove no longer needed polyfills By removing support for older browsers it's possible to simplify both the code and the build-scripts, in addition to removing manually implemented polyfills. Using the PDF.js library/viewer will now require native support for the following features: - The `AbortSignal.any()` static method, see https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal/any_static#browser_compatibility - The `:dir()` CSS pseudo-class, see https://developer.mozilla.org/en-US/docs/Web/CSS/Reference/Selectors/:dir#browser_compatibility - The `light-dark()` CSS function, see https://developer.mozilla.org/en-US/docs/Web/CSS/Reference/Values/color_value/light-dark#browser_compatibility - The CSS `&` nesting selector, see https://developer.mozilla.org/en-US/docs/Web/CSS/Reference/Selectors/Nesting_selector#browser_compatibility This patch updates the minimum supported browsers as follows: - Google Chrome 125, which was released on 2024-05-15; see https://chromereleases.googleblog.com/2024/05/stable-channel-update-for-desktop_15.html - Safari 18, which was released on 2024-09-16; see https://developer.apple.com/documentation/safari-release-notes/safari-18-release-notes *Note:* This version is the first with experimental support for the `CanvasRenderingContext2D.filter` property, which is a long-standing missing feature in Safari, however it must be *manually enabled*; see https://developer.mozilla.org/en-US/docs/Web/API/CanvasRenderingContext2D/filter#browser_compatibility Note that nowadays we usually try, where feasible and possible, to support browsers that are about two years old. By limiting support to only "recent" browsers we reduce the risk of holding back improvements of the *built-in* Firefox PDF Viewer, and also (significantly) reduce the maintenance/support burden for the PDF.js contributors. *Please note:* As always, the minimum supported browser version assumes that a `legacy`-build of the PDF.js library is being used; see https://github.com/mozilla/pdf.js/wiki/Frequently-Asked-Questions#faq-support --- gulpfile.mjs | 45 ++---------- package-lock.json | 135 ----------------------------------- package.json | 3 - src/display/api.js | 27 ++----- src/display/display_utils.js | 12 +--- src/shared/util.js | 54 ++------------ 6 files changed, 20 insertions(+), 256 deletions(-) diff --git a/gulpfile.mjs b/gulpfile.mjs index 40c8247df..c103614cd 100644 --- a/gulpfile.mjs +++ b/gulpfile.mjs @@ -40,10 +40,7 @@ import Metalsmith from "metalsmith"; import ordered from "ordered-read-streams"; import path from "path"; import postcss from "gulp-postcss"; -import postcssDirPseudoClass from "postcss-dir-pseudo-class"; import postcssDiscardComments from "postcss-discard-comments"; -import postcssLightDarkFunction from "@csstools/postcss-light-dark-function"; -import postcssNesting from "postcss-nesting"; import { preprocess } from "./external/builder/builder.mjs"; import relative from "metalsmith-html-relative"; import rename from "gulp-rename"; @@ -91,9 +88,9 @@ const config = JSON.parse(fs.readFileSync(CONFIG_FILE).toString()); const ENV_TARGETS = [ "last 2 versions", - "Chrome >= 118", + "Chrome >= 125", "Firefox ESR", - "Safari >= 16.4", + "Safari >= 18", "Node >= 22", "> 1%", "not IE > 0", @@ -1246,15 +1243,7 @@ function buildGeneric(defines, dir) { preprocessHTML("web/viewer.html", defines).pipe(gulp.dest(dir + "web")), preprocessCSS("web/viewer.css", defines) - .pipe( - postcss([ - postcssDirPseudoClass(), - discardCommentsCSS(), - postcssNesting(), - postcssLightDarkFunction({ preserve: true }), - autoprefixer(AUTOPREFIXER_CONFIG), - ]) - ) + .pipe(postcss([discardCommentsCSS(), autoprefixer(AUTOPREFIXER_CONFIG)])) .pipe(gulp.dest(dir + "web")), gulp @@ -1314,15 +1303,7 @@ function buildComponents(defines, dir) { .src(COMPONENTS_IMAGES, { encoding: false }) .pipe(gulp.dest(dir + "images")), preprocessCSS("web/pdf_viewer.css", defines) - .pipe( - postcss([ - postcssDirPseudoClass(), - discardCommentsCSS(), - postcssNesting(), - postcssLightDarkFunction({ preserve: true }), - autoprefixer(AUTOPREFIXER_CONFIG), - ]) - ) + .pipe(postcss([discardCommentsCSS(), autoprefixer(AUTOPREFIXER_CONFIG)])) .pipe(gulp.dest(dir)), ]); } @@ -1651,13 +1632,7 @@ gulp.task( ), preprocessCSS("web/viewer.css", defines) .pipe( - postcss([ - postcssDirPseudoClass(), - discardCommentsCSS(), - postcssNesting(), - postcssLightDarkFunction({ preserve: true }), - autoprefixer(AUTOPREFIXER_CONFIG), - ]) + postcss([discardCommentsCSS(), autoprefixer(AUTOPREFIXER_CONFIG)]) ) .pipe(gulp.dest(CHROME_BUILD_CONTENT_DIR + "web")), @@ -2584,15 +2559,7 @@ function buildInternalViewer(defines, dir) { gulp.dest(dir + "web") ), preprocessCSS("web/internal/debugger.css", defines) - .pipe( - postcss([ - postcssDirPseudoClass(), - discardCommentsCSS(), - postcssNesting(), - postcssLightDarkFunction({ preserve: true }), - autoprefixer(AUTOPREFIXER_CONFIG), - ]) - ) + .pipe(postcss([discardCommentsCSS(), autoprefixer(AUTOPREFIXER_CONFIG)])) .pipe(gulp.dest(dir + "web")), createCMapBundle().pipe(gulp.dest(dir + "web/cmaps")), createICCBundle().pipe(gulp.dest(dir + "web/iccs")), diff --git a/package-lock.json b/package-lock.json index 79e6278ce..776485267 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,7 +10,6 @@ "@babel/core": "^7.29.0", "@babel/preset-env": "^7.29.2", "@babel/runtime": "^7.29.2", - "@csstools/postcss-light-dark-function": "^3.0.0", "@eslint/json": "^1.2.0", "@fluent/bundle": "^0.19.1", "@fluent/dom": "^0.10.2", @@ -53,9 +52,7 @@ "ordered-read-streams": "^2.0.0", "pngjs": "^7.0.0", "postcss": "^8.5.10", - "postcss-dir-pseudo-class": "^10.0.0", "postcss-discard-comments": "^7.0.7", - "postcss-nesting": "^14.0.0", "postcss-values-parser": "^7.0.0", "prettier": "^3.8.3", "puppeteer": "^24.42.0", @@ -1775,61 +1772,6 @@ "@csstools/css-tokenizer": "^4.0.0" } }, - "node_modules/@csstools/postcss-light-dark-function": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@csstools/postcss-light-dark-function/-/postcss-light-dark-function-3.0.0.tgz", - "integrity": "sha512-s++V5/hYazeRUCYIn2lsBVzUsxdeC46gtwpgW6lu5U/GlPOS5UTDT14kkEyPgXmFbCvaWLREqV7YTMJq1K3G6w==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/csstools" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - } - ], - "license": "MIT-0", - "dependencies": { - "@csstools/css-parser-algorithms": "^4.0.0", - "@csstools/css-tokenizer": "^4.0.0", - "@csstools/postcss-progressive-custom-properties": "^5.0.0", - "@csstools/utilities": "^3.0.0" - }, - "engines": { - "node": ">=20.19.0" - }, - "peerDependencies": { - "postcss": "^8.4" - } - }, - "node_modules/@csstools/postcss-progressive-custom-properties": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/@csstools/postcss-progressive-custom-properties/-/postcss-progressive-custom-properties-5.0.0.tgz", - "integrity": "sha512-NsJoZ89rxmDrUsITf8QIk5w+lQZQ8Xw5K6cLFG+cfiffsLYHb3zcbOOrHLetGl1WIhjWWQ4Cr8MMrg46Q+oACg==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/csstools" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - } - ], - "license": "MIT-0", - "dependencies": { - "postcss-value-parser": "^4.2.0" - }, - "engines": { - "node": ">=20.19.0" - }, - "peerDependencies": { - "postcss": "^8.4" - } - }, "node_modules/@csstools/selector-resolve-nested": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/@csstools/selector-resolve-nested/-/selector-resolve-nested-4.0.0.tgz", @@ -1876,29 +1818,6 @@ "postcss-selector-parser": "^7.1.1" } }, - "node_modules/@csstools/utilities": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@csstools/utilities/-/utilities-3.0.0.tgz", - "integrity": "sha512-etDqA/4jYvOGBM6yfKCOsEXfH96BKztZdgGmGqKi2xHnDe0ILIBraRspwgYatJH9JsCZ5HCGoCst8w18EKOAdg==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/csstools" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - } - ], - "license": "MIT-0", - "engines": { - "node": ">=20.19.0" - }, - "peerDependencies": { - "postcss": "^8.4" - } - }, "node_modules/@dot/log": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/@dot/log/-/log-0.2.1.tgz", @@ -9280,32 +9199,6 @@ "node": "^10 || ^12 || >=14" } }, - "node_modules/postcss-dir-pseudo-class": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/postcss-dir-pseudo-class/-/postcss-dir-pseudo-class-10.0.0.tgz", - "integrity": "sha512-DmtIzULpyC8XaH4b5AaUgt4Jic4QmrECqidNCdR7u7naQFdnxX80YI06u238a+ZVRXwURDxVzy0s/UQnWmpVeg==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/csstools" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - } - ], - "license": "MIT-0", - "dependencies": { - "postcss-selector-parser": "^7.1.1" - }, - "engines": { - "node": ">=20.19.0" - }, - "peerDependencies": { - "postcss": "^8.4" - } - }, "node_modules/postcss-discard-comments": { "version": "7.0.7", "resolved": "https://registry.npmjs.org/postcss-discard-comments/-/postcss-discard-comments-7.0.7.tgz", @@ -9362,34 +9255,6 @@ } } }, - "node_modules/postcss-nesting": { - "version": "14.0.0", - "resolved": "https://registry.npmjs.org/postcss-nesting/-/postcss-nesting-14.0.0.tgz", - "integrity": "sha512-YGFOfVrjxYfeGTS5XctP1WCI5hu8Lr9SmntjfRC+iX5hCihEO+QZl9Ra+pkjqkgoVdDKvb2JccpElcowhZtzpw==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/csstools" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - } - ], - "license": "MIT-0", - "dependencies": { - "@csstools/selector-resolve-nested": "^4.0.0", - "@csstools/selector-specificity": "^6.0.0", - "postcss-selector-parser": "^7.1.1" - }, - "engines": { - "node": ">=20.19.0" - }, - "peerDependencies": { - "postcss": "^8.4" - } - }, "node_modules/postcss-safe-parser": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/postcss-safe-parser/-/postcss-safe-parser-7.0.1.tgz", diff --git a/package.json b/package.json index 5b1f65614..139102a55 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,6 @@ "@babel/core": "^7.29.0", "@babel/preset-env": "^7.29.2", "@babel/runtime": "^7.29.2", - "@csstools/postcss-light-dark-function": "^3.0.0", "@eslint/json": "^1.2.0", "@fluent/bundle": "^0.19.1", "@fluent/dom": "^0.10.2", @@ -48,9 +47,7 @@ "ordered-read-streams": "^2.0.0", "pngjs": "^7.0.0", "postcss": "^8.5.10", - "postcss-dir-pseudo-class": "^10.0.0", "postcss-discard-comments": "^7.0.7", - "postcss-nesting": "^14.0.0", "postcss-values-parser": "^7.0.0", "prettier": "^3.8.3", "puppeteer": "^24.42.0", diff --git a/src/display/api.js b/src/display/api.js index 1f5f6d9bc..90a154cdb 100644 --- a/src/display/api.js +++ b/src/display/api.js @@ -42,14 +42,6 @@ import { CanvasDependencyTracker, CanvasImagesTracker, } from "./canvas_dependency_tracker.js"; -import { - deprecated, - isDataScheme, - isValidFetchUrl, - PageViewport, - RenderingCancelledException, - StatTimer, -} from "./display_utils.js"; import { FontFaceObject, FontLoader } from "./font_loader.js"; import { FontInfo, @@ -63,6 +55,13 @@ import { isRefProxy, LoopbackPort, } from "./api_utils.js"; +import { + isDataScheme, + isValidFetchUrl, + PageViewport, + RenderingCancelledException, + StatTimer, +} from "./display_utils.js"; import { MessageHandler, wrapReason } from "../shared/message_handler.js"; import { NodeBinaryDataFactory, @@ -649,18 +648,6 @@ class PDFDataRangeTransport { this.initialData = initialData; this.progressiveDone = progressiveDone; this.contentDispositionFilename = contentDispositionFilename; - - if (typeof PDFJSDev === "undefined" || PDFJSDev.test("GENERIC")) { - Object.defineProperty(this, "onDataProgress", { - value: () => { - deprecated( - "`PDFDataRangeTransport.prototype.onDataProgress` - method was " + - "removed, since loading progress is now reported automatically " + - "through the `PDFDataTransportStream` class (and related code)." - ); - }, - }); - } } /** diff --git a/src/display/display_utils.js b/src/display/display_utils.js index 37360a0ac..a4bd75133 100644 --- a/src/display/display_utils.js +++ b/src/display/display_utils.js @@ -16,7 +16,6 @@ import { BaseException, DrawOPS, - FeatureTest, shadow, stripPath, Util, @@ -677,16 +676,9 @@ function setLayerDimensions( if (viewport instanceof PageViewport) { const { pageWidth, pageHeight } = viewport.rawDims; const { style } = div; - const useRound = FeatureTest.isCSSRoundSupported; - const w = `var(--total-scale-factor) * ${pageWidth}px`, - h = `var(--total-scale-factor) * ${pageHeight}px`; - const widthStr = useRound - ? `round(down, ${w}, var(--scale-round-x))` - : `calc(${w})`, - heightStr = useRound - ? `round(down, ${h}, var(--scale-round-y))` - : `calc(${h})`; + const widthStr = `round(down, var(--total-scale-factor) * ${pageWidth}px, var(--scale-round-x))`, + heightStr = `round(down, var(--total-scale-factor) * ${pageHeight}px, var(--scale-round-y))`; if (!mustFlip || viewport.rotation % 180 === 0) { style.width = widthStr; diff --git a/src/shared/util.js b/src/shared/util.js index ed7c0a14d..089a74349 100644 --- a/src/shared/util.js +++ b/src/shared/util.js @@ -601,17 +601,13 @@ function objectSize(obj) { return Object.keys(obj).length; } -// Checks the endianness of the platform. -function isLittleEndian() { - const buffer8 = new Uint8Array(4); - buffer8[0] = 1; - const view32 = new Uint32Array(buffer8.buffer, 0, 1); - return view32[0] === 1; -} - class FeatureTest { static get isLittleEndian() { - return shadow(this, "isLittleEndian", isLittleEndian()); + const buffer8 = new Uint8Array(4); + buffer8[0] = 1; + const view32 = new Uint32Array(buffer8.buffer, 0, 1); + + return shadow(this, "isLittleEndian", view32[0] === 1); } static get isOffscreenCanvasSupported() { @@ -660,14 +656,6 @@ class FeatureTest { }); } - static get isCSSRoundSupported() { - return shadow( - this, - "isCSSRoundSupported", - globalThis.CSS?.supports?.("width: round(1.5px, 1px)") - ); - } - static get isAlphaColorInputSupported() { return shadow( this, @@ -1259,38 +1247,6 @@ if ( }; } -// TODO: Remove this once Safari 17.4 is the lowest supported version. -if ( - typeof PDFJSDev !== "undefined" && - !PDFJSDev.test("SKIP_BABEL") && - typeof AbortSignal.any !== "function" -) { - AbortSignal.any = function (iterable) { - const ac = new AbortController(); - const { signal } = ac; - - // Return immediately if any of the signals are already aborted. - for (const s of iterable) { - if (s.aborted) { - ac.abort(s.reason); - return signal; - } - } - // Register "abort" listeners for all signals. - for (const s of iterable) { - s.addEventListener( - "abort", - () => { - ac.abort(s.reason); - }, - { signal } // Automatically remove the listener. - ); - } - - return signal; - }; -} - export { _isValidExplicitDest, AbortException,