[api-major] Remove the PDFJS.disableWorker option

Despite this patch removing the `disableWorker` option itself, please note that we'll still fallback to loading the worker file(s) on the main-thread when running in environments without proper Web Worker support.

Furthermore it's still possible, even with this patch, to force the use of fake workers by manually loading the necessary file using a `<script>` tag on the main-thread.[1]
That way, the functionality of the now removed `SINGLE_FILE` build target and the resulting `build/pdf.combined.js` file can still be achieved simply by adding e.g. `<script src="build/pdf.worker.js"></script>` to the HTML (obviously with the path adjusted as needed).

Finally note that the `disableWorker` option is a performance footgun, and unfortunately many existing third-party examples actually use it without providing any sort of warning/justification.

---

[1] This approach is used in the default viewer, since certain kind of debugging may be easier if the code is running directly on the main-thread.
This commit is contained in:
Jonas Jenwald 2018-01-19 18:16:17 +01:00
parent a5aaf62754
commit 56a8c934dd
11 changed files with 64 additions and 57 deletions

View File

@ -10,9 +10,6 @@ var pdfPath = '../helloworld/helloworld.pdf';
// Setting worker path to worker bundle. // Setting worker path to worker bundle.
PDFJS.workerSrc = '../../build/browserify/pdf.worker.bundle.js'; PDFJS.workerSrc = '../../build/browserify/pdf.worker.bundle.js';
// It is also possible to disable workers via `PDFJS.disableWorker = true`,
// however that might degrade the UI performance in web browsers.
// Loading a document. // Loading a document.
var loadingTask = PDFJS.getDocument(pdfPath); var loadingTask = PDFJS.getDocument(pdfPath);
loadingTask.promise.then(function (pdfDocument) { loadingTask.promise.then(function (pdfDocument) {

View File

@ -19,13 +19,6 @@
// //
var url = './helloworld.pdf'; var url = './helloworld.pdf';
//
// Disable workers to avoid yet another cross-origin issue (workers need
// the URL of the script to be loaded, and dynamically loading a cross-origin
// script does not work).
//
// PDFJS.disableWorker = true;
// //
// The workerSrc property shall be specified. // The workerSrc property shall be specified.
// //

View File

@ -31,12 +31,6 @@
'MDAwIG4gCjAwMDAwMDAzODAgMDAwMDAgbiAKdHJhaWxlcgo8PAogIC9TaXplIDYKICAvUm9v' + 'MDAwIG4gCjAwMDAwMDAzODAgMDAwMDAgbiAKdHJhaWxlcgo8PAogIC9TaXplIDYKICAvUm9v' +
'dCAxIDAgUgo+PgpzdGFydHhyZWYKNDkyCiUlRU9G'); 'dCAxIDAgUgo+PgpzdGFydHhyZWYKNDkyCiUlRU9G');
// Disable workers to avoid yet another cross-origin issue (workers need
// the URL of the script to be loaded, and dynamically loading a cross-origin
// script does not work).
//
// PDFJS.disableWorker = true;
// //
// The workerSrc property shall be specified. // The workerSrc property shall be specified.
// //

View File

@ -28,14 +28,6 @@
// //
var url = '../../web/compressed.tracemonkey-pldi-09.pdf'; var url = '../../web/compressed.tracemonkey-pldi-09.pdf';
//
// Disable workers to avoid yet another cross-origin issue (workers need
// the URL of the script to be loaded, and dynamically loading a cross-origin
// script does not work).
//
// PDFJS.disableWorker = true;
// //
// In cases when the pdf.worker.js is located at the different folder than the // In cases when the pdf.worker.js is located at the different folder than the
// pdf.js's one, or the pdf.js is executed via eval(), the workerSrc property // pdf.js's one, or the pdf.js is executed via eval(), the workerSrc property

View File

@ -10,9 +10,6 @@ var pdfPath = '../helloworld/helloworld.pdf';
// Setting worker path to worker bundle. // Setting worker path to worker bundle.
pdfjsLib.PDFJS.workerSrc = '../../build/webpack/pdf.worker.bundle.js'; pdfjsLib.PDFJS.workerSrc = '../../build/webpack/pdf.worker.bundle.js';
// It is also possible to disable workers via `PDFJS.disableWorker = true`,
// however that might degrade the UI performance in web browsers.
// Loading a document. // Loading a document.
var loadingTask = pdfjsLib.getDocument(pdfPath); var loadingTask = pdfjsLib.getDocument(pdfPath);
loadingTask.promise.then(function (pdfDocument) { loadingTask.promise.then(function (pdfDocument) {

View File

@ -19,8 +19,6 @@ var PdfjsWorker = require('worker-loader!./build/pdf.worker.js');
if (typeof window !== 'undefined' && 'Worker' in window) { if (typeof window !== 'undefined' && 'Worker' in window) {
pdfjs.PDFJS.workerPort = new PdfjsWorker(); pdfjs.PDFJS.workerPort = new PdfjsWorker();
} else {
pdfjs.PDFJS.disableWorker = true;
} }
module.exports = pdfjs; module.exports = pdfjs;

View File

@ -1216,6 +1216,19 @@ var PDFWorker = (function PDFWorkerClosure() {
throw new Error('No PDFJS.workerSrc specified'); throw new Error('No PDFJS.workerSrc specified');
} }
function getMainThreadWorkerMessageHandler() {
if (typeof window === 'undefined') {
return null;
}
if (typeof PDFJSDev === 'undefined' || !PDFJSDev.test('PRODUCTION')) {
return (window.pdfjsNonProductionPdfWorker &&
window.pdfjsNonProductionPdfWorker.WorkerMessageHandler);
}
// PRODUCTION
return (window.pdfjsDistBuildPdfWorker &&
window.pdfjsDistBuildPdfWorker.WorkerMessageHandler);
}
let fakeWorkerFilesLoadedCapability; let fakeWorkerFilesLoadedCapability;
// Loads worker code into main thread. // Loads worker code into main thread.
@ -1225,6 +1238,13 @@ var PDFWorker = (function PDFWorkerClosure() {
return fakeWorkerFilesLoadedCapability.promise; return fakeWorkerFilesLoadedCapability.promise;
} }
fakeWorkerFilesLoadedCapability = createPromiseCapability(); fakeWorkerFilesLoadedCapability = createPromiseCapability();
let mainWorkerMessageHandler = getMainThreadWorkerMessageHandler();
if (mainWorkerMessageHandler) {
// The worker was already loaded using a `<script>` tag.
fakeWorkerFilesLoadedCapability.resolve(mainWorkerMessageHandler);
return fakeWorkerFilesLoadedCapability.promise;
}
// In the developer build load worker_loader which in turn loads all the // In the developer build load worker_loader which in turn loads all the
// other files and resolves the promise. In production only the // other files and resolves the promise. In production only the
// pdf.worker.js file is needed. // pdf.worker.js file is needed.
@ -1316,7 +1336,7 @@ var PDFWorker = (function PDFWorkerClosure() {
// Right now, the requirement is, that an Uint8Array is still an // Right now, the requirement is, that an Uint8Array is still an
// Uint8Array as it arrives on the worker. (Chrome added this with v.15.) // Uint8Array as it arrives on the worker. (Chrome added this with v.15.)
if (typeof Worker !== 'undefined' && !isWorkerDisabled && if (typeof Worker !== 'undefined' && !isWorkerDisabled &&
!getDefaultSetting('disableWorker')) { !getMainThreadWorkerMessageHandler()) {
var workerSrc = getWorkerSrc(); var workerSrc = getWorkerSrc();
try { try {
@ -1427,7 +1447,7 @@ var PDFWorker = (function PDFWorkerClosure() {
}, },
_setupFakeWorker: function PDFWorker_setupFakeWorker() { _setupFakeWorker: function PDFWorker_setupFakeWorker() {
if (!isWorkerDisabled && !getDefaultSetting('disableWorker')) { if (!isWorkerDisabled) {
warn('Setting up fake worker.'); warn('Setting up fake worker.');
isWorkerDisabled = true; isWorkerDisabled = true;
} }

View File

@ -361,8 +361,6 @@ function getDefaultSetting(id) {
return globalSettings ? globalSettings.workerPort : null; return globalSettings ? globalSettings.workerPort : null;
case 'workerSrc': case 'workerSrc':
return globalSettings ? globalSettings.workerSrc : null; return globalSettings ? globalSettings.workerSrc : null;
case 'disableWorker':
return globalSettings ? globalSettings.disableWorker : false;
case 'maxImageSize': case 'maxImageSize':
return globalSettings ? globalSettings.maxImageSize : -1; return globalSettings ? globalSettings.maxImageSize : -1;
case 'imageResourcesPath': case 'imageResourcesPath':

View File

@ -128,15 +128,6 @@ PDFJS.disableFontFace = (PDFJS.disableFontFace === undefined ?
PDFJS.imageResourcesPath = (PDFJS.imageResourcesPath === undefined ? PDFJS.imageResourcesPath = (PDFJS.imageResourcesPath === undefined ?
'' : PDFJS.imageResourcesPath); '' : PDFJS.imageResourcesPath);
/**
* Disable the web worker and run all code on the main thread. This will
* happen automatically if the browser doesn't support workers or sending
* typed arrays to workers.
* @var {boolean}
*/
PDFJS.disableWorker = (PDFJS.disableWorker === undefined ?
false : PDFJS.disableWorker);
/** /**
* Path and filename of the worker file. Required when the worker is enabled * Path and filename of the worker file. Required when the worker is enabled
* in development mode. If unspecified in the production build, the worker * in development mode. If unspecified in the production build, the worker
@ -148,8 +139,7 @@ PDFJS.disableWorker = (PDFJS.disableWorker === undefined ?
PDFJS.workerSrc = (PDFJS.workerSrc === undefined ? null : PDFJS.workerSrc); PDFJS.workerSrc = (PDFJS.workerSrc === undefined ? null : PDFJS.workerSrc);
/** /**
* Defines global port for worker process. Overrides workerSrc and * Defines global port for worker process. Overrides `workerSrc` setting.
* disableWorker setting.
*/ */
PDFJS.workerPort = (PDFJS.workerPort === undefined ? null : PDFJS.workerPort); PDFJS.workerPort = (PDFJS.workerPort === undefined ? null : PDFJS.workerPort);

View File

@ -122,16 +122,14 @@ describe('api', function() {
path: TEST_PDFS_PATH.node + basicApiFileName, path: TEST_PDFS_PATH.node + basicApiFileName,
}); });
} else { } else {
var nonBinaryRequest = PDFJS.disableWorker; let nonBinaryRequest = false;
var request = new XMLHttpRequest(); let request = new XMLHttpRequest();
request.open('GET', TEST_PDFS_PATH.dom + basicApiFileName, false); request.open('GET', TEST_PDFS_PATH.dom + basicApiFileName, false);
if (!nonBinaryRequest) { try {
try { request.responseType = 'arraybuffer';
request.responseType = 'arraybuffer'; nonBinaryRequest = request.responseType !== 'arraybuffer';
nonBinaryRequest = request.responseType !== 'arraybuffer'; } catch (e) {
} catch (e) { nonBinaryRequest = true;
nonBinaryRequest = true;
}
} }
if (nonBinaryRequest && request.overrideMimeType) { if (nonBinaryRequest && request.overrideMimeType) {
request.overrideMimeType('text/plain; charset=x-user-defined'); request.overrideMimeType('text/plain; charset=x-user-defined');

View File

@ -22,8 +22,8 @@ import {
} from './ui_utils'; } from './ui_utils';
import { import {
build, createBlob, getDocument, getFilenameFromUrl, InvalidPDFException, build, createBlob, getDocument, getFilenameFromUrl, InvalidPDFException,
MissingPDFException, OPS, PDFJS, shadow, UnexpectedResponseException, MissingPDFException, OPS, PDFJS, PDFWorker, shadow,
UNSUPPORTED_FEATURES, version UnexpectedResponseException, UNSUPPORTED_FEATURES, version
} from 'pdfjs-lib'; } from 'pdfjs-lib';
import { CursorTool, PDFCursorTools } from './pdf_cursor_tools'; import { CursorTool, PDFCursorTools } from './pdf_cursor_tools';
import { PDFRenderingQueue, RenderingStates } from './pdf_rendering_queue'; import { PDFRenderingQueue, RenderingStates } from './pdf_rendering_queue';
@ -285,8 +285,9 @@ let PDFViewerApplication = {
let hash = document.location.hash.substring(1); let hash = document.location.hash.substring(1);
let hashParams = parseQueryString(hash); let hashParams = parseQueryString(hash);
if ('disableworker' in hashParams) { if ('disableworker' in hashParams &&
PDFJS.disableWorker = (hashParams['disableworker'] === 'true'); hashParams['disableworker'] === 'true') {
waitOn.push(loadFakeWorker());
} }
if ('disablerange' in hashParams) { if ('disablerange' in hashParams) {
PDFJS.disableRange = (hashParams['disablerange'] === 'true'); PDFJS.disableRange = (hashParams['disablerange'] === 'true');
@ -1512,6 +1513,35 @@ if (typeof PDFJSDev === 'undefined' || PDFJSDev.test('GENERIC')) {
}; };
} }
function loadFakeWorker() {
return new Promise(function(resolve, reject) {
if (typeof PDFJSDev === 'undefined' || !PDFJSDev.test('PRODUCTION')) {
if (typeof SystemJS === 'object') {
SystemJS.import('pdfjs/core/worker').then((worker) => {
window.pdfjsNonProductionPdfWorker = worker;
resolve();
});
} else if (typeof require === 'function') {
window.pdfjsNonProductionPdfWorker = require('../src/core/worker.js');
resolve();
} else {
reject(new Error(
'SystemJS or CommonJS must be used to load fake worker.'));
}
} else {
let script = document.createElement('script');
script.src = PDFWorker.getWorkerSrc();
script.onload = function() {
resolve();
};
script.onerror = function() {
reject(new Error(`Cannot load fake worker at: ${script.src}`));
};
(document.head || document.documentElement).appendChild(script);
}
});
}
function loadAndEnablePDFBug(enabledTabs) { function loadAndEnablePDFBug(enabledTabs) {
return new Promise(function (resolve, reject) { return new Promise(function (resolve, reject) {
let appConfig = PDFViewerApplication.appConfig; let appConfig = PDFViewerApplication.appConfig;