Merge pull request #847 from brendandahl/errorhandling

Improved error handling
This commit is contained in:
notmasteryet 2011-12-02 16:54:40 -08:00
commit c80ba5982f
6 changed files with 163 additions and 25 deletions

View File

@ -39,11 +39,15 @@ function getPdf(arg, callback) {
if ('error' in params) if ('error' in params)
xhr.onerror = params.error || undefined; xhr.onerror = params.error || undefined;
xhr.onreadystatechange = function getPdfOnreadystatechange() { xhr.onreadystatechange = function getPdfOnreadystatechange(e) {
if (xhr.readyState === 4 && xhr.status === xhr.expected) { if (xhr.readyState === 4) {
var data = (xhr.mozResponseArrayBuffer || xhr.mozResponse || if (xhr.status === xhr.expected) {
xhr.responseArrayBuffer || xhr.response); var data = (xhr.mozResponseArrayBuffer || xhr.mozResponse ||
callback(data); xhr.responseArrayBuffer || xhr.response);
callback(data);
} else if (params.error) {
params.error(e);
}
} }
}; };
xhr.send(null); xhr.send(null);
@ -63,6 +67,9 @@ var Page = (function pagePage() {
}; };
this.xref = xref; this.xref = xref;
this.ref = ref; this.ref = ref;
this.ctx = null;
this.callback = null;
} }
constructor.prototype = { constructor.prototype = {
@ -165,8 +172,10 @@ var Page = (function pagePage() {
try { try {
self.display(gfx, self.callback); self.display(gfx, self.callback);
} catch (e) { } catch (e) {
if (self.callback) self.callback(e.toString()); if (self.callback)
throw e; self.callback(e);
else
throw e;
} }
}); });
}; };
@ -590,6 +599,14 @@ var PDFDoc = (function pdfDoc() {
} }
}.bind(this)); }.bind(this));
messageHandler.on('page_error', function pdfDocError(data) {
var page = this.pageCache[data.pageNum];
if (page.callback)
page.callback(data.error);
else
throw data.error;
}, this);
setTimeout(function pdfDocFontReadySetTimeout() { setTimeout(function pdfDocFontReadySetTimeout() {
messageHandler.send('doc', this.data); messageHandler.send('doc', this.data);
this.workerReadyPromise.resolve(true); this.workerReadyPromise.resolve(true);

View File

@ -14,7 +14,6 @@ function MessageHandler(name, comObj) {
ah['console_error'] = [function ahConsoleError(data) { ah['console_error'] = [function ahConsoleError(data) {
console.error.apply(console, data); console.error.apply(console, data);
}]; }];
comObj.onmessage = function messageHandlerComObjOnMessage(event) { comObj.onmessage = function messageHandlerComObjOnMessage(event) {
var data = event.data; var data = event.data;
if (data.action in ah) { if (data.action in ah) {
@ -67,7 +66,6 @@ var WorkerMessageHandler = {
handler.on('page_request', function wphSetupPageRequest(pageNum) { handler.on('page_request', function wphSetupPageRequest(pageNum) {
pageNum = parseInt(pageNum); pageNum = parseInt(pageNum);
var page = pdfDoc.getPage(pageNum);
// The following code does quite the same as // The following code does quite the same as
// Page.prototype.startRendering, but stops at one point and sends the // Page.prototype.startRendering, but stops at one point and sends the
@ -77,9 +75,23 @@ var WorkerMessageHandler = {
var start = Date.now(); var start = Date.now();
var dependency = []; var dependency = [];
var IRQueue = null;
// Pre compile the pdf page and fetch the fonts/images. try {
var IRQueue = page.getIRQueue(handler, dependency); var page = pdfDoc.getPage(pageNum);
// Pre compile the pdf page and fetch the fonts/images.
IRQueue = page.getIRQueue(handler, dependency);
} catch (e) {
// Turn the error into an obj that can be serialized
e = {
message: e.message,
stack: e.stack
};
handler.send('page_error', {
pageNum: pageNum,
error: e
});
return;
}
console.log('page=%d - getIRQueue: time=%dms, len=%d', pageNum, console.log('page=%d - getIRQueue: time=%dms, len=%d', pageNum,
Date.now() - start, IRQueue.fnArray.length); Date.now() - start, IRQueue.fnArray.length);

View File

@ -162,9 +162,11 @@ function nextPage(task, loadError) {
page.startRendering( page.startRendering(
ctx, ctx,
function nextPageStartRendering(e) { function nextPageStartRendering(error) {
snapshotCurrentPage(task, (!failure && e) ? var failureMessage = false;
('render : ' + e) : failure); if (error)
failureMessage = 'render : ' + error.message;
snapshotCurrentPage(task, failureMessage);
} }
); );
} catch (e) { } catch (e) {

View File

@ -273,6 +273,38 @@ canvas {
display: none; display: none;
} }
#errorWrapper {
background: none repeat scroll 0 0 #FF5555;
color: white;
left: 0;
position: fixed;
right: 0;
top: 30px;
z-index: 1000;
padding: 3px;
font-size: 0.8em;
}
#errorMessageLeft {
float: left;
}
#errorMessageRight {
float: right;
}
#errorMoreInfo {
background-color: #FFFFFF;
color: black;
padding: 3px;
margin: 3px;
white-space: pre;
}
.clearBoth {
clear: both;
}
/* === Printed media overrides === */ /* === Printed media overrides === */
@media print { @media print {
#sidebar { #sidebar {

View File

@ -97,6 +97,24 @@
<span id="info">--</span> <span id="info">--</span>
</div> </div>
<div id="errorWrapper" hidden='true'>
<div id="errorMessageLeft">
<span id="errorMessage"></span>
<button id="errorShowMore" onclick="" oncontextmenu="return false;">
More Information
</button>
<button id="errorShowLess" onclick="" oncontextmenu="return false;" hidden='true'>
Less Information
</button>
</div>
<div id="errorMessageRight">
<button id="errorClose" oncontextmenu="return false;">
Close
</button>
</div>
<div class="clearBoth"></div>
<div id="errorMoreInfo" hidden='true'></div>
</div>
<div id="sidebar"> <div id="sidebar">
<div id="sidebarBox"> <div id="sidebarBox">

View File

@ -129,7 +129,14 @@ var PDFView = {
if (evt.lengthComputable) if (evt.lengthComputable)
self.progress(evt.loaded / evt.total); self.progress(evt.loaded / evt.total);
}, },
error: self.error error: function getPdfError(e) {
var loadingIndicator = document.getElementById('loading');
loadingIndicator.innerHTML = 'Error';
var moreInfo = {
message: 'Unexpected server response of ' + e.target.status + '.'
};
self.error('An error occurred while loading the PDF.', moreInfo);
}
}, },
function getPdfLoad(data) { function getPdfLoad(data) {
self.loading = true; self.loading = true;
@ -181,9 +188,47 @@ var PDFView = {
return ''; return '';
}, },
error: function pdfViewError() { /**
var loadingIndicator = document.getElementById('loading'); * Show the error box.
loadingIndicator.innerHTML = 'Error'; * @param {String} message A message that is human readable.
* @param {Object} moreInfo (optional) Further information about the error
* that is more technical. Should have a 'message'
* and optionally a 'stack' property.
*/
error: function pdfViewError(message, moreInfo) {
var errorWrapper = document.getElementById('errorWrapper');
errorWrapper.removeAttribute('hidden');
var errorMessage = document.getElementById('errorMessage');
errorMessage.innerHTML = message;
var closeButton = document.getElementById('errorClose');
closeButton.onclick = function() {
errorWrapper.setAttribute('hidden', 'true');
};
var errorMoreInfo = document.getElementById('errorMoreInfo');
var moreInfoButton = document.getElementById('errorShowMore');
var lessInfoButton = document.getElementById('errorShowLess');
moreInfoButton.onclick = function() {
errorMoreInfo.removeAttribute('hidden');
moreInfoButton.setAttribute('hidden', 'true');
lessInfoButton.removeAttribute('hidden');
};
lessInfoButton.onclick = function() {
errorMoreInfo.setAttribute('hidden', 'true');
moreInfoButton.removeAttribute('hidden');
lessInfoButton.setAttribute('hidden', 'true');
};
moreInfoButton.removeAttribute('hidden');
lessInfoButton.setAttribute('hidden', 'true');
errorMoreInfo.innerHTML = 'PDF.JS Build: ' + PDFJS.build + '\n';
if (moreInfo) {
errorMoreInfo.innerHTML += 'Message: ' + moreInfo.message;
if (moreInfo.stack)
errorMoreInfo.innerHTML += '\n' + 'Stack: ' + moreInfo.stack;
}
}, },
progress: function pdfViewProgress(level) { progress: function pdfViewProgress(level) {
@ -200,6 +245,9 @@ var PDFView = {
}; };
} }
var errorWrapper = document.getElementById('errorWrapper');
errorWrapper.setAttribute('hidden', 'true');
var loadingIndicator = document.getElementById('loading'); var loadingIndicator = document.getElementById('loading');
loadingIndicator.setAttribute('hidden', 'true'); loadingIndicator.setAttribute('hidden', 'true');
@ -216,7 +264,12 @@ var PDFView = {
while (container.hasChildNodes()) while (container.hasChildNodes())
container.removeChild(container.lastChild); container.removeChild(container.lastChild);
var pdf = new PDFJS.PDFDoc(data); var pdf;
try {
pdf = new PDFJS.PDFDoc(data);
} catch (e) {
this.error('An error occurred while reading the PDF.', e);
}
var pagesCount = pdf.numPages; var pagesCount = pdf.numPages;
document.getElementById('numPages').innerHTML = pagesCount; document.getElementById('numPages').innerHTML = pagesCount;
document.getElementById('pageNumber').max = pagesCount; document.getElementById('pageNumber').max = pagesCount;
@ -505,11 +558,15 @@ var PageView = function pageView(container, content, id, pageWidth, pageHeight,
ctx.translate(-this.x * scale, -this.y * scale); ctx.translate(-this.x * scale, -this.y * scale);
stats.begin = Date.now(); stats.begin = Date.now();
this.content.startRendering(ctx, (function pageViewDrawCallback() { this.content.startRendering(ctx,
this.updateStats(); (function pageViewDrawCallback(error) {
if (this.onAfterDraw) if (error)
this.onAfterDraw(); PDFView.error('An error occurred while rendering the page.', error);
}).bind(this), textLayer); this.updateStats();
if (this.onAfterDraw)
this.onAfterDraw();
}).bind(this), textLayer
);
setupLinks(this.content, this.scale); setupLinks(this.content, this.scale);
div.setAttribute('data-loaded', true); div.setAttribute('data-loaded', true);