diff --git a/.eslintrc b/.eslintrc index d034a3ce6..2ed7871cf 100644 --- a/.eslintrc +++ b/.eslintrc @@ -68,6 +68,7 @@ "no-redeclare": "error", "no-self-assign": "error", "no-self-compare": "error", + "no-throw-literal": "error", "no-unused-expressions": "error", "no-unused-labels": "error", "no-useless-call": "error", diff --git a/src/display/api.js b/src/display/api.js index 4a3c1f810..984b27b72 100644 --- a/src/display/api.js +++ b/src/display/api.js @@ -60,6 +60,7 @@ var FontFaceObject = displayFontLoader.FontFaceObject; var FontLoader = displayFontLoader.FontLoader; var CanvasGraphics = displayCanvas.CanvasGraphics; var Metadata = displayMetadata.Metadata; +var RenderingCancelledException = displayDOMUtils.RenderingCancelledException; var getDefaultSetting = displayDOMUtils.getDefaultSetting; var DOMCanvasFactory = displayDOMUtils.DOMCanvasFactory; var DOMCMapReaderFactory = displayDOMUtils.DOMCMapReaderFactory; @@ -2147,7 +2148,14 @@ var InternalRenderTask = (function InternalRenderTaskClosure() { cancel: function InternalRenderTask_cancel() { this.running = false; this.cancelled = true; - this.callback('cancelled'); + + if ((typeof PDFJSDev !== 'undefined' && PDFJSDev.test('PDFJS_NEXT')) || + getDefaultSetting('pdfjsNext')) { + this.callback(new RenderingCancelledException( + 'Rendering cancelled, page ' + this.pageNumber, 'canvas')); + } else { + this.callback('cancelled'); + } }, operatorListChanged: function InternalRenderTask_operatorListChanged() { diff --git a/src/display/dom_utils.js b/src/display/dom_utils.js index e27456064..9df1b9395 100644 --- a/src/display/dom_utils.js +++ b/src/display/dom_utils.js @@ -173,6 +173,19 @@ var CustomStyle = (function CustomStyleClosure() { return CustomStyle; })(); +var RenderingCancelledException = (function RenderingCancelledException() { + function RenderingCancelledException(msg, type) { + this.message = msg; + this.type = type; + } + + RenderingCancelledException.prototype = new Error(); + RenderingCancelledException.prototype.name = 'RenderingCancelledException'; + RenderingCancelledException.constructor = RenderingCancelledException; + + return RenderingCancelledException; +})(); + var hasCanvasTypedArrays; if (typeof PDFJSDev === 'undefined' || !PDFJSDev.test('FIREFOX || MOZCENTRAL || CHROME')) { @@ -337,6 +350,7 @@ exports.isExternalLinkTargetSet = isExternalLinkTargetSet; exports.isValidUrl = isValidUrl; exports.getFilenameFromUrl = getFilenameFromUrl; exports.LinkTarget = LinkTarget; +exports.RenderingCancelledException = RenderingCancelledException; exports.hasCanvasTypedArrays = hasCanvasTypedArrays; exports.getDefaultSetting = getDefaultSetting; exports.DEFAULT_LINK_REL = DEFAULT_LINK_REL; diff --git a/src/main_loader.js b/src/main_loader.js index 1de29358f..0d3c24ba1 100644 --- a/src/main_loader.js +++ b/src/main_loader.js @@ -62,6 +62,8 @@ exports.removeNullCharacters = sharedUtil.removeNullCharacters; exports.shadow = sharedUtil.shadow; exports.createBlob = sharedUtil.createBlob; + exports.RenderingCancelledException = + displayDOMUtils.RenderingCancelledException; exports.getFilenameFromUrl = displayDOMUtils.getFilenameFromUrl; exports.addLinkAttributes = displayDOMUtils.addLinkAttributes; })); diff --git a/src/pdf.js b/src/pdf.js index 1dc23daa0..62d60a003 100644 --- a/src/pdf.js +++ b/src/pdf.js @@ -52,5 +52,7 @@ exports.createObjectURL = pdfjsSharedUtil.createObjectURL; exports.removeNullCharacters = pdfjsSharedUtil.removeNullCharacters; exports.shadow = pdfjsSharedUtil.shadow; exports.createBlob = pdfjsSharedUtil.createBlob; +exports.RenderingCancelledException = + pdfjsDisplayDOMUtils.RenderingCancelledException; exports.getFilenameFromUrl = pdfjsDisplayDOMUtils.getFilenameFromUrl; exports.addLinkAttributes = pdfjsDisplayDOMUtils.addLinkAttributes; diff --git a/test/unit/api_spec.js b/test/unit/api_spec.js index dec19928f..9929676b6 100644 --- a/test/unit/api_spec.js +++ b/test/unit/api_spec.js @@ -17,19 +17,23 @@ (function (root, factory) { if (typeof define === 'function' && define.amd) { define('pdfjs-test/unit/api_spec', ['exports', 'pdfjs/shared/util', - 'pdfjs/display/global', 'pdfjs/display/api'], factory); + 'pdfjs/display/dom_utils', 'pdfjs/display/global', 'pdfjs/display/api'], + factory); } else if (typeof exports !== 'undefined') { factory(exports, require('../../src/shared/util.js'), - require('../../src/display/global.js'), - require('../../src/display/api.js')); + require('../../src/display/dom_utils.js'), + require('../../src/display/global.js'), + require('../../src/display/api.js')); } else { factory((root.pdfjsTestUnitApiSpec = {}), root.pdfjsSharedUtil, - root.pdfjsDisplayGlobal, root.pdfjsDisplayApi); + root.pdfjsDisplayDOMUtils, root.pdfjsDisplayGlobal, root.pdfjsDisplayApi); } -}(this, function (exports, sharedUtil, displayGlobal, displayApi) { +}(this, function (exports, sharedUtil, displayDOMUtils, displayGlobal, + displayApi) { var PDFJS = displayGlobal.PDFJS; var createPromiseCapability = sharedUtil.createPromiseCapability; +var RenderingCancelledException = displayDOMUtils.RenderingCancelledException; var PDFDocumentProxy = displayApi.PDFDocumentProxy; var InvalidPDFException = sharedUtil.InvalidPDFException; var MissingPDFException = sharedUtil.MissingPDFException; @@ -1000,6 +1004,25 @@ describe('api', function() { done.fail(reason); }); }); + + it('cancels rendering of page', function(done) { + var canvas = document.createElement('canvas'); + var viewport = page.getViewport(1); + + var renderTask = page.render({ + canvasContext: canvas.getContext('2d'), + viewport: viewport, + }); + renderTask.cancel(); + + renderTask.promise.then(function() { + done.fail('shall cancel rendering'); + }).catch(function (error) { + expect(error instanceof RenderingCancelledException).toEqual(true); + expect(error.type).toEqual('canvas'); + done(); + }); + }); }); describe('Multiple PDFJS instances', function() { // Regression test for https://github.com/mozilla/pdf.js/issues/6205 diff --git a/web/pdf_page_view.js b/web/pdf_page_view.js index 0ea77452a..13c714efb 100644 --- a/web/pdf_page_view.js +++ b/web/pdf_page_view.js @@ -418,7 +418,9 @@ var PDFPageView = (function PDFPageViewClosure() { self.paintTask = null; } - if (error === 'cancelled') { + if (((typeof PDFJSDev === 'undefined' || + !PDFJSDev.test('PDFJS_NEXT')) && error === 'cancelled') || + error instanceof pdfjsLib.RenderingCancelledException) { self.error = null; return Promise.resolve(undefined); } @@ -625,7 +627,13 @@ var PDFPageView = (function PDFPageViewClosure() { var cancelled = false; var ensureNotCancelled = function () { if (cancelled) { - throw 'cancelled'; + if ((typeof PDFJSDev !== 'undefined' && + PDFJSDev.test('PDFJS_NEXT')) || pdfjsLib.PDFJS.pdfjsNext) { + throw new pdfjsLib.RenderingCancelledException( + 'Rendering cancelled, page ' + self.id, 'svg'); + } else { + throw 'cancelled'; // eslint-disable-line no-throw-literal + } } };