Merge pull request #6571 from yurydelendik/worker
[api-minor] Allows a worker to handle multiple documents.
This commit is contained in:
commit
c2dfe9e9a9
@ -1,17 +1,6 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
var sheet = {
|
||||
cssRules: [],
|
||||
insertRule: function(rule) {
|
||||
this.cssRules.push(rule);
|
||||
},
|
||||
};
|
||||
|
||||
var style = {
|
||||
sheet: sheet,
|
||||
};
|
||||
|
||||
function xmlEncode(s){
|
||||
var i = 0, ch;
|
||||
s = String(s);
|
||||
@ -75,6 +64,15 @@ function DOMElement(name) {
|
||||
this.childNodes = [];
|
||||
this.attributes = {};
|
||||
this.textContent = '';
|
||||
|
||||
if (name === 'style') {
|
||||
this.sheet = {
|
||||
cssRules: [],
|
||||
insertRule: function (rule) {
|
||||
this.cssRules.push(rule);
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
DOMElement.prototype = {
|
||||
@ -125,14 +123,23 @@ DOMElement.prototype = {
|
||||
global.document = {
|
||||
childNodes : [],
|
||||
|
||||
getElementById: function (id) {
|
||||
if (id === 'PDFJS_FONT_STYLE_TAG') {
|
||||
return style;
|
||||
}
|
||||
get documentElement() {
|
||||
return this;
|
||||
},
|
||||
|
||||
createElementNS: function (NS, element) {
|
||||
var elObject = new DOMElement(element);
|
||||
return elObject;
|
||||
},
|
||||
|
||||
createElement: function (element) {
|
||||
return this.createElementNS('', element);
|
||||
},
|
||||
|
||||
getElementsByTagName: function (element) {
|
||||
if (element === 'head') {
|
||||
return [this.head || (this.head = new DOMElement('head'))];
|
||||
}
|
||||
return [];
|
||||
}
|
||||
};
|
||||
|
@ -529,7 +529,7 @@ var PartialEvaluator = (function PartialEvaluatorClosure() {
|
||||
|
||||
// Keep track of each font we translated so the caller can
|
||||
// load them asynchronously before calling display on a page.
|
||||
font.loadedName = 'g_font_' + (fontRefIsDict ?
|
||||
font.loadedName = 'g_' + this.pdfManager.docId + '_f' + (fontRefIsDict ?
|
||||
fontName.replace(/\W/g, '') : fontID);
|
||||
|
||||
font.translated = fontCapability.promise;
|
||||
|
@ -24,6 +24,10 @@ var BasePdfManager = (function BasePdfManagerClosure() {
|
||||
}
|
||||
|
||||
BasePdfManager.prototype = {
|
||||
get docId() {
|
||||
return this._docId;
|
||||
},
|
||||
|
||||
onLoadedStream: function BasePdfManager_onLoadedStream() {
|
||||
throw new NotImplementedException();
|
||||
},
|
||||
@ -85,7 +89,8 @@ var BasePdfManager = (function BasePdfManagerClosure() {
|
||||
})();
|
||||
|
||||
var LocalPdfManager = (function LocalPdfManagerClosure() {
|
||||
function LocalPdfManager(data, password) {
|
||||
function LocalPdfManager(docId, data, password) {
|
||||
this._docId = docId;
|
||||
var stream = new Stream(data);
|
||||
this.pdfDocument = new PDFDocument(this, stream, password);
|
||||
this._loadedStreamCapability = createPromiseCapability();
|
||||
@ -136,8 +141,8 @@ var LocalPdfManager = (function LocalPdfManagerClosure() {
|
||||
})();
|
||||
|
||||
var NetworkPdfManager = (function NetworkPdfManagerClosure() {
|
||||
function NetworkPdfManager(args, msgHandler) {
|
||||
|
||||
function NetworkPdfManager(docId, args, msgHandler) {
|
||||
this._docId = docId;
|
||||
this.msgHandler = msgHandler;
|
||||
|
||||
var params = {
|
||||
|
@ -51,12 +51,51 @@ var WorkerTask = (function WorkerTaskClosure() {
|
||||
})();
|
||||
|
||||
var WorkerMessageHandler = PDFJS.WorkerMessageHandler = {
|
||||
setup: function wphSetup(handler) {
|
||||
setup: function wphSetup(handler, port) {
|
||||
handler.on('test', function wphSetupTest(data) {
|
||||
// check if Uint8Array can be sent to worker
|
||||
if (!(data instanceof Uint8Array)) {
|
||||
handler.send('test', 'main', false);
|
||||
return;
|
||||
}
|
||||
// making sure postMessage transfers are working
|
||||
var supportTransfers = data[0] === 255;
|
||||
handler.postMessageTransfers = supportTransfers;
|
||||
// check if the response property is supported by xhr
|
||||
var xhr = new XMLHttpRequest();
|
||||
var responseExists = 'response' in xhr;
|
||||
// check if the property is actually implemented
|
||||
try {
|
||||
var dummy = xhr.responseType;
|
||||
} catch (e) {
|
||||
responseExists = false;
|
||||
}
|
||||
if (!responseExists) {
|
||||
handler.send('test', false);
|
||||
return;
|
||||
}
|
||||
handler.send('test', {
|
||||
supportTypedArray: true,
|
||||
supportTransfers: supportTransfers
|
||||
});
|
||||
});
|
||||
|
||||
handler.on('GetDocRequest', function wphSetupDoc(data) {
|
||||
return WorkerMessageHandler.createDocumentHandler(data, port);
|
||||
});
|
||||
},
|
||||
createDocumentHandler: function wphCreateDocumentHandler(data, port) {
|
||||
// This context is actually holds references on pdfManager and handler,
|
||||
// until the latter is destroyed.
|
||||
var pdfManager;
|
||||
var terminated = false;
|
||||
var cancelXHRs = null;
|
||||
var WorkerTasks = [];
|
||||
|
||||
var docId = data.docId;
|
||||
var workerHandlerName = data.docId + '_worker';
|
||||
var handler = new MessageHandler(workerHandlerName, docId, port);
|
||||
|
||||
function ensureNotTerminated() {
|
||||
if (terminated) {
|
||||
throw new Error('Worker was terminated');
|
||||
@ -114,7 +153,7 @@ var WorkerMessageHandler = PDFJS.WorkerMessageHandler = {
|
||||
var disableRange = data.disableRange;
|
||||
if (source.data) {
|
||||
try {
|
||||
pdfManager = new LocalPdfManager(source.data, source.password);
|
||||
pdfManager = new LocalPdfManager(docId, source.data, source.password);
|
||||
pdfManagerCapability.resolve(pdfManager);
|
||||
} catch (ex) {
|
||||
pdfManagerCapability.reject(ex);
|
||||
@ -122,7 +161,7 @@ var WorkerMessageHandler = PDFJS.WorkerMessageHandler = {
|
||||
return pdfManagerCapability.promise;
|
||||
} else if (source.chunkedViewerLoading) {
|
||||
try {
|
||||
pdfManager = new NetworkPdfManager(source, handler);
|
||||
pdfManager = new NetworkPdfManager(docId, source, handler);
|
||||
pdfManagerCapability.resolve(pdfManager);
|
||||
} catch (ex) {
|
||||
pdfManagerCapability.reject(ex);
|
||||
@ -179,7 +218,7 @@ var WorkerMessageHandler = PDFJS.WorkerMessageHandler = {
|
||||
}
|
||||
|
||||
try {
|
||||
pdfManager = new NetworkPdfManager(source, handler);
|
||||
pdfManager = new NetworkPdfManager(docId, source, handler);
|
||||
pdfManagerCapability.resolve(pdfManager);
|
||||
} catch (ex) {
|
||||
pdfManagerCapability.reject(ex);
|
||||
@ -224,7 +263,7 @@ var WorkerMessageHandler = PDFJS.WorkerMessageHandler = {
|
||||
|
||||
// the data is array, instantiating directly from it
|
||||
try {
|
||||
pdfManager = new LocalPdfManager(pdfFile, source.password);
|
||||
pdfManager = new LocalPdfManager(docId, pdfFile, source.password);
|
||||
pdfManagerCapability.resolve(pdfManager);
|
||||
} catch (ex) {
|
||||
pdfManagerCapability.reject(ex);
|
||||
@ -262,35 +301,7 @@ var WorkerMessageHandler = PDFJS.WorkerMessageHandler = {
|
||||
return pdfManagerCapability.promise;
|
||||
}
|
||||
|
||||
handler.on('test', function wphSetupTest(data) {
|
||||
// check if Uint8Array can be sent to worker
|
||||
if (!(data instanceof Uint8Array)) {
|
||||
handler.send('test', false);
|
||||
return;
|
||||
}
|
||||
// making sure postMessage transfers are working
|
||||
var supportTransfers = data[0] === 255;
|
||||
handler.postMessageTransfers = supportTransfers;
|
||||
// check if the response property is supported by xhr
|
||||
var xhr = new XMLHttpRequest();
|
||||
var responseExists = 'response' in xhr;
|
||||
// check if the property is actually implemented
|
||||
try {
|
||||
var dummy = xhr.responseType;
|
||||
} catch (e) {
|
||||
responseExists = false;
|
||||
}
|
||||
if (!responseExists) {
|
||||
handler.send('test', false);
|
||||
return;
|
||||
}
|
||||
handler.send('test', {
|
||||
supportTypedArray: true,
|
||||
supportTransfers: supportTransfers
|
||||
});
|
||||
});
|
||||
|
||||
handler.on('GetDocRequest', function wphSetupDoc(data) {
|
||||
var setupDoc = function(data) {
|
||||
var onSuccess = function(doc) {
|
||||
ensureNotTerminated();
|
||||
handler.send('GetDoc', { pdfInfo: doc });
|
||||
@ -366,7 +377,7 @@ var WorkerMessageHandler = PDFJS.WorkerMessageHandler = {
|
||||
});
|
||||
}, onFailure);
|
||||
}, onFailure);
|
||||
});
|
||||
};
|
||||
|
||||
handler.on('GetPage', function wphSetupGetPage(data) {
|
||||
return pdfManager.getPage(data.pageIndex).then(function(page) {
|
||||
@ -546,8 +557,16 @@ var WorkerMessageHandler = PDFJS.WorkerMessageHandler = {
|
||||
task.terminate();
|
||||
});
|
||||
|
||||
return Promise.all(waitOn).then(function () {});
|
||||
return Promise.all(waitOn).then(function () {
|
||||
// Notice that even if we destroying handler, resolved response promise
|
||||
// must be sent back.
|
||||
handler.destroy();
|
||||
handler = null;
|
||||
});
|
||||
});
|
||||
|
||||
setupDoc(data);
|
||||
return workerHandlerName;
|
||||
}
|
||||
};
|
||||
|
||||
@ -557,6 +576,7 @@ var workerConsole = {
|
||||
log: function log() {
|
||||
var args = Array.prototype.slice.call(arguments);
|
||||
globalScope.postMessage({
|
||||
targetName: 'main',
|
||||
action: 'console_log',
|
||||
data: args
|
||||
});
|
||||
@ -565,6 +585,7 @@ var workerConsole = {
|
||||
error: function error() {
|
||||
var args = Array.prototype.slice.call(arguments);
|
||||
globalScope.postMessage({
|
||||
targetName: 'main',
|
||||
action: 'console_error',
|
||||
data: args
|
||||
});
|
||||
@ -594,11 +615,12 @@ if (typeof window === 'undefined') {
|
||||
// Listen for unsupported features so we can pass them on to the main thread.
|
||||
PDFJS.UnsupportedManager.listen(function (msg) {
|
||||
globalScope.postMessage({
|
||||
targetName: 'main',
|
||||
action: '_unsupported_feature',
|
||||
data: msg
|
||||
});
|
||||
});
|
||||
|
||||
var handler = new MessageHandler('worker_processor', this);
|
||||
WorkerMessageHandler.setup(handler);
|
||||
var handler = new MessageHandler('worker', 'main', this);
|
||||
WorkerMessageHandler.setup(handler, this);
|
||||
}
|
||||
|
@ -17,7 +17,7 @@
|
||||
Promise, PasswordResponses, PasswordException, InvalidPDFException,
|
||||
MissingPDFException, UnknownErrorException, FontFaceObject,
|
||||
loadJpegStream, createScratchCanvas, CanvasGraphics, stringToBytes,
|
||||
UnexpectedResponseException, deprecated */
|
||||
UnexpectedResponseException, deprecated, UnsupportedManager */
|
||||
|
||||
'use strict';
|
||||
|
||||
@ -225,6 +225,8 @@ PDFJS.isEvalSupported = (PDFJS.isEvalSupported === undefined ?
|
||||
* @property {number} rangeChunkSize - Optional parameter to specify
|
||||
* maximum number of bytes fetched per range request. The default value is
|
||||
* 2^16 = 65536.
|
||||
* @property {PDFWorker} worker - The worker that will be used for the loading
|
||||
* and parsing of the PDF data.
|
||||
*/
|
||||
|
||||
/**
|
||||
@ -287,7 +289,6 @@ PDFJS.getDocument = function getDocument(src,
|
||||
task.onPassword = passwordCallback || null;
|
||||
task.onProgress = progressCallback || null;
|
||||
|
||||
var workerInitializedCapability, transport;
|
||||
var source;
|
||||
if (typeof src === 'string') {
|
||||
source = { url: src };
|
||||
@ -308,12 +309,18 @@ PDFJS.getDocument = function getDocument(src,
|
||||
}
|
||||
|
||||
var params = {};
|
||||
var rangeTransport = null;
|
||||
var worker = null;
|
||||
for (var key in source) {
|
||||
if (key === 'url' && typeof window !== 'undefined') {
|
||||
// The full path is required in the 'url' field.
|
||||
params[key] = combineUrl(window.location.href, source[key]);
|
||||
continue;
|
||||
} else if (key === 'range') {
|
||||
rangeTransport = source[key];
|
||||
continue;
|
||||
} else if (key === 'worker') {
|
||||
worker = source[key];
|
||||
continue;
|
||||
} else if (key === 'data' && !(source[key] instanceof Uint8Array)) {
|
||||
// Converting string or array-like data to Uint8Array.
|
||||
@ -334,27 +341,97 @@ PDFJS.getDocument = function getDocument(src,
|
||||
params[key] = source[key];
|
||||
}
|
||||
|
||||
params.rangeChunkSize = source.rangeChunkSize || DEFAULT_RANGE_CHUNK_SIZE;
|
||||
params.rangeChunkSize = params.rangeChunkSize || DEFAULT_RANGE_CHUNK_SIZE;
|
||||
|
||||
workerInitializedCapability = createPromiseCapability();
|
||||
transport = new WorkerTransport(workerInitializedCapability, source.range);
|
||||
workerInitializedCapability.promise.then(function transportInitialized() {
|
||||
transport.fetchDocument(task, params);
|
||||
});
|
||||
task._transport = transport;
|
||||
if (!worker) {
|
||||
// Worker was not provided -- creating and owning our own.
|
||||
worker = new PDFWorker();
|
||||
task._worker = worker;
|
||||
}
|
||||
var docId = task.docId;
|
||||
worker.promise.then(function () {
|
||||
if (task.destroyed) {
|
||||
throw new Error('Loading aborted');
|
||||
}
|
||||
return _fetchDocument(worker, params, rangeTransport, docId).then(
|
||||
function (workerId) {
|
||||
if (task.destroyed) {
|
||||
throw new Error('Loading aborted');
|
||||
}
|
||||
var messageHandler = new MessageHandler(docId, workerId, worker.port);
|
||||
var transport = new WorkerTransport(messageHandler, task, rangeTransport);
|
||||
task._transport = transport;
|
||||
});
|
||||
}, task._capability.reject);
|
||||
|
||||
return task;
|
||||
};
|
||||
|
||||
/**
|
||||
* Starts fetching of specified PDF document/data.
|
||||
* @param {PDFWorker} worker
|
||||
* @param {Object} source
|
||||
* @param {PDFDataRangeTransport} pdfDataRangeTransport
|
||||
* @param {string} docId Unique document id, used as MessageHandler id.
|
||||
* @returns {Promise} The promise, which is resolved when worker id of
|
||||
* MessageHandler is known.
|
||||
* @private
|
||||
*/
|
||||
function _fetchDocument(worker, source, pdfDataRangeTransport, docId) {
|
||||
if (worker.destroyed) {
|
||||
return Promise.reject(new Error('Worker was destroyed'));
|
||||
}
|
||||
|
||||
source.disableAutoFetch = PDFJS.disableAutoFetch;
|
||||
source.disableStream = PDFJS.disableStream;
|
||||
source.chunkedViewerLoading = !!pdfDataRangeTransport;
|
||||
if (pdfDataRangeTransport) {
|
||||
source.length = pdfDataRangeTransport.length;
|
||||
source.initialData = pdfDataRangeTransport.initialData;
|
||||
}
|
||||
return worker.messageHandler.sendWithPromise('GetDocRequest', {
|
||||
docId: docId,
|
||||
source: source,
|
||||
disableRange: PDFJS.disableRange,
|
||||
maxImageSize: PDFJS.maxImageSize,
|
||||
cMapUrl: PDFJS.cMapUrl,
|
||||
cMapPacked: PDFJS.cMapPacked,
|
||||
disableFontFace: PDFJS.disableFontFace,
|
||||
disableCreateObjectURL: PDFJS.disableCreateObjectURL,
|
||||
verbosity: PDFJS.verbosity
|
||||
}).then(function (workerId) {
|
||||
if (worker.destroyed) {
|
||||
throw new Error('Worker was destroyed');
|
||||
}
|
||||
return workerId;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* PDF document loading operation.
|
||||
* @class
|
||||
* @alias PDFDocumentLoadingTask
|
||||
*/
|
||||
var PDFDocumentLoadingTask = (function PDFDocumentLoadingTaskClosure() {
|
||||
var nextDocumentId = 0;
|
||||
|
||||
/** @constructs PDFDocumentLoadingTask */
|
||||
function PDFDocumentLoadingTask() {
|
||||
this._capability = createPromiseCapability();
|
||||
this._transport = null;
|
||||
this._worker = null;
|
||||
|
||||
/**
|
||||
* Unique document loading task id -- used in MessageHandlers.
|
||||
* @type {string}
|
||||
*/
|
||||
this.docId = 'd' + (nextDocumentId++);
|
||||
|
||||
/**
|
||||
* Shows if loading task is destroyed.
|
||||
* @type {boolean}
|
||||
*/
|
||||
this.destroyed = false;
|
||||
|
||||
/**
|
||||
* Callback to request a password if wrong or no password was provided.
|
||||
@ -386,7 +463,17 @@ var PDFDocumentLoadingTask = (function PDFDocumentLoadingTaskClosure() {
|
||||
* is completed.
|
||||
*/
|
||||
destroy: function () {
|
||||
return this._transport.destroy();
|
||||
this.destroyed = true;
|
||||
|
||||
var transportDestroyed = !this._transport ? Promise.resolve() :
|
||||
this._transport.destroy();
|
||||
return transportDestroyed.then(function () {
|
||||
this._transport = null;
|
||||
if (this._worker) {
|
||||
this._worker.destroy();
|
||||
this._worker = null;
|
||||
}
|
||||
}.bind(this));
|
||||
},
|
||||
|
||||
/**
|
||||
@ -615,7 +702,7 @@ var PDFDocumentProxy = (function PDFDocumentProxyClosure() {
|
||||
* Destroys current document instance and terminates worker.
|
||||
*/
|
||||
destroy: function PDFDocumentProxy_destroy() {
|
||||
return this.transport.destroy();
|
||||
return this.loadingTask.destroy();
|
||||
}
|
||||
};
|
||||
return PDFDocumentProxy;
|
||||
@ -1011,17 +1098,212 @@ var PDFPageProxy = (function PDFPageProxyClosure() {
|
||||
return PDFPageProxy;
|
||||
})();
|
||||
|
||||
/**
|
||||
* PDF.js web worker abstraction, it controls instantiation of PDF documents and
|
||||
* WorkerTransport for them. If creation of a web worker is not possible,
|
||||
* a "fake" worker will be used instead.
|
||||
* @class
|
||||
*/
|
||||
var PDFWorker = (function PDFWorkerClosure() {
|
||||
var nextFakeWorkerId = 0;
|
||||
|
||||
// Loads worker code into main thread.
|
||||
function setupFakeWorkerGlobal() {
|
||||
if (!PDFJS.fakeWorkerFilesLoadedCapability) {
|
||||
PDFJS.fakeWorkerFilesLoadedCapability = createPromiseCapability();
|
||||
// In the developer build load worker_loader which in turn loads all the
|
||||
// other files and resolves the promise. In production only the
|
||||
// pdf.worker.js file is needed.
|
||||
//#if !PRODUCTION
|
||||
Util.loadScript(PDFJS.workerSrc);
|
||||
//#endif
|
||||
//#if PRODUCTION && SINGLE_FILE
|
||||
// PDFJS.fakeWorkerFilesLoadedCapability.resolve();
|
||||
//#endif
|
||||
//#if PRODUCTION && !SINGLE_FILE
|
||||
// Util.loadScript(PDFJS.workerSrc, function() {
|
||||
// PDFJS.fakeWorkerFilesLoadedCapability.resolve();
|
||||
// });
|
||||
//#endif
|
||||
}
|
||||
return PDFJS.fakeWorkerFilesLoadedCapability.promise;
|
||||
}
|
||||
|
||||
function PDFWorker(name) {
|
||||
this.name = name;
|
||||
this.destroyed = false;
|
||||
|
||||
this._readyCapability = createPromiseCapability();
|
||||
this._port = null;
|
||||
this._webWorker = null;
|
||||
this._messageHandler = null;
|
||||
this._initialize();
|
||||
}
|
||||
|
||||
PDFWorker.prototype = /** @lends PDFWorker.prototype */ {
|
||||
get promise() {
|
||||
return this._readyCapability.promise;
|
||||
},
|
||||
|
||||
get port() {
|
||||
return this._port;
|
||||
},
|
||||
|
||||
get messageHandler() {
|
||||
return this._messageHandler;
|
||||
},
|
||||
|
||||
_initialize: function PDFWorker_initialize() {
|
||||
// If worker support isn't disabled explicit and the browser has worker
|
||||
// support, create a new web worker and test if it/the browser fullfills
|
||||
// all requirements to run parts of pdf.js in a web worker.
|
||||
// Right now, the requirement is, that an Uint8Array is still an
|
||||
// Uint8Array as it arrives on the worker. (Chrome added this with v.15.)
|
||||
//#if !SINGLE_FILE
|
||||
if (!globalScope.PDFJS.disableWorker && typeof Worker !== 'undefined') {
|
||||
var workerSrc = PDFJS.workerSrc;
|
||||
if (!workerSrc) {
|
||||
error('No PDFJS.workerSrc specified');
|
||||
}
|
||||
|
||||
try {
|
||||
// Some versions of FF can't create a worker on localhost, see:
|
||||
// https://bugzilla.mozilla.org/show_bug.cgi?id=683280
|
||||
var worker = new Worker(workerSrc);
|
||||
var messageHandler = new MessageHandler('main', 'worker', worker);
|
||||
|
||||
messageHandler.on('test', function PDFWorker_test(data) {
|
||||
if (this.destroyed) {
|
||||
this._readyCapability.reject(new Error('Worker was destroyed'));
|
||||
messageHandler.destroy();
|
||||
worker.terminate();
|
||||
return; // worker was destroyed
|
||||
}
|
||||
var supportTypedArray = data && data.supportTypedArray;
|
||||
if (supportTypedArray) {
|
||||
this._messageHandler = messageHandler;
|
||||
this._port = worker;
|
||||
this._webWorker = worker;
|
||||
if (!data.supportTransfers) {
|
||||
PDFJS.postMessageTransfers = false;
|
||||
}
|
||||
this._readyCapability.resolve();
|
||||
} else {
|
||||
this._setupFakeWorker();
|
||||
messageHandler.destroy();
|
||||
worker.terminate();
|
||||
}
|
||||
}.bind(this));
|
||||
|
||||
messageHandler.on('console_log', function (data) {
|
||||
console.log.apply(console, data);
|
||||
});
|
||||
messageHandler.on('console_error', function (data) {
|
||||
console.error.apply(console, data);
|
||||
});
|
||||
messageHandler.on('_unsupported_feature', function (data) {
|
||||
UnsupportedManager.notify(data);
|
||||
});
|
||||
|
||||
var testObj = new Uint8Array([PDFJS.postMessageTransfers ? 255 : 0]);
|
||||
// Some versions of Opera throw a DATA_CLONE_ERR on serializing the
|
||||
// typed array. Also, checking if we can use transfers.
|
||||
try {
|
||||
messageHandler.send('test', testObj, [testObj.buffer]);
|
||||
} catch (ex) {
|
||||
info('Cannot use postMessage transfers');
|
||||
testObj[0] = 0;
|
||||
messageHandler.send('test', testObj);
|
||||
}
|
||||
return;
|
||||
} catch (e) {
|
||||
info('The worker has been disabled.');
|
||||
}
|
||||
}
|
||||
//#endif
|
||||
// Either workers are disabled, not supported or have thrown an exception.
|
||||
// Thus, we fallback to a faked worker.
|
||||
this._setupFakeWorker();
|
||||
},
|
||||
|
||||
_setupFakeWorker: function PDFWorker_setupFakeWorker() {
|
||||
warn('Setting up fake worker.');
|
||||
globalScope.PDFJS.disableWorker = true;
|
||||
|
||||
setupFakeWorkerGlobal().then(function () {
|
||||
if (this.destroyed) {
|
||||
this._readyCapability.reject(new Error('Worker was destroyed'));
|
||||
return;
|
||||
}
|
||||
|
||||
// If we don't use a worker, just post/sendMessage to the main thread.
|
||||
var port = {
|
||||
_listeners: [],
|
||||
postMessage: function (obj) {
|
||||
var e = {data: obj};
|
||||
this._listeners.forEach(function (listener) {
|
||||
listener.call(this, e);
|
||||
}, this);
|
||||
},
|
||||
addEventListener: function (name, listener) {
|
||||
this._listeners.push(listener);
|
||||
},
|
||||
removeEventListener: function (name, listener) {
|
||||
var i = this._listeners.indexOf(listener);
|
||||
this._listeners.splice(i, 1);
|
||||
},
|
||||
terminate: function () {}
|
||||
};
|
||||
this._port = port;
|
||||
|
||||
// All fake workers use the same port, making id unique.
|
||||
var id = 'fake' + (nextFakeWorkerId++);
|
||||
|
||||
// If the main thread is our worker, setup the handling for the
|
||||
// messages -- the main thread sends to it self.
|
||||
var workerHandler = new MessageHandler(id + '_worker', id, port);
|
||||
PDFJS.WorkerMessageHandler.setup(workerHandler, port);
|
||||
|
||||
var messageHandler = new MessageHandler(id, id + '_worker', port);
|
||||
this._messageHandler = messageHandler;
|
||||
this._readyCapability.resolve();
|
||||
}.bind(this));
|
||||
},
|
||||
|
||||
/**
|
||||
* Destroys the worker instance.
|
||||
*/
|
||||
destroy: function PDFWorker_destroy() {
|
||||
this.destroyed = true;
|
||||
if (this._webWorker) {
|
||||
// We need to terminate only web worker created resource.
|
||||
this._webWorker.terminate();
|
||||
this._webWorker = null;
|
||||
}
|
||||
this._port = null;
|
||||
if (this._messageHandler) {
|
||||
this._messageHandler.destroy();
|
||||
this._messageHandler = null;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
return PDFWorker;
|
||||
})();
|
||||
PDFJS.PDFWorker = PDFWorker;
|
||||
|
||||
/**
|
||||
* For internal use only.
|
||||
* @ignore
|
||||
*/
|
||||
var WorkerTransport = (function WorkerTransportClosure() {
|
||||
function WorkerTransport(workerInitializedCapability, pdfDataRangeTransport) {
|
||||
function WorkerTransport(messageHandler, loadingTask, pdfDataRangeTransport) {
|
||||
this.messageHandler = messageHandler;
|
||||
this.loadingTask = loadingTask;
|
||||
this.pdfDataRangeTransport = pdfDataRangeTransport;
|
||||
this.workerInitializedCapability = workerInitializedCapability;
|
||||
this.commonObjs = new PDFObjects();
|
||||
this.fontLoader = new FontLoader(loadingTask.docId);
|
||||
|
||||
this.loadingTask = null;
|
||||
this.destroyed = false;
|
||||
this.destroyCapability = null;
|
||||
|
||||
@ -1029,58 +1311,7 @@ var WorkerTransport = (function WorkerTransportClosure() {
|
||||
this.pagePromises = [];
|
||||
this.downloadInfoCapability = createPromiseCapability();
|
||||
|
||||
// If worker support isn't disabled explicit and the browser has worker
|
||||
// support, create a new web worker and test if it/the browser fullfills
|
||||
// all requirements to run parts of pdf.js in a web worker.
|
||||
// Right now, the requirement is, that an Uint8Array is still an Uint8Array
|
||||
// as it arrives on the worker. Chrome added this with version 15.
|
||||
//#if !SINGLE_FILE
|
||||
if (!globalScope.PDFJS.disableWorker && typeof Worker !== 'undefined') {
|
||||
var workerSrc = PDFJS.workerSrc;
|
||||
if (!workerSrc) {
|
||||
error('No PDFJS.workerSrc specified');
|
||||
}
|
||||
|
||||
try {
|
||||
// Some versions of FF can't create a worker on localhost, see:
|
||||
// https://bugzilla.mozilla.org/show_bug.cgi?id=683280
|
||||
var worker = new Worker(workerSrc);
|
||||
var messageHandler = new MessageHandler('main', worker);
|
||||
this.messageHandler = messageHandler;
|
||||
|
||||
messageHandler.on('test', function transportTest(data) {
|
||||
var supportTypedArray = data && data.supportTypedArray;
|
||||
if (supportTypedArray) {
|
||||
this.worker = worker;
|
||||
if (!data.supportTransfers) {
|
||||
PDFJS.postMessageTransfers = false;
|
||||
}
|
||||
this.setupMessageHandler(messageHandler);
|
||||
workerInitializedCapability.resolve();
|
||||
} else {
|
||||
this.setupFakeWorker();
|
||||
}
|
||||
}.bind(this));
|
||||
|
||||
var testObj = new Uint8Array([PDFJS.postMessageTransfers ? 255 : 0]);
|
||||
// Some versions of Opera throw a DATA_CLONE_ERR on serializing the
|
||||
// typed array. Also, checking if we can use transfers.
|
||||
try {
|
||||
messageHandler.send('test', testObj, [testObj.buffer]);
|
||||
} catch (ex) {
|
||||
info('Cannot use postMessage transfers');
|
||||
testObj[0] = 0;
|
||||
messageHandler.send('test', testObj);
|
||||
}
|
||||
return;
|
||||
} catch (e) {
|
||||
info('The worker has been disabled.');
|
||||
}
|
||||
}
|
||||
//#endif
|
||||
// Either workers are disabled, not supported or have thrown an exception.
|
||||
// Thus, we fallback to a faked worker.
|
||||
this.setupFakeWorker();
|
||||
this.setupMessageHandler();
|
||||
}
|
||||
WorkerTransport.prototype = {
|
||||
destroy: function WorkerTransport_destroy() {
|
||||
@ -1106,64 +1337,23 @@ var WorkerTransport = (function WorkerTransportClosure() {
|
||||
var terminated = this.messageHandler.sendWithPromise('Terminate', null);
|
||||
waitOn.push(terminated);
|
||||
Promise.all(waitOn).then(function () {
|
||||
FontLoader.clear();
|
||||
if (self.worker) {
|
||||
self.worker.terminate();
|
||||
}
|
||||
self.fontLoader.clear();
|
||||
if (self.pdfDataRangeTransport) {
|
||||
self.pdfDataRangeTransport.abort();
|
||||
self.pdfDataRangeTransport = null;
|
||||
}
|
||||
self.messageHandler = null;
|
||||
if (self.messageHandler) {
|
||||
self.messageHandler.destroy();
|
||||
self.messageHandler = null;
|
||||
}
|
||||
self.destroyCapability.resolve();
|
||||
}, this.destroyCapability.reject);
|
||||
return this.destroyCapability.promise;
|
||||
},
|
||||
|
||||
setupFakeWorker: function WorkerTransport_setupFakeWorker() {
|
||||
globalScope.PDFJS.disableWorker = true;
|
||||
|
||||
if (!PDFJS.fakeWorkerFilesLoadedCapability) {
|
||||
PDFJS.fakeWorkerFilesLoadedCapability = createPromiseCapability();
|
||||
// In the developer build load worker_loader which in turn loads all the
|
||||
// other files and resolves the promise. In production only the
|
||||
// pdf.worker.js file is needed.
|
||||
//#if !PRODUCTION
|
||||
Util.loadScript(PDFJS.workerSrc);
|
||||
//#endif
|
||||
//#if PRODUCTION && SINGLE_FILE
|
||||
// PDFJS.fakeWorkerFilesLoadedCapability.resolve();
|
||||
//#endif
|
||||
//#if PRODUCTION && !SINGLE_FILE
|
||||
// Util.loadScript(PDFJS.workerSrc, function() {
|
||||
// PDFJS.fakeWorkerFilesLoadedCapability.resolve();
|
||||
// });
|
||||
//#endif
|
||||
}
|
||||
PDFJS.fakeWorkerFilesLoadedCapability.promise.then(function () {
|
||||
warn('Setting up fake worker.');
|
||||
// If we don't use a worker, just post/sendMessage to the main thread.
|
||||
var fakeWorker = {
|
||||
postMessage: function WorkerTransport_postMessage(obj) {
|
||||
fakeWorker.onmessage({data: obj});
|
||||
},
|
||||
terminate: function WorkerTransport_terminate() {}
|
||||
};
|
||||
|
||||
var messageHandler = new MessageHandler('main', fakeWorker);
|
||||
this.setupMessageHandler(messageHandler);
|
||||
|
||||
// If the main thread is our worker, setup the handling for the messages
|
||||
// the main thread sends to it self.
|
||||
PDFJS.WorkerMessageHandler.setup(messageHandler);
|
||||
|
||||
this.workerInitializedCapability.resolve();
|
||||
}.bind(this));
|
||||
},
|
||||
|
||||
setupMessageHandler:
|
||||
function WorkerTransport_setupMessageHandler(messageHandler) {
|
||||
this.messageHandler = messageHandler;
|
||||
function WorkerTransport_setupMessageHandler() {
|
||||
var messageHandler = this.messageHandler;
|
||||
|
||||
function updatePassword(password) {
|
||||
messageHandler.send('UpdatePassword', password);
|
||||
@ -1303,7 +1493,7 @@ var WorkerTransport = (function WorkerTransportClosure() {
|
||||
font = new FontFaceObject(exportedData);
|
||||
}
|
||||
|
||||
FontLoader.bind(
|
||||
this.fontLoader.bind(
|
||||
[font],
|
||||
function fontReady(fontObjs) {
|
||||
this.commonObjs.resolve(id, font);
|
||||
@ -1428,34 +1618,6 @@ var WorkerTransport = (function WorkerTransportClosure() {
|
||||
}, this);
|
||||
},
|
||||
|
||||
fetchDocument: function WorkerTransport_fetchDocument(loadingTask, source) {
|
||||
if (this.destroyed) {
|
||||
loadingTask._capability.reject(new Error('Loading aborted'));
|
||||
this.destroyCapability.resolve();
|
||||
return;
|
||||
}
|
||||
|
||||
this.loadingTask = loadingTask;
|
||||
|
||||
source.disableAutoFetch = PDFJS.disableAutoFetch;
|
||||
source.disableStream = PDFJS.disableStream;
|
||||
source.chunkedViewerLoading = !!this.pdfDataRangeTransport;
|
||||
if (this.pdfDataRangeTransport) {
|
||||
source.length = this.pdfDataRangeTransport.length;
|
||||
source.initialData = this.pdfDataRangeTransport.initialData;
|
||||
}
|
||||
this.messageHandler.send('GetDocRequest', {
|
||||
source: source,
|
||||
disableRange: PDFJS.disableRange,
|
||||
maxImageSize: PDFJS.maxImageSize,
|
||||
cMapUrl: PDFJS.cMapUrl,
|
||||
cMapPacked: PDFJS.cMapPacked,
|
||||
disableFontFace: PDFJS.disableFontFace,
|
||||
disableCreateObjectURL: PDFJS.disableCreateObjectURL,
|
||||
verbosity: PDFJS.verbosity
|
||||
});
|
||||
},
|
||||
|
||||
getData: function WorkerTransport_getData() {
|
||||
return this.messageHandler.sendWithPromise('GetData', null);
|
||||
},
|
||||
@ -1539,7 +1701,7 @@ var WorkerTransport = (function WorkerTransportClosure() {
|
||||
}
|
||||
}
|
||||
this.commonObjs.clear();
|
||||
FontLoader.clear();
|
||||
this.fontLoader.clear();
|
||||
}.bind(this));
|
||||
}
|
||||
};
|
||||
|
@ -19,12 +19,24 @@
|
||||
|
||||
PDFJS.disableFontFace = false;
|
||||
|
||||
var FontLoader = {
|
||||
function FontLoader(docId) {
|
||||
this.docId = docId;
|
||||
this.styleElement = null;
|
||||
//#if !(MOZCENTRAL)
|
||||
this.nativeFontFaces = [];
|
||||
this.loadTestFontId = 0;
|
||||
this.loadingContext = {
|
||||
requests: [],
|
||||
nextRequestId: 0
|
||||
};
|
||||
//#endif
|
||||
}
|
||||
FontLoader.prototype = {
|
||||
insertRule: function fontLoaderInsertRule(rule) {
|
||||
var styleElement = document.getElementById('PDFJS_FONT_STYLE_TAG');
|
||||
var styleElement = this.styleElement;
|
||||
if (!styleElement) {
|
||||
styleElement = document.createElement('style');
|
||||
styleElement.id = 'PDFJS_FONT_STYLE_TAG';
|
||||
styleElement = this.styleElement = document.createElement('style');
|
||||
styleElement.id = 'PDFJS_FONT_STYLE_TAG_' + this.docId;
|
||||
document.documentElement.getElementsByTagName('head')[0].appendChild(
|
||||
styleElement);
|
||||
}
|
||||
@ -34,7 +46,7 @@ var FontLoader = {
|
||||
},
|
||||
|
||||
clear: function fontLoaderClear() {
|
||||
var styleElement = document.getElementById('PDFJS_FONT_STYLE_TAG');
|
||||
var styleElement = this.styleElement;
|
||||
if (styleElement) {
|
||||
styleElement.parentNode.removeChild(styleElement);
|
||||
}
|
||||
@ -75,49 +87,6 @@ var FontLoader = {
|
||||
));
|
||||
},
|
||||
|
||||
get isEvalSupported() {
|
||||
var evalSupport = false;
|
||||
if (PDFJS.isEvalSupported) {
|
||||
try {
|
||||
/* jshint evil: true */
|
||||
new Function('');
|
||||
evalSupport = true;
|
||||
} catch (e) {}
|
||||
}
|
||||
return shadow(this, 'isEvalSupported', evalSupport);
|
||||
},
|
||||
|
||||
loadTestFontId: 0,
|
||||
|
||||
loadingContext: {
|
||||
requests: [],
|
||||
nextRequestId: 0
|
||||
},
|
||||
|
||||
isSyncFontLoadingSupported: (function detectSyncFontLoadingSupport() {
|
||||
if (isWorker) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// User agent string sniffing is bad, but there is no reliable way to tell
|
||||
// if font is fully loaded and ready to be used with canvas.
|
||||
var userAgent = window.navigator.userAgent;
|
||||
var m = /Mozilla\/5.0.*?rv:(\d+).*? Gecko/.exec(userAgent);
|
||||
if (m && m[1] >= 14) {
|
||||
return true;
|
||||
}
|
||||
// TODO other browsers
|
||||
if (userAgent === 'node') {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
})(),
|
||||
|
||||
nativeFontFaces: [],
|
||||
|
||||
isFontLoadingAPISupported: (!isWorker && typeof document !== 'undefined' &&
|
||||
!!document.fonts),
|
||||
|
||||
addNativeFontFace: function fontLoader_addNativeFontFace(nativeFontFace) {
|
||||
this.nativeFontFaces.push(nativeFontFace);
|
||||
document.fonts.add(nativeFontFace);
|
||||
@ -146,27 +115,29 @@ var FontLoader = {
|
||||
}
|
||||
font.attached = true;
|
||||
|
||||
if (this.isFontLoadingAPISupported) {
|
||||
if (FontLoader.isFontLoadingAPISupported) {
|
||||
var nativeFontFace = font.createNativeFontFace();
|
||||
if (nativeFontFace) {
|
||||
this.addNativeFontFace(nativeFontFace);
|
||||
fontLoadPromises.push(getNativeFontPromise(nativeFontFace));
|
||||
}
|
||||
} else {
|
||||
var rule = font.bindDOM();
|
||||
var rule = font.createFontFaceRule();
|
||||
if (rule) {
|
||||
this.insertRule(rule);
|
||||
rules.push(rule);
|
||||
fontsToLoad.push(font);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var request = FontLoader.queueLoadingCallback(callback);
|
||||
if (this.isFontLoadingAPISupported) {
|
||||
var request = this.queueLoadingCallback(callback);
|
||||
if (FontLoader.isFontLoadingAPISupported) {
|
||||
Promise.all(fontLoadPromises).then(function() {
|
||||
request.complete();
|
||||
});
|
||||
} else if (rules.length > 0 && !this.isSyncFontLoadingSupported) {
|
||||
FontLoader.prepareFontLoadEvent(rules, fontsToLoad, request);
|
||||
} else if (rules.length > 0 && !FontLoader.isSyncFontLoadingSupported) {
|
||||
this.prepareFontLoadEvent(rules, fontsToLoad, request);
|
||||
} else {
|
||||
request.complete();
|
||||
}
|
||||
@ -184,7 +155,7 @@ var FontLoader = {
|
||||
}
|
||||
}
|
||||
|
||||
var context = FontLoader.loadingContext;
|
||||
var context = this.loadingContext;
|
||||
var requestId = 'pdfjs-font-loading-' + (context.nextRequestId++);
|
||||
var request = {
|
||||
id: requestId,
|
||||
@ -271,7 +242,7 @@ var FontLoader = {
|
||||
var url = 'url(data:font/opentype;base64,' + btoa(data) + ');';
|
||||
var rule = '@font-face { font-family:"' + loadTestFontId + '";src:' +
|
||||
url + '}';
|
||||
FontLoader.insertRule(rule);
|
||||
this.insertRule(rule);
|
||||
|
||||
var names = [];
|
||||
for (i = 0, ii = fonts.length; i < ii; i++) {
|
||||
@ -316,19 +287,56 @@ var FontLoader = {
|
||||
//}
|
||||
//#endif
|
||||
};
|
||||
//#if !(MOZCENTRAL)
|
||||
FontLoader.isFontLoadingAPISupported = (!isWorker &&
|
||||
typeof document !== 'undefined' && !!document.fonts);
|
||||
//#endif
|
||||
//#if !(MOZCENTRAL || CHROME)
|
||||
Object.defineProperty(FontLoader, 'isSyncFontLoadingSupported', {
|
||||
get: function () {
|
||||
var supported = false;
|
||||
|
||||
// User agent string sniffing is bad, but there is no reliable way to tell
|
||||
// if font is fully loaded and ready to be used with canvas.
|
||||
var userAgent = window.navigator.userAgent;
|
||||
var m = /Mozilla\/5.0.*?rv:(\d+).*? Gecko/.exec(userAgent);
|
||||
if (m && m[1] >= 14) {
|
||||
supported = true;
|
||||
}
|
||||
// TODO other browsers
|
||||
if (userAgent === 'node') {
|
||||
supported = true;
|
||||
}
|
||||
return shadow(FontLoader, 'isSyncFontLoadingSupported', supported);
|
||||
},
|
||||
enumerable: true,
|
||||
configurable: true
|
||||
});
|
||||
//#endif
|
||||
|
||||
var FontFaceObject = (function FontFaceObjectClosure() {
|
||||
function FontFaceObject(name, file, properties) {
|
||||
function FontFaceObject(translatedData) {
|
||||
this.compiledGlyphs = {};
|
||||
if (arguments.length === 1) {
|
||||
// importing translated data
|
||||
var data = arguments[0];
|
||||
for (var i in data) {
|
||||
this[i] = data[i];
|
||||
}
|
||||
return;
|
||||
// importing translated data
|
||||
for (var i in translatedData) {
|
||||
this[i] = translatedData[i];
|
||||
}
|
||||
}
|
||||
Object.defineProperty(FontFaceObject, 'isEvalSupported', {
|
||||
get: function () {
|
||||
var evalSupport = false;
|
||||
if (PDFJS.isEvalSupported) {
|
||||
try {
|
||||
/* jshint evil: true */
|
||||
new Function('');
|
||||
evalSupport = true;
|
||||
} catch (e) {}
|
||||
}
|
||||
return shadow(this, 'isEvalSupported', evalSupport);
|
||||
},
|
||||
enumerable: true,
|
||||
configurable: true
|
||||
});
|
||||
FontFaceObject.prototype = {
|
||||
//#if !(MOZCENTRAL)
|
||||
createNativeFontFace: function FontFaceObject_createNativeFontFace() {
|
||||
@ -343,8 +351,6 @@ var FontFaceObject = (function FontFaceObjectClosure() {
|
||||
|
||||
var nativeFontFace = new FontFace(this.loadedName, this.data, {});
|
||||
|
||||
FontLoader.addNativeFontFace(nativeFontFace);
|
||||
|
||||
if (PDFJS.pdfBug && 'FontInspector' in globalScope &&
|
||||
globalScope['FontInspector'].enabled) {
|
||||
globalScope['FontInspector'].fontAdded(this);
|
||||
@ -353,7 +359,7 @@ var FontFaceObject = (function FontFaceObjectClosure() {
|
||||
},
|
||||
//#endif
|
||||
|
||||
bindDOM: function FontFaceObject_bindDOM() {
|
||||
createFontFaceRule: function FontFaceObject_createFontFaceRule() {
|
||||
if (!this.data) {
|
||||
return null;
|
||||
}
|
||||
@ -370,7 +376,6 @@ var FontFaceObject = (function FontFaceObjectClosure() {
|
||||
var url = ('url(data:' + this.mimetype + ';base64,' +
|
||||
window.btoa(data) + ');');
|
||||
var rule = '@font-face { font-family:"' + fontName + '";src:' + url + '}';
|
||||
FontLoader.insertRule(rule);
|
||||
|
||||
if (PDFJS.pdfBug && 'FontInspector' in globalScope &&
|
||||
globalScope['FontInspector'].enabled) {
|
||||
@ -380,13 +385,14 @@ var FontFaceObject = (function FontFaceObjectClosure() {
|
||||
return rule;
|
||||
},
|
||||
|
||||
getPathGenerator: function FontLoader_getPathGenerator(objs, character) {
|
||||
getPathGenerator:
|
||||
function FontFaceObject_getPathGenerator(objs, character) {
|
||||
if (!(character in this.compiledGlyphs)) {
|
||||
var cmds = objs.get(this.loadedName + '_path_' + character);
|
||||
var current, i, len;
|
||||
|
||||
// If we can, compile cmds into JS for MAXIMUM SPEED
|
||||
if (FontLoader.isEvalSupported) {
|
||||
if (FontFaceObject.isEvalSupported) {
|
||||
var args, js = '';
|
||||
for (i = 0, len = cmds.length; i < len; i++) {
|
||||
current = cmds[i];
|
||||
|
@ -1518,26 +1518,20 @@ PDFJS.createObjectURL = (function createObjectURLClosure() {
|
||||
};
|
||||
})();
|
||||
|
||||
function MessageHandler(name, comObj) {
|
||||
this.name = name;
|
||||
function MessageHandler(sourceName, targetName, comObj) {
|
||||
this.sourceName = sourceName;
|
||||
this.targetName = targetName;
|
||||
this.comObj = comObj;
|
||||
this.callbackIndex = 1;
|
||||
this.postMessageTransfers = true;
|
||||
var callbacksCapabilities = this.callbacksCapabilities = {};
|
||||
var ah = this.actionHandler = {};
|
||||
|
||||
ah['console_log'] = [function ahConsoleLog(data) {
|
||||
console.log.apply(console, data);
|
||||
}];
|
||||
ah['console_error'] = [function ahConsoleError(data) {
|
||||
console.error.apply(console, data);
|
||||
}];
|
||||
ah['_unsupported_feature'] = [function ah_unsupportedFeature(data) {
|
||||
UnsupportedManager.notify(data);
|
||||
}];
|
||||
|
||||
comObj.onmessage = function messageHandlerComObjOnMessage(event) {
|
||||
this._onComObjOnMessage = function messageHandlerComObjOnMessage(event) {
|
||||
var data = event.data;
|
||||
if (data.targetName !== this.sourceName) {
|
||||
return;
|
||||
}
|
||||
if (data.isReply) {
|
||||
var callbackId = data.callbackId;
|
||||
if (data.callbackId in callbacksCapabilities) {
|
||||
@ -1554,10 +1548,14 @@ function MessageHandler(name, comObj) {
|
||||
} else if (data.action in ah) {
|
||||
var action = ah[data.action];
|
||||
if (data.callbackId) {
|
||||
var sourceName = this.sourceName;
|
||||
var targetName = data.sourceName;
|
||||
Promise.resolve().then(function () {
|
||||
return action[0].call(action[1], data.data);
|
||||
}).then(function (result) {
|
||||
comObj.postMessage({
|
||||
sourceName: sourceName,
|
||||
targetName: targetName,
|
||||
isReply: true,
|
||||
callbackId: data.callbackId,
|
||||
data: result
|
||||
@ -1568,6 +1566,8 @@ function MessageHandler(name, comObj) {
|
||||
reason = reason + '';
|
||||
}
|
||||
comObj.postMessage({
|
||||
sourceName: sourceName,
|
||||
targetName: targetName,
|
||||
isReply: true,
|
||||
callbackId: data.callbackId,
|
||||
error: reason
|
||||
@ -1579,7 +1579,8 @@ function MessageHandler(name, comObj) {
|
||||
} else {
|
||||
error('Unknown action from worker: ' + data.action);
|
||||
}
|
||||
};
|
||||
}.bind(this);
|
||||
comObj.addEventListener('message', this._onComObjOnMessage);
|
||||
}
|
||||
|
||||
MessageHandler.prototype = {
|
||||
@ -1598,6 +1599,8 @@ MessageHandler.prototype = {
|
||||
*/
|
||||
send: function messageHandlerSend(actionName, data, transfers) {
|
||||
var message = {
|
||||
sourceName: this.sourceName,
|
||||
targetName: this.targetName,
|
||||
action: actionName,
|
||||
data: data
|
||||
};
|
||||
@ -1615,6 +1618,8 @@ MessageHandler.prototype = {
|
||||
function messageHandlerSendWithPromise(actionName, data, transfers) {
|
||||
var callbackId = this.callbackIndex++;
|
||||
var message = {
|
||||
sourceName: this.sourceName,
|
||||
targetName: this.targetName,
|
||||
action: actionName,
|
||||
data: data,
|
||||
callbackId: callbackId
|
||||
@ -1640,6 +1645,10 @@ MessageHandler.prototype = {
|
||||
} else {
|
||||
this.comObj.postMessage(message);
|
||||
}
|
||||
},
|
||||
|
||||
destroy: function () {
|
||||
this.comObj.removeEventListener('message', this._onComObjOnMessage);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -77,8 +77,7 @@ describe('api', function() {
|
||||
var loadingTask = PDFJS.getDocument(basicApiUrl);
|
||||
// This can be somewhat random -- we cannot guarantee perfect
|
||||
// 'Terminate' message to the worker before/after setting up pdfManager.
|
||||
var destroyed = loadingTask._transport.workerInitializedCapability.
|
||||
promise.then(function () {
|
||||
var destroyed = loadingTask._worker.promise.then(function () {
|
||||
return loadingTask.destroy();
|
||||
});
|
||||
waitsForPromiseResolved(destroyed, function (data) {
|
||||
@ -208,6 +207,73 @@ describe('api', function() {
|
||||
});
|
||||
});
|
||||
});
|
||||
describe('PDFWorker', function() {
|
||||
it('worker created or destroyed', function () {
|
||||
var worker = new PDFJS.PDFWorker('test1');
|
||||
waitsForPromiseResolved(worker.promise, function () {
|
||||
expect(worker.name).toEqual('test1');
|
||||
expect(!!worker.port).toEqual(true);
|
||||
expect(worker.destroyed).toEqual(false);
|
||||
expect(!!worker._webWorker).toEqual(true);
|
||||
expect(worker.port === worker._webWorker).toEqual(true);
|
||||
|
||||
worker.destroy();
|
||||
expect(!!worker.port).toEqual(false);
|
||||
expect(worker.destroyed).toEqual(true);
|
||||
});
|
||||
});
|
||||
it('worker created or destroyed by getDocument', function () {
|
||||
var loadingTask = PDFJS.getDocument(basicApiUrl);
|
||||
var worker;
|
||||
waitsForPromiseResolved(loadingTask.promise, function () {
|
||||
worker = loadingTask._worker;
|
||||
expect(!!worker).toEqual(true);
|
||||
});
|
||||
|
||||
var destroyPromise = loadingTask.promise.then(function () {
|
||||
return loadingTask.destroy();
|
||||
});
|
||||
waitsForPromiseResolved(destroyPromise, function () {
|
||||
var destroyedWorker = loadingTask._worker;
|
||||
expect(!!destroyedWorker).toEqual(false);
|
||||
expect(worker.destroyed).toEqual(true);
|
||||
});
|
||||
});
|
||||
it('worker created and can be used in getDocument', function () {
|
||||
var worker = new PDFJS.PDFWorker('test1');
|
||||
var loadingTask = PDFJS.getDocument({url: basicApiUrl, worker: worker});
|
||||
waitsForPromiseResolved(loadingTask.promise, function () {
|
||||
var docWorker = loadingTask._worker;
|
||||
expect(!!docWorker).toEqual(false);
|
||||
// checking is the same port is used in the MessageHandler
|
||||
var messageHandlerPort = loadingTask._transport.messageHandler.comObj;
|
||||
expect(messageHandlerPort === worker.port).toEqual(true);
|
||||
});
|
||||
|
||||
var destroyPromise = loadingTask.promise.then(function () {
|
||||
return loadingTask.destroy();
|
||||
});
|
||||
waitsForPromiseResolved(destroyPromise, function () {
|
||||
expect(worker.destroyed).toEqual(false);
|
||||
worker.destroy();
|
||||
});
|
||||
});
|
||||
it('creates more than one worker', function () {
|
||||
var worker1 = new PDFJS.PDFWorker('test1');
|
||||
var worker2 = new PDFJS.PDFWorker('test2');
|
||||
var worker3 = new PDFJS.PDFWorker('test3');
|
||||
var ready = Promise.all([worker1.promise, worker2.promise,
|
||||
worker3.promise]);
|
||||
waitsForPromiseResolved(ready, function () {
|
||||
expect(worker1.port !== worker2.port &&
|
||||
worker1.port !== worker3.port &&
|
||||
worker2.port !== worker3.port).toEqual(true);
|
||||
worker1.destroy();
|
||||
worker2.destroy();
|
||||
worker3.destroy();
|
||||
});
|
||||
});
|
||||
});
|
||||
describe('PDFDocument', function() {
|
||||
var promise = PDFJS.getDocument(basicApiUrl);
|
||||
var doc;
|
||||
|
Loading…
x
Reference in New Issue
Block a user