From 35e78f7f111577948c15cc6cd2faf459368f323c Mon Sep 17 00:00:00 2001 From: Jonas Jenwald Date: Fri, 30 Jan 2026 09:30:55 +0100 Subject: [PATCH 1/5] Generate the `preferences_schema.json` file, for the Chromium addon, during building This avoids the hassle of having to manually update that file when adding/modifying preferences in the viewer. Updating the preferences-metadata should now only be something that the Chromium addon maintainer has to do. --- .github/workflows/lint.yml | 3 - extensions/chromium/preferences_schema.json | 256 ------------------- external/chromium/prefs.mjs | 270 ++++++++++++++++++++ gulpfile.mjs | 101 ++------ 4 files changed, 286 insertions(+), 344 deletions(-) delete mode 100644 extensions/chromium/preferences_schema.json create mode 100644 external/chromium/prefs.mjs diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 26924ed39..94e849728 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -30,8 +30,5 @@ jobs: - name: Run lint run: npx gulp lint - - name: Run lint-chromium - run: npx gulp lint-chromium - - name: Run lint-mozcentral run: npx gulp lint-mozcentral diff --git a/extensions/chromium/preferences_schema.json b/extensions/chromium/preferences_schema.json deleted file mode 100644 index 269d71e66..000000000 --- a/extensions/chromium/preferences_schema.json +++ /dev/null @@ -1,256 +0,0 @@ -{ - "type": "object", - "properties": { - "viewerCssTheme": { - "title": "Theme", - "description": "The theme to use.\n0 = Use system theme.\n1 = Light theme.\n2 = Dark theme.", - "type": "integer", - "enum": [0, 1, 2], - "default": 2 - }, - "showPreviousViewOnLoad": { - "description": "DEPRECATED. Set viewOnLoad to 1 to disable showing the last page/position on load.", - "type": "boolean", - "default": true - }, - "viewOnLoad": { - "title": "View position on load", - "description": "The position in the document upon load.\n -1 = Default (uses OpenAction if available, otherwise equal to `viewOnLoad = 0`).\n 0 = The last viewed page/position.\n 1 = The initial page/position.", - "type": "integer", - "enum": [-1, 0, 1], - "default": 0 - }, - "defaultZoomDelay": { - "title": "Default zoom delay", - "description": "Delay (in ms) to wait before redrawing the canvas.", - "type": "integer", - "default": 400 - }, - "defaultZoomValue": { - "title": "Default zoom level", - "description": "Default zoom level of the viewer. Accepted values: 'auto', 'page-actual', 'page-width', 'page-height', 'page-fit', or a zoom level in percents.", - "type": "string", - "pattern": "|auto|page-actual|page-width|page-height|page-fit|[0-9]+\\.?[0-9]*(,[0-9]+\\.?[0-9]*){0,2}", - "default": "" - }, - "sidebarViewOnLoad": { - "title": "Sidebar state on load", - "description": "Controls the state of the sidebar upon load.\n -1 = Default (uses PageMode if available, otherwise the last position if available/enabled).\n 0 = Do not show sidebar.\n 1 = Show thumbnails in sidebar.\n 2 = Show document outline in sidebar.\n 3 = Show attachments in sidebar.", - "type": "integer", - "enum": [-1, 0, 1, 2, 3], - "default": -1 - }, - "enableHandToolOnLoad": { - "description": "DEPRECATED. Set cursorToolOnLoad to 1 to enable the hand tool by default.", - "type": "boolean", - "default": false - }, - "enableHWA": { - "title": "Enable hardware acceleration", - "description": "Whether to enable hardware acceleration.", - "type": "boolean", - "default": true - }, - "enableAltText": { - "type": "boolean", - "default": false - }, - "enableGuessAltText": { - "type": "boolean", - "default": true - }, - "enableAltTextModelDownload": { - "type": "boolean", - "default": true - }, - "enableNewAltTextWhenAddingImage": { - "type": "boolean", - "default": true - }, - "altTextLearnMoreUrl": { - "type": "string", - "default": "" - }, - "commentLearnMoreUrl": { - "type": "string", - "default": "" - }, - "enableSignatureEditor": { - "type": "boolean", - "default": false - }, - "enableSplitMerge": { - "type": "boolean", - "default": false - }, - "enableUpdatedAddImage": { - "type": "boolean", - "default": false - }, - "cursorToolOnLoad": { - "title": "Cursor tool on load", - "description": "The cursor tool that is enabled upon load.\n 0 = Text selection tool.\n 1 = Hand tool.", - "type": "integer", - "enum": [0, 1], - "default": 0 - }, - "pdfBugEnabled": { - "title": "Enable debugging tools", - "description": "Whether to enable debugging tools.", - "type": "boolean", - "default": false - }, - "enableScripting": { - "title": "Enable active content (JavaScript) in PDFs", - "type": "boolean", - "description": "Whether to allow execution of active content (JavaScript) by PDF files.", - "default": false - }, - "enableHighlightFloatingButton": { - "type": "boolean", - "default": false - }, - "highlightEditorColors": { - "type": "string", - "default": "yellow=#FFFF98,green=#53FFBC,blue=#80EBFF,pink=#FFCBE6,red=#FF4F5F,yellow_HCM=#FFFFCC,green_HCM=#53FFBC,blue_HCM=#80EBFF,pink_HCM=#F6B8FF,red_HCM=#C50043" - }, - "disableRange": { - "title": "Disable range requests", - "description": "Whether to disable range requests (not recommended).", - "type": "boolean", - "default": false - }, - "disableStream": { - "title": "Disable streaming for requests", - "description": "Whether to disable streaming for requests (not recommended).", - "type": "boolean", - "default": false - }, - "disableAutoFetch": { - "type": "boolean", - "default": false - }, - "disableFontFace": { - "title": "Disable @font-face", - "description": "Whether to disable @font-face and fall back to canvas rendering (this is more resource-intensive).", - "type": "boolean", - "default": false - }, - "disableTextLayer": { - "description": "DEPRECATED. Set textLayerMode to 0 to disable the text selection layer by default.", - "type": "boolean", - "default": false - }, - "textLayerMode": { - "title": "Text layer mode", - "description": "Controls if the text layer is enabled, and the selection mode that is used.\n 0 = Disabled.\n 1 = Enabled.", - "type": "integer", - "enum": [0, 1], - "default": 1 - }, - "externalLinkTarget": { - "title": "External links target window", - "description": "Controls how external links will be opened.\n 0 = default.\n 1 = replaces current window.\n 2 = new window/tab.\n 3 = parent.\n 4 = in top window.", - "type": "integer", - "enum": [0, 1, 2, 3, 4], - "default": 0 - }, - "disablePageLabels": { - "type": "boolean", - "default": false - }, - "disablePageMode": { - "description": "DEPRECATED.", - "type": "boolean", - "default": false - }, - "disableTelemetry": { - "title": "Disable telemetry", - "type": "boolean", - "description": "Whether to prevent the extension from reporting the extension and browser version to the extension developers.", - "default": false - }, - "annotationMode": { - "type": "integer", - "enum": [0, 1, 2, 3], - "default": 2 - }, - "annotationEditorMode": { - "type": "integer", - "enum": [-1, 0, 3, 15], - "default": 0 - }, - "capCanvasAreaFactor": { - "type": "integer", - "default": 200 - }, - "enablePermissions": { - "type": "boolean", - "default": false - }, - "enableXfa": { - "type": "boolean", - "default": true - }, - "historyUpdateUrl": { - "type": "boolean", - "default": false - }, - "ignoreDestinationZoom": { - "title": "Ignore the zoom argument in destinations", - "description": "When enabled it will maintain the currently active zoom level, rather than letting the PDF document modify it, when navigating to internal destinations.", - "type": "boolean", - "default": false - }, - "enablePrintAutoRotate": { - "title": "Automatically rotate printed pages", - "description": "When enabled, landscape pages are rotated when printed.", - "type": "boolean", - "default": true - }, - "scrollModeOnLoad": { - "title": "Scroll mode on load", - "description": "Controls how the viewer scrolls upon load.\n -1 = Default (uses the last position if available/enabled).\n 3 = Page scrolling.\n 0 = Vertical scrolling.\n 1 = Horizontal scrolling.\n 2 = Wrapped scrolling.", - "type": "integer", - "enum": [-1, 0, 1, 2, 3], - "default": -1 - }, - "spreadModeOnLoad": { - "title": "Spread mode on load", - "description": "Whether the viewer should join pages into spreads upon load.\n -1 = Default (uses the last position if available/enabled).\n 0 = No spreads.\n 1 = Odd spreads.\n 2 = Even spreads.", - "type": "integer", - "enum": [-1, 0, 1, 2], - "default": -1 - }, - "forcePageColors": { - "description": "When enabled, the pdf rendering will use the high contrast mode colors", - "type": "boolean", - "default": false - }, - "pageColorsBackground": { - "description": "The color is a string as defined in CSS. Its goal is to help improve readability in high contrast mode", - "type": "string", - "default": "Canvas" - }, - "pageColorsForeground": { - "description": "The color is a string as defined in CSS. Its goal is to help improve readability in high contrast mode", - "type": "string", - "default": "CanvasText" - }, - "enableAutoLinking": { - "description": "Enable creation of hyperlinks from text that look like URLs.", - "type": "boolean", - "default": true - }, - "enableComment": { - "description": "Enable creation of comment annotations.", - "type": "boolean", - "default": false - }, - "enableOptimizedPartialRendering": { - "description": "Enable tracking of PDF operations to optimize partial rendering.", - "type": "boolean", - "default": false - } - } -} diff --git a/external/chromium/prefs.mjs b/external/chromium/prefs.mjs new file mode 100644 index 000000000..63e3b10e8 --- /dev/null +++ b/external/chromium/prefs.mjs @@ -0,0 +1,270 @@ +/* Copyright 2026 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. + */ + +const prefsMetadata = { + annotationEditorMode: { + enum: [-1, 0, 3, 15], + }, + annotationMode: { + enum: [0, 1, 2, 3], + }, + cursorToolOnLoad: { + title: "Cursor tool on load", + description: + "The cursor tool that is enabled upon load.\n 0 = Text selection tool.\n 1 = Hand tool.", + enum: [0, 1], + }, + defaultZoomDelay: { + title: "Default zoom delay", + description: "Delay (in ms) to wait before redrawing the canvas.", + }, + defaultZoomValue: { + title: "Default zoom level", + description: + "Default zoom level of the viewer. Accepted values: 'auto', 'page-actual', 'page-width', 'page-height', 'page-fit', or a zoom level in percents.", + pattern: + "|auto|page-actual|page-width|page-height|page-fit|[0-9]+\\.?[0-9]*(,[0-9]+\\.?[0-9]*){0,2}", + }, + disableFontFace: { + title: "Disable @font-face", + description: + "Whether to disable @font-face and fall back to canvas rendering (this is more resource-intensive).", + }, + disableRange: { + title: "Disable range requests", + description: "Whether to disable range requests (not recommended).", + }, + disableStream: { + title: "Disable streaming for requests", + description: "Whether to disable streaming for requests (not recommended).", + }, + disableTelemetry: { + title: "Disable telemetry", + description: + "Whether to prevent the extension from reporting the extension and browser version to the extension developers.", + }, + enableAutoLinking: { + description: "Enable creation of hyperlinks from text that look like URLs.", + }, + enableComment: { + description: "Enable creation of comment annotations.", + }, + enableHWA: { + title: "Enable hardware acceleration", + description: "Whether to enable hardware acceleration.", + }, + enableOptimizedPartialRendering: { + description: + "Enable tracking of PDF operations to optimize partial rendering.", + }, + enablePrintAutoRotate: { + title: "Automatically rotate printed pages", + description: "When enabled, landscape pages are rotated when printed.", + }, + enableScripting: { + title: "Enable active content (JavaScript) in PDFs", + description: + "Whether to allow execution of active content (JavaScript) by PDF files.", + }, + externalLinkTarget: { + title: "External links target window", + description: + "Controls how external links will be opened.\n 0 = default.\n 1 = replaces current window.\n 2 = new window/tab.\n 3 = parent.\n 4 = in top window.", + enum: [0, 1, 2, 3, 4], + }, + forcePageColors: { + description: + "When enabled, the pdf rendering will use the high contrast mode colors", + }, + ignoreDestinationZoom: { + title: "Ignore the zoom argument in destinations", + description: + "When enabled it will maintain the currently active zoom level, rather than letting the PDF document modify it, when navigating to internal destinations.", + }, + pageColorsBackground: { + description: + "The color is a string as defined in CSS. Its goal is to help improve readability in high contrast mode", + }, + pageColorsForeground: { + description: + "The color is a string as defined in CSS. Its goal is to help improve readability in high contrast mode", + }, + pdfBugEnabled: { + title: "Enable debugging tools", + description: "Whether to enable debugging tools.", + }, + scrollModeOnLoad: { + title: "Scroll mode on load", + description: + "Controls how the viewer scrolls upon load.\n -1 = Default (uses the last position if available/enabled).\n 0 = Vertical scrolling.\n 1 = Horizontal scrolling.\n 2 = Wrapped scrolling.\n 3 = Page scrolling.", + enum: [-1, 0, 1, 2, 3], + }, + sidebarViewOnLoad: { + title: "Sidebar state on load", + description: + "Controls the state of the sidebar upon load.\n -1 = Default (uses PageMode if available, otherwise the last position if available/enabled).\n 0 = Do not show sidebar.\n 1 = Show thumbnails in sidebar.\n 2 = Show document outline in sidebar.\n 3 = Show attachments in sidebar.", + enum: [-1, 0, 1, 2, 3], + }, + spreadModeOnLoad: { + title: "Spread mode on load", + description: + "Whether the viewer should join pages into spreads upon load.\n -1 = Default (uses the last position if available/enabled).\n 0 = No spreads.\n 1 = Odd spreads.\n 2 = Even spreads.", + enum: [-1, 0, 1, 2], + }, + textLayerMode: { + title: "Text layer mode", + description: + "Controls if the text layer is enabled, and the selection mode that is used.\n 0 = Disabled.\n 1 = Enabled.", + enum: [0, 1], + }, + viewerCssTheme: { + title: "Theme", + description: + "The theme to use.\n0 = Use system theme.\n1 = Light theme.\n2 = Dark theme.", + enum: [0, 1, 2], + }, + viewOnLoad: { + title: "View position on load", + description: + "The position in the document upon load.\n -1 = Default (uses OpenAction if available, otherwise equal to `viewOnLoad = 0`).\n 0 = The last viewed page/position.\n 1 = The initial page/position.", + enum: [-1, 0, 1], + }, +}; + +// Deprecated keys are allowed in the managed preferences file. +// The code maintainer is responsible for adding migration logic to +// extensions/chromium/options/migration.js and web/chromecom.js . +const deprecatedPrefs = { + disablePageMode: { + description: "DEPRECATED.", + type: "boolean", + default: false, + }, + disableTextLayer: { + description: + "DEPRECATED. Set textLayerMode to 0 to disable the text selection layer by default.", + type: "boolean", + default: false, + }, + enableHandToolOnLoad: { + description: + "DEPRECATED. Set cursorToolOnLoad to 1 to enable the hand tool by default.", + type: "boolean", + default: false, + }, + showPreviousViewOnLoad: { + description: + "DEPRECATED. Set viewOnLoad to 1 to disable showing the last page/position on load.", + type: "boolean", + default: true, + }, +}; + +function buildPrefsSchema(prefs) { + const properties = Object.create(null); + + for (const name in prefs) { + const pref = prefs[name]; + let type = typeof pref; + + switch (type) { + case "boolean": + case "string": + break; + case "number": + type = "integer"; + break; + default: + throw new Error(`Invalid type (${type}) for "${name}"-preference.`); + } + + const metadata = prefsMetadata[name]; + if (metadata) { + let numMetadataKeys = 0; + // Do some (very basic) validation of the metadata. + for (const key in metadata) { + const entry = metadata[key]; + + switch (key) { + case "default": + case "type": + throw new Error( + `Invalid key (${key}) in metadata for "${name}"-preference.` + ); + case "description": + if (entry.startsWith("DEPRECATED.")) { + throw new Error( + `The \`description\` of the "${name}"-preference cannot begin with "DEPRECATED."` + ); + } + break; + } + numMetadataKeys++; + } + if (numMetadataKeys === 0) { + throw new Error( + `No metadata for "${name}"-preference, remove the entry.` + ); + } + } + + properties[name] = { + type, + default: pref, + ...metadata, + }; + } + + for (const name in prefsMetadata) { + if (!properties[name]) { + // Do *not* throw here, since keeping the metadata up-to-date should be + // the responsibility of the CHROMIUM-addon maintainer. + console.error( + `The "${name}"-preference was removed, add it to \`deprecatedPrefs\` instead.\n` + ); + } + } + + for (const name in deprecatedPrefs) { + const entry = deprecatedPrefs[name]; + + if (properties[name]) { + throw new Error( + `The "${name}"-preference should not be listed as deprecated.` + ); + } + if (!entry.description?.startsWith("DEPRECATED.")) { + throw new Error( + `The \`description\` of the deprecated "${name}"-preference must begin with "DEPRECATED."` + ); + } + for (const key of ["default", "type"]) { + if (key in entry) { + continue; + } + throw new Error( + `A \`${key}\` entry must be provided for the deprecated "${name}"-preference.` + ); + } + properties[name] = entry; + } + + return { + type: "object", + properties, + }; +} + +export { buildPrefsSchema }; diff --git a/gulpfile.mjs b/gulpfile.mjs index 3ad321ee3..b5c333617 100644 --- a/gulpfile.mjs +++ b/gulpfile.mjs @@ -20,6 +20,7 @@ import { import { exec, execSync, spawn, spawnSync } from "child_process"; import autoprefixer from "autoprefixer"; import babel from "@babel/core"; +import { buildPrefsSchema } from "./external/chromium/prefs.mjs"; import crypto from "crypto"; import fs from "fs"; import gulp from "gulp"; @@ -452,51 +453,6 @@ function getVersionJSON() { return JSON.parse(fs.readFileSync(BUILD_DIR + "version.json").toString()); } -function checkChromePreferencesFile(chromePrefsPath, webPrefs) { - const chromePrefs = JSON.parse(fs.readFileSync(chromePrefsPath).toString()); - const chromePrefsKeys = Object.keys(chromePrefs.properties).filter(key => { - const description = chromePrefs.properties[key].description; - // Deprecated keys are allowed in the managed preferences file. - // The code maintainer is responsible for adding migration logic to - // extensions/chromium/options/migration.js and web/chromecom.js . - return !description?.startsWith("DEPRECATED."); - }); - - let ret = true; - // Verify that every entry in webPrefs is also in preferences_schema.json. - for (const [key, value] of Object.entries(webPrefs)) { - if (!chromePrefsKeys.includes(key)) { - // Note: this would also reject keys that are present but marked as - // DEPRECATED. A key should not be marked as DEPRECATED if it is still - // listed in webPrefs. - ret = false; - console.log( - `Warning: ${chromePrefsPath} does not contain an entry for pref: ${key}` - ); - } else if (chromePrefs.properties[key].default !== value) { - ret = false; - console.log( - `Warning: not the same values (for "${key}"): ` + - `${chromePrefs.properties[key].default} !== ${value}` - ); - } - } - - // Verify that preferences_schema.json does not contain entries that are not - // in webPrefs (app_options.js). - for (const key of chromePrefsKeys) { - if (!(key in webPrefs)) { - ret = false; - console.log( - `Warning: ${chromePrefsPath} contains an unrecognized pref: ${key}. ` + - `Remove it, or prepend "DEPRECATED. " and add migration logic to ` + - `extensions/chromium/options/migration.js and web/chromecom.js.` - ); - } - } - return ret; -} - function createMainBundle(defines) { const mainFileConfig = createWebpackConfig(defines, { filename: defines.MINIFIED ? "pdf.min.mjs" : "pdf.mjs", @@ -1490,6 +1446,16 @@ gulp.task( ) ); +function createChromiumPrefsSchema() { + const prefs = getDefaultPreferences("chromium/"); + const chromiumPrefs = buildPrefsSchema(prefs); + + return createStringSource( + "preferences_schema.json", + JSON.stringify(chromiumPrefs, null, 2) + ); +} + gulp.task( "chromium", gulp.series( @@ -1582,14 +1548,12 @@ gulp.task( .pipe(replace(/\bPDFJSSCRIPT_VERSION\b/g, version)) .pipe(gulp.dest(CHROME_BUILD_DIR)), gulp - .src( - [ - "extensions/chromium/**/*.{html,js,css,png}", - "extensions/chromium/preferences_schema.json", - ], - { base: "extensions/chromium/", encoding: false } - ) + .src(["extensions/chromium/**/*.{html,js,css,png}"], { + base: "extensions/chromium/", + encoding: false, + }) .pipe(gulp.dest(CHROME_BUILD_DIR)), + createChromiumPrefsSchema().pipe(gulp.dest(CHROME_BUILD_DIR)), ]); } ) @@ -2124,39 +2088,6 @@ gulp.task( }) ); -gulp.task( - "lint-chromium", - gulp.series( - function scriptingLintChromium() { - const defines = { - ...DEFINES, - CHROME: true, - SKIP_BABEL: false, - TESTING: false, - }; - return buildDefaultPreferences(defines, "lint-chromium/"); - }, - async function prefsLintChromium() { - await parseDefaultPreferences("lint-chromium/"); - }, - function runLintChromium(done) { - console.log(); - console.log("### Checking supplemental Chromium files"); - - if ( - !checkChromePreferencesFile( - "extensions/chromium/preferences_schema.json", - getDefaultPreferences("lint-chromium/") - ) - ) { - done(new Error("chromium/preferences_schema is not in sync.")); - return; - } - done(); - } - ) -); - gulp.task("dev-wasm", function () { const VIEWER_WASM_OUTPUT = "web/wasm/"; From 06cf7dd7b045f929a7c51bf8cef94fa0c737ee6a Mon Sep 17 00:00:00 2001 From: Jonas Jenwald Date: Fri, 30 Jan 2026 09:31:28 +0100 Subject: [PATCH 2/5] Stop pre-building the preference defaults, to simplify the build scripts This is a left-over from before the introduction of `AppOptions`, but is no longer necessary now. --- gulpfile.mjs | 103 ++++++++-------------------------- test/unit/app_options_spec.js | 18 ++++++ web/preferences.js | 16 ++---- 3 files changed, 45 insertions(+), 92 deletions(-) diff --git a/gulpfile.mjs b/gulpfile.mjs index b5c333617..e46b82292 100644 --- a/gulpfile.mjs +++ b/gulpfile.mjs @@ -284,7 +284,6 @@ function createWebpackConfig( disableVersionInfo = false, disableSourceMaps = false, disableLicenseHeader = false, - defaultPreferencesDir = null, } = {} ) { const versionInfo = !disableVersionInfo @@ -295,9 +294,6 @@ function createWebpackConfig( BUNDLE_VERSION: versionInfo.version, BUNDLE_BUILD: versionInfo.commit, TESTING: defines.TESTING ?? process.env.TESTING === "true", - DEFAULT_PREFERENCES: defaultPreferencesDir - ? getDefaultPreferences(defaultPreferencesDir) - : {}, DEFAULT_FTL: defines.GENERIC ? getDefaultFtl() : "", }; const licenseHeaderLibre = fs @@ -546,36 +542,24 @@ function createWorkerBundle(defines) { } function createWebBundle(defines, options) { - const viewerFileConfig = createWebpackConfig( - defines, - { - filename: "viewer.mjs", - library: { - type: "module", - }, + const viewerFileConfig = createWebpackConfig(defines, { + filename: "viewer.mjs", + library: { + type: "module", }, - { - defaultPreferencesDir: options.defaultPreferencesDir, - } - ); + }); return gulp .src("./web/viewer.js", { encoding: false }) .pipe(webpack2Stream(viewerFileConfig)); } function createGVWebBundle(defines, options) { - const viewerFileConfig = createWebpackConfig( - defines, - { - filename: "viewer-geckoview.mjs", - library: { - type: "module", - }, + const viewerFileConfig = createWebpackConfig(defines, { + filename: "viewer-geckoview.mjs", + library: { + type: "module", }, - { - defaultPreferencesDir: options.defaultPreferencesDir, - } - ); + }); return gulp .src("./web/viewer-geckoview.js", { encoding: false }) .pipe(webpack2Stream(viewerFileConfig)); @@ -1063,11 +1047,7 @@ function buildGeneric(defines, dir) { createMainBundle(defines).pipe(gulp.dest(dir + "build")), createWorkerBundle(defines).pipe(gulp.dest(dir + "build")), createSandboxBundle(defines).pipe(gulp.dest(dir + "build")), - createWebBundle(defines, { - defaultPreferencesDir: defines.SKIP_BABEL - ? "generic/" - : "generic-legacy/", - }).pipe(gulp.dest(dir + "web")), + createWebBundle(defines).pipe(gulp.dest(dir + "web")), gulp .src(COMMON_WEB_FILES, { base: "web/", encoding: false }) .pipe(gulp.dest(dir + "web")), @@ -1111,13 +1091,7 @@ gulp.task( "locale", function scriptingGeneric() { const defines = { ...DEFINES, GENERIC: true }; - return ordered([ - buildDefaultPreferences(defines, "generic/"), - createTemporaryScriptingBundle(defines), - ]); - }, - async function prefsGeneric() { - await parseDefaultPreferences("generic/"); + return createTemporaryScriptingBundle(defines); }, function createGeneric() { console.log(); @@ -1138,13 +1112,7 @@ gulp.task( "locale", function scriptingGenericLegacy() { const defines = { ...DEFINES, GENERIC: true, SKIP_BABEL: false }; - return ordered([ - buildDefaultPreferences(defines, "generic-legacy/"), - createTemporaryScriptingBundle(defines), - ]); - }, - async function prefsGenericLegacy() { - await parseDefaultPreferences("generic-legacy/"); + return createTemporaryScriptingBundle(defines); }, function createGenericLegacy() { console.log(); @@ -1258,13 +1226,7 @@ gulp.task( "locale", function scriptingMinified() { const defines = { ...DEFINES, MINIFIED: true, GENERIC: true }; - return ordered([ - buildDefaultPreferences(defines, "minified/"), - createTemporaryScriptingBundle(defines), - ]); - }, - async function prefsMinified() { - await parseDefaultPreferences("minified/"); + return createTemporaryScriptingBundle(defines); }, function createMinified() { console.log(); @@ -1288,13 +1250,7 @@ gulp.task( GENERIC: true, SKIP_BABEL: false, }; - return ordered([ - buildDefaultPreferences(defines, "minified-legacy/"), - createTemporaryScriptingBundle(defines), - ]); - }, - async function prefsMinifiedLegacy() { - await parseDefaultPreferences("minified-legacy/"); + return createTemporaryScriptingBundle(defines); }, function createMinifiedLegacy() { console.log(); @@ -1389,12 +1345,12 @@ gulp.task( createWorkerBundle(defines).pipe( gulp.dest(MOZCENTRAL_CONTENT_DIR + "build") ), - createWebBundle(defines, { defaultPreferencesDir: "mozcentral/" }).pipe( + createWebBundle(defines).pipe( + gulp.dest(MOZCENTRAL_CONTENT_DIR + "web") + ), + createGVWebBundle(gvDefines).pipe( gulp.dest(MOZCENTRAL_CONTENT_DIR + "web") ), - createGVWebBundle(gvDefines, { - defaultPreferencesDir: "mozcentral/", - }).pipe(gulp.dest(MOZCENTRAL_CONTENT_DIR + "web")), gulp .src(MOZCENTRAL_WEB_FILES, { base: "web/", encoding: false }) .pipe(gulp.dest(MOZCENTRAL_CONTENT_DIR + "web")), @@ -1499,7 +1455,7 @@ gulp.task( createSandboxBundle(defines).pipe( gulp.dest(CHROME_BUILD_CONTENT_DIR + "build") ), - createWebBundle(defines, { defaultPreferencesDir: "chromium/" }).pipe( + createWebBundle(defines).pipe( gulp.dest(CHROME_BUILD_CONTENT_DIR + "web") ), gulp @@ -1634,9 +1590,6 @@ function buildLib(defines, dir) { BUNDLE_VERSION: versionInfo.version, BUNDLE_BUILD: versionInfo.commit, TESTING: defines.TESTING ?? process.env.TESTING === "true", - DEFAULT_PREFERENCES: getDefaultPreferences( - defines.SKIP_BABEL ? "lib/" : "lib-legacy/" - ), DEFAULT_FTL: getDefaultFtl(), }; @@ -1667,13 +1620,7 @@ gulp.task( createBuildNumber, function scriptingLib() { const defines = { ...DEFINES, GENERIC: true, LIB: true }; - return ordered([ - buildDefaultPreferences(defines, "lib/"), - createTemporaryScriptingBundle(defines), - ]); - }, - async function prefsLib() { - await parseDefaultPreferences("lib/"); + return createTemporaryScriptingBundle(defines); }, function createLib() { const defines = { ...DEFINES, GENERIC: true, LIB: true }; @@ -1697,13 +1644,7 @@ gulp.task( LIB: true, SKIP_BABEL: false, }; - return ordered([ - buildDefaultPreferences(defines, "lib-legacy/"), - createTemporaryScriptingBundle(defines), - ]); - }, - async function prefsLibLegacy() { - await parseDefaultPreferences("lib-legacy/"); + return createTemporaryScriptingBundle(defines); }, function createLibLegacy() { const defines = { diff --git a/test/unit/app_options_spec.js b/test/unit/app_options_spec.js index 13128404f..8aa945b7b 100644 --- a/test/unit/app_options_spec.js +++ b/test/unit/app_options_spec.js @@ -14,6 +14,7 @@ */ import { AppOptions, OptionKind } from "../../web/app_options.js"; +import { BasePreferences } from "../../web/preferences.js"; import { objectSize } from "../../src/shared/util.js"; describe("AppOptions", function () { @@ -39,3 +40,20 @@ describe("AppOptions", function () { expect(objectSize(options)).toBeLessThanOrEqual(MAX_NUMBER_OF_PREFS); }); }); + +describe("BasePreferences", function () { + it("checks that preference defaults are correct", async function () { + const TestPreferences = class extends BasePreferences { + async _readFromStorage(prefObj) { + return { prefs: Object.create(null) }; + } + }; + + const testPrefs = new TestPreferences(); + await testPrefs.initializedPromise; + + expect(testPrefs.defaults).toEqual( + AppOptions.getAll(OptionKind.PREFERENCE, /* defaultOnly = */ true) + ); + }); +}); diff --git a/web/preferences.js b/web/preferences.js index f290ed9d7..1978be96a 100644 --- a/web/preferences.js +++ b/web/preferences.js @@ -22,9 +22,7 @@ import { AppOptions, OptionKind } from "./app_options.js"; */ class BasePreferences { #defaults = Object.freeze( - typeof PDFJSDev === "undefined" - ? AppOptions.getAll(OptionKind.PREFERENCE, /* defaultOnly = */ true) - : PDFJSDev.eval("DEFAULT_PREFERENCES") + AppOptions.getAll(OptionKind.PREFERENCE, /* defaultOnly = */ true) ); #initializedPromise = null; @@ -37,14 +35,6 @@ class BasePreferences { throw new Error("Cannot initialize BasePreferences."); } - if (typeof PDFJSDev !== "undefined" && PDFJSDev.test("CHROME")) { - Object.defineProperty(this, "defaults", { - get() { - return this.#defaults; - }, - }); - } - this.#initializedPromise = this._readFromStorage(this.#defaults).then( ({ browserPrefs, prefs }) => { if ( @@ -135,6 +125,10 @@ class BasePreferences { return AppOptions.get(name); } + get defaults() { + return this.#defaults; + } + get initializedPromise() { return this.#initializedPromise; } From 2a83f955b052254aa8528ffb65eecefa346a44e6 Mon Sep 17 00:00:00 2001 From: Jonas Jenwald Date: Fri, 30 Jan 2026 09:32:41 +0100 Subject: [PATCH 3/5] Make `getDefaultPreferences` a synchronous function, to simplify the build scripts --- gulpfile.mjs | 28 +++++++--------------------- 1 file changed, 7 insertions(+), 21 deletions(-) diff --git a/gulpfile.mjs b/gulpfile.mjs index e46b82292..858633d85 100644 --- a/gulpfile.mjs +++ b/gulpfile.mjs @@ -888,12 +888,15 @@ function buildDefaultPreferences(defines, dir) { .pipe(gulp.dest(DEFAULT_PREFERENCES_DIR + dir)); } -async function parseDefaultPreferences(dir) { +function getDefaultPreferences(dir) { console.log(); console.log("### Parsing default preferences"); - // eslint-disable-next-line no-unsanitized/method - const { AppOptions, OptionKind } = await import( + const require = process + .getBuiltinModule("module") + .createRequire(import.meta.url); + + const { AppOptions, OptionKind } = require( "./" + DEFAULT_PREFERENCES_DIR + dir + "app_options.mjs" ); @@ -904,18 +907,7 @@ async function parseDefaultPreferences(dir) { if (Object.keys(prefs).length === 0) { throw new Error("No default preferences found."); } - - fs.writeFileSync( - DEFAULT_PREFERENCES_DIR + dir + "default_preferences.json", - JSON.stringify(prefs) - ); -} - -function getDefaultPreferences(dir) { - const str = fs - .readFileSync(DEFAULT_PREFERENCES_DIR + dir + "default_preferences.json") - .toString(); - return JSON.parse(str); + return prefs; } function getDefaultFtl() { @@ -1306,9 +1298,6 @@ gulp.task( const defines = { ...DEFINES, MOZCENTRAL: true }; return buildDefaultPreferences(defines, "mozcentral/"); }, - async function prefsMozcentral() { - await parseDefaultPreferences("mozcentral/"); - }, function createMozcentral() { console.log(); console.log("### Building mozilla-central extension"); @@ -1424,9 +1413,6 @@ gulp.task( createTemporaryScriptingBundle(defines), ]); }, - async function prefsChromium() { - await parseDefaultPreferences("chromium/"); - }, function createChromium() { console.log(); console.log("### Building Chromium extension"); From 5d020763139c7dad45d5498196e14c2272247562 Mon Sep 17 00:00:00 2001 From: Jonas Jenwald Date: Fri, 30 Jan 2026 09:32:53 +0100 Subject: [PATCH 4/5] Add tests (and CI) to ensure that preference generation works correctly for all relevant build-targets Given that previous patches reduced that number of build-targets running this code, ensure that it's still tested sufficiently. --- .github/workflows/prefs_tests.yml | 31 +++++++ gulpfile.mjs | 140 +++++++++++++++++------------- web/app_options.js | 2 +- 3 files changed, 111 insertions(+), 62 deletions(-) create mode 100644 .github/workflows/prefs_tests.yml diff --git a/.github/workflows/prefs_tests.yml b/.github/workflows/prefs_tests.yml new file mode 100644 index 000000000..b439dbf5c --- /dev/null +++ b/.github/workflows/prefs_tests.yml @@ -0,0 +1,31 @@ +name: Prefs tests +on: [push, pull_request] +permissions: + contents: read + +jobs: + test: + name: Test + runs-on: ubuntu-latest + + strategy: + fail-fast: false + matrix: + node-version: [lts/*] + + steps: + - name: Checkout repository + uses: actions/checkout@v6 + with: + fetch-depth: 0 + + - name: Use Node.js ${{ matrix.node-version }} + uses: actions/setup-node@v6 + with: + node-version: ${{ matrix.node-version }} + + - name: Install dependencies + run: npm ci + + - name: Run prefs tests + run: npx gulp prefstest diff --git a/gulpfile.mjs b/gulpfile.mjs index 858633d85..7b036c530 100644 --- a/gulpfile.mjs +++ b/gulpfile.mjs @@ -68,6 +68,7 @@ const GH_PAGES_DIR = BUILD_DIR + "gh-pages/"; const DIST_DIR = BUILD_DIR + "dist/"; const TYPES_DIR = BUILD_DIR + "types/"; const TMP_DIR = BUILD_DIR + "tmp/"; +const PREFSTEST_DIR = BUILD_DIR + "prefstest/"; const TYPESTEST_DIR = BUILD_DIR + "typestest/"; const COMMON_WEB_FILES = [ "web/images/*.{png,svg,gif}", @@ -677,8 +678,7 @@ function getTempFile(prefix, suffix) { function runTests(testsName, { bot = false, xfaOnly = false } = {}) { return new Promise((resolve, reject) => { - console.log(); - console.log("### Running " + testsName + " tests"); + console.log("\n### Running " + testsName + " tests"); const PDF_TEST = process.env.PDF_TEST || "test_manifest.json"; let forceNoChrome = false; @@ -763,8 +763,7 @@ function collectArgs(options, args) { } function makeRef(done, bot) { - console.log(); - console.log("### Creating reference images"); + console.log("\n### Creating reference images"); let forceNoChrome = false; const args = ["test.mjs", "--masterMode"]; @@ -815,8 +814,7 @@ gulp.task("default", function (done) { }); function createBuildNumber(done) { - console.log(); - console.log("### Getting extension build number"); + console.log("\n### Getting extension build number"); exec( "git log --format=oneline " + config.baseVersion + "..", @@ -861,8 +859,7 @@ function createBuildNumber(done) { } function buildDefaultPreferences(defines, dir) { - console.log(); - console.log("### Building default preferences"); + console.log(`\n### Building default preferences (${dir})`); const bundleDefines = { ...defines, @@ -889,8 +886,7 @@ function buildDefaultPreferences(defines, dir) { } function getDefaultPreferences(dir) { - console.log(); - console.log("### Parsing default preferences"); + console.log(`\n### Parsing default preferences (${dir})`); const require = process .getBuiltinModule("module") @@ -905,7 +901,7 @@ function getDefaultPreferences(dir) { /* defaultOnly = */ true ); if (Object.keys(prefs).length === 0) { - throw new Error("No default preferences found."); + throw new Error(`No default preferences found in "${dir}".`); } return prefs; } @@ -928,8 +924,7 @@ function getDefaultFtl() { gulp.task("locale", function () { const VIEWER_LOCALE_OUTPUT = "web/locale/"; - console.log(); - console.log("### Building localization files"); + console.log("\n### Building localization files"); fs.rmSync(VIEWER_LOCALE_OUTPUT, { recursive: true, force: true }); fs.mkdirSync(VIEWER_LOCALE_OUTPUT, { recursive: true }); @@ -977,8 +972,7 @@ gulp.task("cmaps", async function () { const CMAP_INPUT = "external/cmaps"; const VIEWER_CMAP_OUTPUT = "external/bcmaps"; - console.log(); - console.log("### Building cmaps"); + console.log("\n### Building cmaps"); // Testing a file that usually present. if (!checkFile(CMAP_INPUT + "/UniJIS-UCS2-H")) { @@ -1086,8 +1080,7 @@ gulp.task( return createTemporaryScriptingBundle(defines); }, function createGeneric() { - console.log(); - console.log("### Creating generic viewer"); + console.log("\n### Creating generic viewer"); const defines = { ...DEFINES, GENERIC: true }; return buildGeneric(defines, GENERIC_DIR); @@ -1107,8 +1100,7 @@ gulp.task( return createTemporaryScriptingBundle(defines); }, function createGenericLegacy() { - console.log(); - console.log("### Creating generic (legacy) viewer"); + console.log("\n### Creating generic (legacy) viewer"); const defines = { ...DEFINES, GENERIC: true, SKIP_BABEL: false }; return buildGeneric(defines, GENERIC_LEGACY_DIR); @@ -1143,8 +1135,7 @@ function buildComponents(defines, dir) { gulp.task( "components", gulp.series(createBuildNumber, function createComponents() { - console.log(); - console.log("### Creating generic components"); + console.log("\n### Creating generic components"); const defines = { ...DEFINES, COMPONENTS: true, GENERIC: true }; return buildComponents(defines, COMPONENTS_DIR); @@ -1154,8 +1145,7 @@ gulp.task( gulp.task( "components-legacy", gulp.series(createBuildNumber, function createComponentsLegacy() { - console.log(); - console.log("### Creating generic (legacy) components"); + console.log("\n### Creating generic (legacy) components"); const defines = { ...DEFINES, COMPONENTS: true, @@ -1170,8 +1160,7 @@ gulp.task( gulp.task( "image_decoders", gulp.series(createBuildNumber, function createImageDecoders() { - console.log(); - console.log("### Creating image decoders"); + console.log("\n### Creating image decoders"); const defines = { ...DEFINES, GENERIC: true, IMAGE_DECODERS: true }; return createImageDecodersBundle(defines).pipe( @@ -1183,8 +1172,7 @@ gulp.task( gulp.task( "image_decoders-legacy", gulp.series(createBuildNumber, function createImageDecodersLegacy() { - console.log(); - console.log("### Creating (legacy) image decoders"); + console.log("\n### Creating (legacy) image decoders"); const defines = { ...DEFINES, GENERIC: true, @@ -1221,8 +1209,7 @@ gulp.task( return createTemporaryScriptingBundle(defines); }, function createMinified() { - console.log(); - console.log("### Creating minified viewer"); + console.log("\n### Creating minified viewer"); const defines = { ...DEFINES, MINIFIED: true, GENERIC: true }; return buildMinified(defines, MINIFIED_DIR); @@ -1245,8 +1232,7 @@ gulp.task( return createTemporaryScriptingBundle(defines); }, function createMinifiedLegacy() { - console.log(); - console.log("### Creating minified (legacy) viewer"); + console.log("\n### Creating minified (legacy) viewer"); const defines = { ...DEFINES, MINIFIED: true, @@ -1260,6 +1246,8 @@ gulp.task( ); function createDefaultPrefsFile() { + console.log("\n### Building mozilla-central preferences file"); + const defaultFileName = "PdfJsDefaultPrefs.js", overrideFileName = "PdfJsOverridePrefs.js"; const licenseHeader = fs.readFileSync("./src/license_header.js").toString(); @@ -1299,8 +1287,7 @@ gulp.task( return buildDefaultPreferences(defines, "mozcentral/"); }, function createMozcentral() { - console.log(); - console.log("### Building mozilla-central extension"); + console.log("\n### Building mozilla-central extension"); const defines = { ...DEFINES, MOZCENTRAL: true }; const gvDefines = { ...defines, GECKOVIEW: true }; @@ -1392,6 +1379,8 @@ gulp.task( ); function createChromiumPrefsSchema() { + console.log("\n### Building Chromium preferences file"); + const prefs = getDefaultPreferences("chromium/"); const chromiumPrefs = buildPrefsSchema(prefs); @@ -1414,8 +1403,7 @@ gulp.task( ]); }, function createChromium() { - console.log(); - console.log("### Building Chromium extension"); + console.log("\n### Building Chromium extension"); const defines = { ...DEFINES, CHROME: true, SKIP_BABEL: false }; const CHROME_BUILD_DIR = BUILD_DIR + "/chromium/", @@ -1502,8 +1490,7 @@ gulp.task( ); gulp.task("jsdoc", function (done) { - console.log(); - console.log("### Generating documentation (JSDoc)"); + console.log("\n### Generating documentation (JSDoc)"); fs.rmSync(JSDOC_BUILD_DIR, { recursive: true, force: true }); fs.mkdirSync(JSDOC_BUILD_DIR, { recursive: true }); @@ -1813,6 +1800,49 @@ gulp.task( ) ); +gulp.task( + "prefstest", + gulp.series( + setTestEnv, + function genericPrefs() { + const defines = { ...DEFINES, GENERIC: true }; + return buildDefaultPreferences(defines, "generic/"); + }, + function genericLegacyPrefs() { + const defines = { ...DEFINES, GENERIC: true, SKIP_BABEL: false }; + return buildDefaultPreferences(defines, "generic-legacy/"); + }, + function chromiumPrefs() { + const defines = { ...DEFINES, CHROME: true, SKIP_BABEL: false }; + return buildDefaultPreferences(defines, "chromium/"); + }, + function mozcentralPrefs() { + const defines = { ...DEFINES, MOZCENTRAL: true }; + return buildDefaultPreferences(defines, "mozcentral/"); + }, + function checkPrefs() { + console.log("\n### Checking preference generation"); + + // Check that the preferences were correctly generated, + // for all the relevant builds. + for (const dir of [ + "generic/", + "generic-legacy/", + "chromium/", + "mozcentral/", + ]) { + getDefaultPreferences(dir); + } + + // Check that all the relevant files can be generated. + return ordered([ + createChromiumPrefsSchema().pipe(gulp.dest(PREFSTEST_DIR)), + createDefaultPrefsFile().pipe(gulp.dest(PREFSTEST_DIR)), + ]); + } + ) +); + gulp.task( "typestest", gulp.series( @@ -1846,8 +1876,7 @@ gulp.task( ); function createBaseline(done) { - console.log(); - console.log("### Creating baseline environment"); + console.log("\n### Creating baseline environment"); const baselineCommit = process.env.BASELINE; if (!baselineCommit) { @@ -1908,8 +1937,7 @@ gulp.task( ); gulp.task("lint", function (done) { - console.log(); - console.log("### Linting JS/CSS/JSON/SVG/HTML files"); + console.log("\n### Linting JS/CSS/JSON/SVG/HTML files"); // Ensure that we lint the Firefox specific *.jsm files too. const esLintOptions = [ @@ -1989,8 +2017,7 @@ gulp.task("lint", function (done) { gulp.task( "lint-mozcentral", gulp.series("mozcentral", function runLintMozcentral(done) { - console.log(); - console.log("### Checking mozilla-central files"); + console.log("\n### Checking mozilla-central files"); const styleLintOptions = [ "../../node_modules/stylelint/bin/stylelint.mjs", @@ -2034,8 +2061,7 @@ gulp.task( }); }, function createDevSandbox() { - console.log(); - console.log("### Building development sandbox"); + console.log("\n### Building development sandbox"); const defines = { ...DEFINES, GENERIC: true, TESTING: true }; const sandboxDir = BUILD_DIR + "dev-sandbox/"; @@ -2079,8 +2105,7 @@ gulp.task( ); }, async function createServer() { - console.log(); - console.log("### Starting local server"); + console.log("\n### Starting local server"); let port = 8888; const i = process.argv.indexOf("--port"); @@ -2101,8 +2126,7 @@ gulp.task( ); gulp.task("clean", function (done) { - console.log(); - console.log("### Cleaning up project builds"); + console.log("\n### Cleaning up project builds"); fs.rmSync(BUILD_DIR, { recursive: true, force: true }); done(); @@ -2111,8 +2135,7 @@ gulp.task("clean", function (done) { gulp.task("importl10n", async function () { const { downloadL10n } = await import("./external/importL10n/locales.mjs"); - console.log(); - console.log("### Importing translations from mozilla-central"); + console.log("\n### Importing translations from mozilla-central"); if (!fs.existsSync(L10N_DIR)) { fs.mkdirSync(L10N_DIR); @@ -2121,8 +2144,7 @@ gulp.task("importl10n", async function () { }); function ghPagesPrepare() { - console.log(); - console.log("### Creating web site"); + console.log("\n### Creating web site"); fs.rmSync(GH_PAGES_DIR, { recursive: true, force: true }); @@ -2391,8 +2413,7 @@ gulp.task( gulp.task( "mozcentralbaseline", gulp.series(createBaseline, function createMozcentralBaseline(done) { - console.log(); - console.log("### Creating mozcentral baseline environment"); + console.log("\n### Creating mozcentral baseline environment"); // Create a mozcentral build. fs.rmSync(BASELINE_DIR + BUILD_DIR, { recursive: true, force: true }); @@ -2429,8 +2450,7 @@ gulp.task( "mozcentral", "mozcentralbaseline", function createMozcentralDiff(done) { - console.log(); - console.log("### Creating mozcentral diff"); + console.log("\n### Creating mozcentral diff"); // Create the diff between the current mozcentral build and the // baseline mozcentral build, which both exist at this point. @@ -2472,14 +2492,12 @@ gulp.task( ); gulp.task("externaltest", function (done) { - console.log(); - console.log("### Running test-fixtures.js"); + console.log("\n### Running test-fixtures.js"); safeSpawnSync("node", ["external/builder/test-fixtures.mjs"], { stdio: "inherit", }); - console.log(); - console.log("### Running test-fixtures_babel.js"); + console.log("\n### Running test-fixtures_babel.js"); safeSpawnSync("node", ["external/builder/test-fixtures_babel.mjs"], { stdio: "inherit", }); diff --git a/web/app_options.js b/web/app_options.js index 4e9901086..67a32ca6c 100644 --- a/web/app_options.js +++ b/web/app_options.js @@ -582,7 +582,7 @@ if (typeof PDFJSDev === "undefined" || PDFJSDev.test("GENERIC")) { }; } -if (typeof PDFJSDev === "undefined" || PDFJSDev.test("TESTING || LIB")) { +if (typeof PDFJSDev === "undefined" || PDFJSDev.test("TESTING")) { // Ensure that the `defaultOptions` are correctly specified. for (const name in defaultOptions) { const { value, kind, type } = defaultOptions[name]; From 1370950843e1cd1c02869c79e886dba5252590c8 Mon Sep 17 00:00:00 2001 From: Jonas Jenwald Date: Fri, 30 Jan 2026 09:35:36 +0100 Subject: [PATCH 5/5] Remove unnecessary IIFEs when setting the `compatParams` This really isn't necessary, and it's just a left-over from before the code was moved into the current file. Also, spotted during rebasing, use the existing "locale" hash-parameter in integration-tests rather than adding a duplicate one for testing. --- test/integration/comment_spec.mjs | 2 +- web/app.js | 1 - web/app_options.js | 16 ++++++---------- 3 files changed, 7 insertions(+), 12 deletions(-) diff --git a/test/integration/comment_spec.mjs b/test/integration/comment_spec.mjs index cad7f144c..3074e4a3d 100644 --- a/test/integration/comment_spec.mjs +++ b/test/integration/comment_spec.mjs @@ -111,7 +111,7 @@ describe("Comment", () => { ".annotationEditorLayer", "page-width", null, - { enableComment: true, localeProperties: "ar" } + { enableComment: true, locale: "ar" } ); }); diff --git a/web/app.js b/web/app.js index b482c84f0..e882ad150 100644 --- a/web/app.js +++ b/web/app.js @@ -387,7 +387,6 @@ const PDFViewerApplication = { forcePageColors: x => x === "true", pageColorsBackground: x => x, pageColorsForeground: x => x, - localeProperties: x => ({ lang: x }), sidebarViewOnLoad: x => parseInt(x), }); } diff --git a/web/app_options.js b/web/app_options.js index 67a32ca6c..5101be5e5 100644 --- a/web/app_options.js +++ b/web/app_options.js @@ -37,19 +37,15 @@ if (typeof PDFJSDev === "undefined" || PDFJSDev.test("GENERIC")) { // Limit canvas size to 5 mega-pixels on mobile. // Support: Android, iOS - (function () { - if (isIOS || isAndroid) { - compatParams.set("maxCanvasPixels", 5242880); - } - })(); + if (isIOS || isAndroid) { + compatParams.set("maxCanvasPixels", 5242880); + } // Don't use system fonts on Android (issue 18210). // Support: Android - (function () { - if (isAndroid) { - compatParams.set("useSystemFonts", false); - } - })(); + if (isAndroid) { + compatParams.set("useSystemFonts", false); + } } const OptionKind = {