diff --git a/src/api.js b/src/api.js index 2ab23bdde..b3ff6f8d6 100644 --- a/src/api.js +++ b/src/api.js @@ -18,7 +18,9 @@ * @return {Promise} A promise that is resolved with {PDFDocumentProxy} object. */ PDFJS.getDocument = function getDocument(source) { - var url, data, headers, password, parameters = {}; + var url, data, headers, password, parameters = {}, workerInitializedPromise, + workerReadyPromise, transport; + if (typeof source === 'string') { url = source; } else if (isArrayBuffer(source)) { @@ -37,8 +39,9 @@ PDFJS.getDocument = function getDocument(source) { 'string or a parameter object'); } - var promise = new PDFJS.Promise(); - var transport = new WorkerTransport(promise); + workerInitializedPromise = new PDFJS.Promise(); + workerReadyPromise = new PDFJS.Promise(); + transport = new WorkerTransport(workerInitializedPromise, workerReadyPromise); if (data) { // assuming the data is array, instantiating directly from it transport.sendData(data, parameters); @@ -48,24 +51,31 @@ PDFJS.getDocument = function getDocument(source) { { url: url, progress: function getPDFProgress(evt) { - if (evt.lengthComputable) - promise.progress({ + if (evt.lengthComputable) { + workerReadyPromise.progress({ loaded: evt.loaded, total: evt.total }); + } }, error: function getPDFError(e) { - promise.reject('Unexpected server response of ' + + workerReadyPromise.reject('Unexpected server response of ' + e.target.status + '.'); }, headers: headers }, function getPDFLoad(data) { - transport.sendData(data, parameters); + // sometimes the pdf has finished downloading before the web worker-test + // has finished. In that case the rendering of the final pdf would cause + // errors. We have to wait for the WorkerTransport to finalize worker- + // support detection + workerInitializedPromise.then(function workerInitialized() { + transport.sendData(data, parameters); + }); }); } - return promise; + return workerReadyPromise; }; /** @@ -426,8 +436,8 @@ var PDFPageProxy = (function PDFPageProxyClosure() { * For internal use only. */ var WorkerTransport = (function WorkerTransportClosure() { - function WorkerTransport(promise) { - this.workerReadyPromise = promise; + function WorkerTransport(workerInitializedPromise, workerReadyPromise) { + this.workerReadyPromise = workerReadyPromise; this.objs = new PDFObjects(); this.pageCache = []; @@ -471,6 +481,7 @@ var WorkerTransport = (function WorkerTransportClosure() { globalScope.PDFJS.disableWorker = true; this.setupFakeWorker(); } + workerInitializedPromise.resolve(); }.bind(this)); var testObj = new Uint8Array(1); @@ -486,6 +497,7 @@ var WorkerTransport = (function WorkerTransportClosure() { // Thus, we fallback to a faked worker. globalScope.PDFJS.disableWorker = true; this.setupFakeWorker(); + workerInitializedPromise.resolve(); } WorkerTransport.prototype = { destroy: function WorkerTransport_destroy() { diff --git a/web/compatibility.js b/web/compatibility.js index 528841bb6..4b7119c63 100644 --- a/web/compatibility.js +++ b/web/compatibility.js @@ -6,6 +6,16 @@ // Checking if the typed arrays are supported (function checkTypedArrayCompatibility() { if (typeof Uint8Array !== 'undefined') { + // some mobile versions do not support subarray (e.g. safari 5 / iOS) + if (typeof Uint8Array.prototype.subarray === 'undefined') { + Uint8Array.prototype.subarray = function subarray(start, end) { + return new Uint8Array(this.slice(start, end)); + }; + Float32Array.prototype.subarray = function subarray(start, end) { + return new Float32Array(this.slice(start, end)); + }; + } + // some mobile version might not support Float64Array if (typeof Float64Array === 'undefined') window.Float64Array = Float32Array; @@ -69,8 +79,17 @@ // Object.defineProperty() ? (function checkObjectDefinePropertyCompatibility() { - if (typeof Object.defineProperty !== 'undefined') - return; + if (typeof Object.defineProperty !== 'undefined') { + // some browsers (e.g. safari) cannot use defineProperty() on DOM objects + // and thus the native version is not sufficient + var definePropertyPossible = true; + try { + Object.defineProperty(new Image(), 'id', { value: 'test' }); + } catch (e) { + definePropertyPossible = false; + } + if (definePropertyPossible) return; + } Object.defineProperty = function objectDefineProperty(obj, name, def) { delete obj[name];