diff --git a/browser/extensions/pdfjs/README.mozilla b/browser/extensions/pdfjs/README.mozilla index 24513981a94f9..9a94b248e5f1d 100644 --- a/browser/extensions/pdfjs/README.mozilla +++ b/browser/extensions/pdfjs/README.mozilla @@ -1,5 +1,5 @@ This is the PDF.js project output, https://github.com/mozilla/pdf.js -Current extension version is: 2.0.491 +Current extension version is: 2.0.506 -Taken from upstream commit: 2dc4af52 +Taken from upstream commit: b7a3a5e7 diff --git a/browser/extensions/pdfjs/content/PdfJsDefaultPreferences.jsm b/browser/extensions/pdfjs/content/PdfJsDefaultPreferences.jsm index a5b5744d1f5ed..111b957ed64e3 100644 --- a/browser/extensions/pdfjs/content/PdfJsDefaultPreferences.jsm +++ b/browser/extensions/pdfjs/content/PdfJsDefaultPreferences.jsm @@ -37,5 +37,7 @@ var PdfJsDefaultPreferences = Object.freeze({ "renderInteractiveForms": false, "enablePrintAutoRotate": false, "disablePageMode": false, - "disablePageLabels": false + "disablePageLabels": false, + "scrollModeOnLoad": 0, + "spreadModeOnLoad": 0 }); diff --git a/browser/extensions/pdfjs/content/build/pdf.js b/browser/extensions/pdfjs/content/build/pdf.js index 5021574500592..bce26136246ca 100644 --- a/browser/extensions/pdfjs/content/build/pdf.js +++ b/browser/extensions/pdfjs/content/build/pdf.js @@ -1650,8 +1650,8 @@ exports.GlobalWorkerOptions = GlobalWorkerOptions; "use strict"; -var pdfjsVersion = '2.0.491'; -var pdfjsBuild = '2dc4af52'; +var pdfjsVersion = '2.0.506'; +var pdfjsBuild = 'b7a3a5e7'; var pdfjsSharedUtil = __w_pdfjs_require__(0); var pdfjsDisplayAPI = __w_pdfjs_require__(9); var pdfjsDisplayTextLayer = __w_pdfjs_require__(17); @@ -4929,7 +4929,7 @@ function _fetchDocument(worker, source, pdfDataRangeTransport, docId) { } return worker.messageHandler.sendWithPromise('GetDocRequest', { docId, - apiVersion: '2.0.491', + apiVersion: '2.0.506', source: { data: source.data, url: source.url, @@ -6252,8 +6252,8 @@ var InternalRenderTask = function InternalRenderTaskClosure() { }(); var version, build; { - exports.version = version = '2.0.491'; - exports.build = build = '2dc4af52'; + exports.version = version = '2.0.506'; + exports.build = build = 'b7a3a5e7'; } exports.getDocument = getDocument; exports.LoopbackPort = LoopbackPort; diff --git a/browser/extensions/pdfjs/content/build/pdf.worker.js b/browser/extensions/pdfjs/content/build/pdf.worker.js index c7074a0789569..949bb48449a4a 100644 --- a/browser/extensions/pdfjs/content/build/pdf.worker.js +++ b/browser/extensions/pdfjs/content/build/pdf.worker.js @@ -21103,8 +21103,8 @@ exports.PostScriptCompiler = PostScriptCompiler; "use strict"; -var pdfjsVersion = '2.0.491'; -var pdfjsBuild = '2dc4af52'; +var pdfjsVersion = '2.0.506'; +var pdfjsBuild = 'b7a3a5e7'; var pdfjsCoreWorker = __w_pdfjs_require__(20); exports.WorkerMessageHandler = pdfjsCoreWorker.WorkerMessageHandler; @@ -21305,7 +21305,7 @@ var WorkerMessageHandler = { var cancelXHRs = null; var WorkerTasks = []; let apiVersion = docParams.apiVersion; - let workerVersion = '2.0.491'; + let workerVersion = '2.0.506'; if (apiVersion !== null && apiVersion !== workerVersion) { throw new Error(`The API version "${apiVersion}" does not match ` + `the Worker version "${workerVersion}".`); } diff --git a/browser/extensions/pdfjs/content/web/images/secondaryToolbarButton-scrollHorizontal.png b/browser/extensions/pdfjs/content/web/images/secondaryToolbarButton-scrollHorizontal.png new file mode 100644 index 0000000000000..cb702fc4d1114 Binary files /dev/null and b/browser/extensions/pdfjs/content/web/images/secondaryToolbarButton-scrollHorizontal.png differ diff --git a/browser/extensions/pdfjs/content/web/images/secondaryToolbarButton-scrollHorizontal@2x.png b/browser/extensions/pdfjs/content/web/images/secondaryToolbarButton-scrollHorizontal@2x.png new file mode 100644 index 0000000000000..7f05289bb157e Binary files /dev/null and b/browser/extensions/pdfjs/content/web/images/secondaryToolbarButton-scrollHorizontal@2x.png differ diff --git a/browser/extensions/pdfjs/content/web/images/secondaryToolbarButton-scrollVertical.png b/browser/extensions/pdfjs/content/web/images/secondaryToolbarButton-scrollVertical.png new file mode 100644 index 0000000000000..0b8427a16c0f3 Binary files /dev/null and b/browser/extensions/pdfjs/content/web/images/secondaryToolbarButton-scrollVertical.png differ diff --git a/browser/extensions/pdfjs/content/web/images/secondaryToolbarButton-scrollVertical@2x.png b/browser/extensions/pdfjs/content/web/images/secondaryToolbarButton-scrollVertical@2x.png new file mode 100644 index 0000000000000..72ab55ebf270e Binary files /dev/null and b/browser/extensions/pdfjs/content/web/images/secondaryToolbarButton-scrollVertical@2x.png differ diff --git a/browser/extensions/pdfjs/content/web/images/secondaryToolbarButton-scrollWrapped.png b/browser/extensions/pdfjs/content/web/images/secondaryToolbarButton-scrollWrapped.png new file mode 100644 index 0000000000000..165fc8bc01381 Binary files /dev/null and b/browser/extensions/pdfjs/content/web/images/secondaryToolbarButton-scrollWrapped.png differ diff --git a/browser/extensions/pdfjs/content/web/images/secondaryToolbarButton-scrollWrapped@2x.png b/browser/extensions/pdfjs/content/web/images/secondaryToolbarButton-scrollWrapped@2x.png new file mode 100644 index 0000000000000..4246141192214 Binary files /dev/null and b/browser/extensions/pdfjs/content/web/images/secondaryToolbarButton-scrollWrapped@2x.png differ diff --git a/browser/extensions/pdfjs/content/web/images/secondaryToolbarButton-spreadEven.png b/browser/extensions/pdfjs/content/web/images/secondaryToolbarButton-spreadEven.png new file mode 100644 index 0000000000000..3fa07e703eaa5 Binary files /dev/null and b/browser/extensions/pdfjs/content/web/images/secondaryToolbarButton-spreadEven.png differ diff --git a/browser/extensions/pdfjs/content/web/images/secondaryToolbarButton-spreadEven@2x.png b/browser/extensions/pdfjs/content/web/images/secondaryToolbarButton-spreadEven@2x.png new file mode 100644 index 0000000000000..32e5033d7db1b Binary files /dev/null and b/browser/extensions/pdfjs/content/web/images/secondaryToolbarButton-spreadEven@2x.png differ diff --git a/browser/extensions/pdfjs/content/web/images/secondaryToolbarButton-spreadNone.png b/browser/extensions/pdfjs/content/web/images/secondaryToolbarButton-spreadNone.png new file mode 100644 index 0000000000000..161147354c938 Binary files /dev/null and b/browser/extensions/pdfjs/content/web/images/secondaryToolbarButton-spreadNone.png differ diff --git a/browser/extensions/pdfjs/content/web/images/secondaryToolbarButton-spreadNone@2x.png b/browser/extensions/pdfjs/content/web/images/secondaryToolbarButton-spreadNone@2x.png new file mode 100644 index 0000000000000..8e51cf3b7d6eb Binary files /dev/null and b/browser/extensions/pdfjs/content/web/images/secondaryToolbarButton-spreadNone@2x.png differ diff --git a/browser/extensions/pdfjs/content/web/images/secondaryToolbarButton-spreadOdd.png b/browser/extensions/pdfjs/content/web/images/secondaryToolbarButton-spreadOdd.png new file mode 100644 index 0000000000000..5126313a1dee1 Binary files /dev/null and b/browser/extensions/pdfjs/content/web/images/secondaryToolbarButton-spreadOdd.png differ diff --git a/browser/extensions/pdfjs/content/web/images/secondaryToolbarButton-spreadOdd@2x.png b/browser/extensions/pdfjs/content/web/images/secondaryToolbarButton-spreadOdd@2x.png new file mode 100644 index 0000000000000..5996b74db1e0c Binary files /dev/null and b/browser/extensions/pdfjs/content/web/images/secondaryToolbarButton-spreadOdd@2x.png differ diff --git a/browser/extensions/pdfjs/content/web/viewer.css b/browser/extensions/pdfjs/content/web/viewer.css index 4efc835693614..a95657b95d181 100644 --- a/browser/extensions/pdfjs/content/web/viewer.css +++ b/browser/extensions/pdfjs/content/web/viewer.css @@ -290,6 +290,46 @@ border: none; } +.pdfViewer.scrollHorizontal, .pdfViewer.scrollWrapped, .spread { + margin-left: 3.5px; + margin-right: 3.5px; + text-align: center; +} + +.pdfViewer.scrollHorizontal, .spread { + white-space: nowrap; +} + +.pdfViewer.removePageBorders, +.pdfViewer.scrollHorizontal .spread, +.pdfViewer.scrollWrapped .spread { + margin-left: 0; + margin-right: 0; +} + +.spread .page, +.pdfViewer.scrollHorizontal .page, +.pdfViewer.scrollWrapped .page, +.pdfViewer.scrollHorizontal .spread, +.pdfViewer.scrollWrapped .spread { + display: inline-block; + vertical-align: middle; +} + +.spread .page, +.pdfViewer.scrollHorizontal .page, +.pdfViewer.scrollWrapped .page { + margin-left: -3.5px; + margin-right: -3.5px; +} + +.pdfViewer.removePageBorders .spread .page, +.pdfViewer.removePageBorders.scrollHorizontal .page, +.pdfViewer.removePageBorders.scrollWrapped .page { + margin-left: 5px; + margin-right: 5px; +} + .pdfViewer .page canvas { margin: 0; display: block; @@ -309,6 +349,22 @@ background: url('images/loading-icon.gif') center no-repeat; } +.pdfPresentationMode .pdfViewer { + margin-left: 0; + margin-right: 0; +} + +.pdfPresentationMode .pdfViewer .page, +.pdfPresentationMode .pdfViewer .spread { + display: block; +} + +.pdfPresentationMode .pdfViewer .page, +.pdfPresentationMode .pdfViewer.removePageBorders .page { + margin-left: auto; + margin-right: auto; +} + .pdfPresentationMode:-moz-full-screen .pdfViewer .page { margin-bottom: 100%; border: 0; @@ -1279,6 +1335,30 @@ html[dir="rtl"] .secondaryToolbarButton > span { content: url(images/secondaryToolbarButton-handTool.png); } +.secondaryToolbarButton.scrollVertical::before { + content: url(images/secondaryToolbarButton-scrollVertical.png); +} + +.secondaryToolbarButton.scrollHorizontal::before { + content: url(images/secondaryToolbarButton-scrollHorizontal.png); +} + +.secondaryToolbarButton.scrollWrapped::before { + content: url(images/secondaryToolbarButton-scrollWrapped.png); +} + +.secondaryToolbarButton.spreadNone::before { + content: url(images/secondaryToolbarButton-spreadNone.png); +} + +.secondaryToolbarButton.spreadOdd::before { + content: url(images/secondaryToolbarButton-spreadOdd.png); +} + +.secondaryToolbarButton.spreadEven::before { + content: url(images/secondaryToolbarButton-spreadEven.png); +} + .secondaryToolbarButton.documentProperties::before { content: url(images/secondaryToolbarButton-documentProperties.png); } @@ -1996,6 +2076,30 @@ html[dir='rtl'] #documentPropertiesOverlay .row > * { content: url(images/secondaryToolbarButton-handTool@2x.png); } + .secondaryToolbarButton.scrollVertical::before { + content: url(images/secondaryToolbarButton-scrollVertical@2x.png); + } + + .secondaryToolbarButton.scrollHorizontal::before { + content: url(images/secondaryToolbarButton-scrollHorizontal@2x.png); + } + + .secondaryToolbarButton.scrollWrapped::before { + content: url(images/secondaryToolbarButton-scrollWrapped@2x.png); + } + + .secondaryToolbarButton.spreadNone::before { + content: url(images/secondaryToolbarButton-spreadNone@2x.png); + } + + .secondaryToolbarButton.spreadOdd::before { + content: url(images/secondaryToolbarButton-spreadOdd@2x.png); + } + + .secondaryToolbarButton.spreadEven::before { + content: url(images/secondaryToolbarButton-spreadEven@2x.png); + } + .secondaryToolbarButton.documentProperties::before { content: url(images/secondaryToolbarButton-documentProperties@2x.png); } diff --git a/browser/extensions/pdfjs/content/web/viewer.html b/browser/extensions/pdfjs/content/web/viewer.html index 3939b0b4ec030..218e80dd16948 100644 --- a/browser/extensions/pdfjs/content/web/viewer.html +++ b/browser/extensions/pdfjs/content/web/viewer.html @@ -146,7 +146,31 @@
- + + + +
+ + + + + +
+ + diff --git a/browser/extensions/pdfjs/content/web/viewer.js b/browser/extensions/pdfjs/content/web/viewer.js index 070e00681edd6..f885a68e513a9 100644 --- a/browser/extensions/pdfjs/content/web/viewer.js +++ b/browser/extensions/pdfjs/content/web/viewer.js @@ -82,7 +82,7 @@ /******/ __webpack_require__.p = ""; /******/ /******/ // Load entry module and return exports -/******/ return __webpack_require__(__webpack_require__.s = 10); +/******/ return __webpack_require__(__webpack_require__.s = 11); /******/ }) /************************************************************************/ /******/ ([ @@ -95,7 +95,7 @@ Object.defineProperty(exports, "__esModule", { value: true }); -exports.waitOnEventOrTimeout = exports.WaitOnType = exports.animationStarted = exports.normalizeWheelEventDelta = exports.binarySearchFirstItem = exports.watchScroll = exports.scrollIntoView = exports.getOutputScale = exports.approximateFraction = exports.getPageSizeInches = exports.roundToDivide = exports.getVisibleElements = exports.parseQueryString = exports.noContextMenuHandler = exports.getPDFFileNameFromURL = exports.ProgressBar = exports.EventBus = exports.NullL10n = exports.TextLayerMode = exports.RendererType = exports.PresentationModeState = exports.cloneObj = exports.isFileSchema = exports.isPortraitOrientation = exports.isValidRotation = exports.VERTICAL_PADDING = exports.SCROLLBAR_PADDING = exports.MAX_AUTO_SCALE = exports.UNKNOWN_SCALE = exports.MAX_SCALE = exports.MIN_SCALE = exports.DEFAULT_SCALE = exports.DEFAULT_SCALE_VALUE = exports.CSS_UNITS = undefined; +exports.moveToEndOfArray = exports.waitOnEventOrTimeout = exports.WaitOnType = exports.animationStarted = exports.normalizeWheelEventDelta = exports.binarySearchFirstItem = exports.watchScroll = exports.scrollIntoView = exports.getOutputScale = exports.approximateFraction = exports.getPageSizeInches = exports.roundToDivide = exports.getVisibleElements = exports.backtrackBeforeAllVisibleElements = exports.parseQueryString = exports.noContextMenuHandler = exports.getPDFFileNameFromURL = exports.ProgressBar = exports.EventBus = exports.NullL10n = exports.TextLayerMode = exports.RendererType = exports.PresentationModeState = exports.cloneObj = exports.isFileSchema = exports.isPortraitOrientation = exports.isValidRotation = exports.VERTICAL_PADDING = exports.SCROLLBAR_PADDING = exports.MAX_AUTO_SCALE = exports.UNKNOWN_SCALE = exports.MAX_SCALE = exports.MIN_SCALE = exports.DEFAULT_SCALE = exports.DEFAULT_SCALE_VALUE = exports.CSS_UNITS = undefined; var _pdfjsLib = __webpack_require__(1); @@ -163,7 +163,7 @@ function scrollIntoView(element, spot, skipOverflowHiddenElements = false) { } let offsetY = element.offsetTop + element.clientTop; let offsetX = element.offsetLeft + element.clientLeft; - while (parent.clientHeight === parent.scrollHeight || skipOverflowHiddenElements && getComputedStyle(parent).overflow === 'hidden') { + while (parent.clientHeight === parent.scrollHeight && parent.clientWidth === parent.scrollWidth || skipOverflowHiddenElements && getComputedStyle(parent).overflow === 'hidden') { if (parent.dataset._scaleY) { offsetY /= parent.dataset._scaleY; offsetX /= parent.dataset._scaleX; @@ -193,6 +193,12 @@ function watchScroll(viewAreaElement, callback) { } rAF = window.requestAnimationFrame(function viewAreaElementScrolled() { rAF = null; + let currentX = viewAreaElement.scrollLeft; + let lastX = state.lastX; + if (currentX !== lastX) { + state.right = currentX > lastX; + } + state.lastX = currentX; let currentY = viewAreaElement.scrollTop; let lastY = state.lastY; if (currentY !== lastY) { @@ -203,7 +209,9 @@ function watchScroll(viewAreaElement, callback) { }); }; let state = { + right: true, down: true, + lastX: viewAreaElement.scrollLeft, lastY: viewAreaElement.scrollTop, _eventHandler: debounceScroll }; @@ -294,43 +302,79 @@ function getPageSizeInches({ view, userUnit, rotate }) { height: changeOrientation ? width : height }; } -function getVisibleElements(scrollEl, views, sortByVisibility = false) { +function backtrackBeforeAllVisibleElements(index, views, top) { + if (index < 2) { + return index; + } + let elt = views[index].div; + let pageTop = elt.offsetTop + elt.clientTop; + if (pageTop >= top) { + elt = views[index - 1].div; + pageTop = elt.offsetTop + elt.clientTop; + } + for (let i = index - 2; i >= 0; --i) { + elt = views[i].div; + if (elt.offsetTop + elt.clientTop + elt.clientHeight <= pageTop) { + break; + } + index = i; + } + return index; +} +function getVisibleElements(scrollEl, views, sortByVisibility = false, horizontal = false) { let top = scrollEl.scrollTop, bottom = top + scrollEl.clientHeight; let left = scrollEl.scrollLeft, right = left + scrollEl.clientWidth; - function isElementBottomBelowViewTop(view) { + function isElementBottomAfterViewTop(view) { let element = view.div; let elementBottom = element.offsetTop + element.clientTop + element.clientHeight; return elementBottom > top; } + function isElementRightAfterViewLeft(view) { + let element = view.div; + let elementRight = element.offsetLeft + element.clientLeft + element.clientWidth; + return elementRight > left; + } let visible = [], view, element; - let currentHeight, viewHeight, hiddenHeight, percentHeight; - let currentWidth, viewWidth; - let firstVisibleElementInd = views.length === 0 ? 0 : binarySearchFirstItem(views, isElementBottomBelowViewTop); + let currentHeight, viewHeight, viewBottom, hiddenHeight; + let currentWidth, viewWidth, viewRight, hiddenWidth; + let percentVisible; + let firstVisibleElementInd = views.length === 0 ? 0 : binarySearchFirstItem(views, horizontal ? isElementRightAfterViewLeft : isElementBottomAfterViewTop); + if (views.length > 0 && !horizontal) { + firstVisibleElementInd = backtrackBeforeAllVisibleElements(firstVisibleElementInd, views, top); + } + let lastEdge = horizontal ? right : -1; for (let i = firstVisibleElementInd, ii = views.length; i < ii; i++) { view = views[i]; element = view.div; + currentWidth = element.offsetLeft + element.clientLeft; currentHeight = element.offsetTop + element.clientTop; + viewWidth = element.clientWidth; viewHeight = element.clientHeight; - if (currentHeight > bottom) { + viewRight = currentWidth + viewWidth; + viewBottom = currentHeight + viewHeight; + if (lastEdge === -1) { + if (viewBottom >= bottom) { + lastEdge = viewBottom; + } + } else if ((horizontal ? currentWidth : currentHeight) > lastEdge) { break; } - currentWidth = element.offsetLeft + element.clientLeft; - viewWidth = element.clientWidth; - if (currentWidth + viewWidth < left || currentWidth > right) { + if (viewBottom <= top || currentHeight >= bottom || viewRight <= left || currentWidth >= right) { continue; } - hiddenHeight = Math.max(0, top - currentHeight) + Math.max(0, currentHeight + viewHeight - bottom); - percentHeight = (viewHeight - hiddenHeight) * 100 / viewHeight | 0; + hiddenHeight = Math.max(0, top - currentHeight) + Math.max(0, viewBottom - bottom); + hiddenWidth = Math.max(0, left - currentWidth) + Math.max(0, viewRight - right); + percentVisible = (viewHeight - hiddenHeight) * (viewWidth - hiddenWidth) * 100 / viewHeight / viewWidth | 0; visible.push({ id: view.id, x: currentWidth, y: currentHeight, view, - percent: percentHeight + percent: percentVisible }); } let first = visible[0]; @@ -543,6 +587,22 @@ class ProgressBar { this.bar.classList.remove('hidden'); } } +function moveToEndOfArray(arr, condition) { + const moved = [], + len = arr.length; + let write = 0; + for (let read = 0; read < len; ++read) { + if (condition(arr[read])) { + moved.push(arr[read]); + } else { + arr[write] = arr[read]; + ++write; + } + } + for (let read = 0; write < len; ++read, ++write) { + arr[write] = moved[read]; + } +} exports.CSS_UNITS = CSS_UNITS; exports.DEFAULT_SCALE_VALUE = DEFAULT_SCALE_VALUE; exports.DEFAULT_SCALE = DEFAULT_SCALE; @@ -565,6 +625,7 @@ exports.ProgressBar = ProgressBar; exports.getPDFFileNameFromURL = getPDFFileNameFromURL; exports.noContextMenuHandler = noContextMenuHandler; exports.parseQueryString = parseQueryString; +exports.backtrackBeforeAllVisibleElements = backtrackBeforeAllVisibleElements; exports.getVisibleElements = getVisibleElements; exports.roundToDivide = roundToDivide; exports.getPageSizeInches = getPageSizeInches; @@ -577,6 +638,7 @@ exports.normalizeWheelEventDelta = normalizeWheelEventDelta; exports.animationStarted = animationStarted; exports.WaitOnType = WaitOnType; exports.waitOnEventOrTimeout = waitOnEventOrTimeout; +exports.moveToEndOfArray = moveToEndOfArray; /***/ }), /* 1 */ @@ -844,37 +906,37 @@ var _pdf_cursor_tools = __webpack_require__(6); var _pdf_rendering_queue = __webpack_require__(3); -var _pdf_sidebar = __webpack_require__(12); +var _pdf_sidebar = __webpack_require__(13); var _app_options = __webpack_require__(7); var _dom_events = __webpack_require__(2); -var _overlay_manager = __webpack_require__(13); +var _overlay_manager = __webpack_require__(14); -var _password_prompt = __webpack_require__(14); +var _password_prompt = __webpack_require__(15); -var _pdf_attachment_viewer = __webpack_require__(15); +var _pdf_attachment_viewer = __webpack_require__(16); -var _pdf_document_properties = __webpack_require__(16); +var _pdf_document_properties = __webpack_require__(17); -var _pdf_find_bar = __webpack_require__(17); +var _pdf_find_bar = __webpack_require__(18); var _pdf_find_controller = __webpack_require__(9); -var _pdf_history = __webpack_require__(18); +var _pdf_history = __webpack_require__(19); var _pdf_link_service = __webpack_require__(5); -var _pdf_outline_viewer = __webpack_require__(19); +var _pdf_outline_viewer = __webpack_require__(20); -var _pdf_presentation_mode = __webpack_require__(20); +var _pdf_presentation_mode = __webpack_require__(21); -var _pdf_sidebar_resizer = __webpack_require__(21); +var _pdf_sidebar_resizer = __webpack_require__(22); -var _pdf_thumbnail_viewer = __webpack_require__(22); +var _pdf_thumbnail_viewer = __webpack_require__(23); -var _pdf_viewer = __webpack_require__(24); +var _pdf_viewer = __webpack_require__(25); var _secondary_toolbar = __webpack_require__(29); @@ -1017,6 +1079,10 @@ let PDFViewerApplication = { _app_options.AppOptions.set('disablePageLabels', value); }), preferences.get('enablePrintAutoRotate').then(function resolved(value) { _app_options.AppOptions.set('enablePrintAutoRotate', value); + }), preferences.get('scrollModeOnLoad').then(function resolved(value) { + _app_options.AppOptions.set('scrollModeOnLoad', value); + }), preferences.get('spreadModeOnLoad').then(function resolved(value) { + _app_options.AppOptions.set('spreadModeOnLoad', value); })]).catch(function (reason) {}); }, _parseHashParameters() { @@ -1534,16 +1600,26 @@ let PDFViewerApplication = { scrollLeft: '0', scrollTop: '0', rotation: null, - sidebarView: _pdf_sidebar.SidebarView.NONE + sidebarView: _pdf_sidebar.SidebarView.NONE, + scrollMode: null, + spreadMode: null }).catch(() => {}); Promise.all([storePromise, pageModePromise]).then(([values = {}, pageMode]) => { let hash = _app_options.AppOptions.get('defaultZoomValue') ? 'zoom=' + _app_options.AppOptions.get('defaultZoomValue') : null; let rotation = null; let sidebarView = _app_options.AppOptions.get('sidebarViewOnLoad'); + let scrollMode = _app_options.AppOptions.get('scrollModeOnLoad'); + let spreadMode = _app_options.AppOptions.get('spreadModeOnLoad'); if (values.exists && _app_options.AppOptions.get('showPreviousViewOnLoad')) { hash = 'page=' + values.page + '&zoom=' + (_app_options.AppOptions.get('defaultZoomValue') || values.zoom) + ',' + values.scrollLeft + ',' + values.scrollTop; rotation = parseInt(values.rotation, 10); sidebarView = sidebarView || values.sidebarView | 0; + if (values.scrollMode !== null) { + scrollMode = values.scrollMode; + } + if (values.spreadMode !== null) { + spreadMode = values.spreadMode; + } } if (pageMode && !_app_options.AppOptions.get('disablePageMode')) { sidebarView = sidebarView || apiPageModeToSidebarView(pageMode); @@ -1551,14 +1627,18 @@ let PDFViewerApplication = { return { hash, rotation, - sidebarView + sidebarView, + scrollMode, + spreadMode }; - }).then(({ hash, rotation, sidebarView }) => { + }).then(({ hash, rotation, sidebarView, scrollMode, spreadMode }) => { initialParams.bookmark = this.initialBookmark; initialParams.hash = hash; this.setInitialView(hash, { rotation, - sidebarView + sidebarView, + scrollMode, + spreadMode }); if (!this.isViewerEmbedded) { pdfViewer.focus(); @@ -1680,12 +1760,19 @@ let PDFViewerApplication = { }); }); }, - setInitialView(storedHash, { rotation, sidebarView } = {}) { + setInitialView(storedHash, values = {}) { + let { rotation, sidebarView, scrollMode, spreadMode } = values; let setRotation = angle => { if ((0, _ui_utils.isValidRotation)(angle)) { this.pdfViewer.pagesRotation = angle; } }; + if (Number.isInteger(scrollMode)) { + this.pdfViewer.setScrollMode(scrollMode); + } + if (Number.isInteger(spreadMode)) { + this.pdfViewer.setSpreadMode(spreadMode); + } this.isInitialViewSet = true; this.pdfSidebar.setInitialView(sidebarView); if (this.initialBookmark) { @@ -1794,6 +1881,10 @@ let PDFViewerApplication = { eventBus.on('scalechanged', webViewerScaleChanged); eventBus.on('rotatecw', webViewerRotateCw); eventBus.on('rotateccw', webViewerRotateCcw); + eventBus.on('switchscrollmode', webViewerSwitchScrollMode); + eventBus.on('scrollmodechanged', webViewerScrollModeChanged); + eventBus.on('switchspreadmode', webViewerSwitchSpreadMode); + eventBus.on('spreadmodechanged', webViewerSpreadModeChanged); eventBus.on('documentproperties', webViewerDocumentProperties); eventBus.on('find', webViewerFind); eventBus.on('findfromurlhash', webViewerFindFromUrlHash); @@ -1850,6 +1941,10 @@ let PDFViewerApplication = { eventBus.off('scalechanged', webViewerScaleChanged); eventBus.off('rotatecw', webViewerRotateCw); eventBus.off('rotateccw', webViewerRotateCcw); + eventBus.off('switchscrollmode', webViewerSwitchScrollMode); + eventBus.off('scrollmodechanged', webViewerScrollModeChanged); + eventBus.off('switchspreadmode', webViewerSwitchSpreadMode); + eventBus.off('spreadmodechanged', webViewerSpreadModeChanged); eventBus.off('documentproperties', webViewerDocumentProperties); eventBus.off('find', webViewerFind); eventBus.off('findfromurlhash', webViewerFindFromUrlHash); @@ -2056,6 +2151,18 @@ function webViewerUpdateViewarea(evt) { let loading = currentPage.renderingState !== _pdf_rendering_queue.RenderingStates.FINISHED; PDFViewerApplication.toolbar.updateLoadingIndicatorState(loading); } +function webViewerScrollModeChanged(evt) { + let store = PDFViewerApplication.store; + if (store && PDFViewerApplication.isInitialViewSet) { + store.set('scrollMode', evt.mode).catch(function () {}); + } +} +function webViewerSpreadModeChanged(evt) { + let store = PDFViewerApplication.store; + if (store && PDFViewerApplication.isInitialViewSet) { + store.set('spreadMode', evt.mode).catch(function () {}); + } +} function webViewerResize() { let { pdfDocument, pdfViewer } = PDFViewerApplication; if (!pdfDocument) { @@ -2128,6 +2235,12 @@ function webViewerRotateCw() { function webViewerRotateCcw() { PDFViewerApplication.rotatePages(-90); } +function webViewerSwitchScrollMode(evt) { + PDFViewerApplication.pdfViewer.setScrollMode(evt.mode); +} +function webViewerSwitchSpreadMode(evt) { + PDFViewerApplication.pdfViewer.setSpreadMode(evt.mode); +} function webViewerDocumentProperties() { PDFViewerApplication.pdfDocumentProperties.open(); } @@ -2324,23 +2437,29 @@ function webViewerKeyDown(evt) { } } if (cmd === 0) { + let turnPage = 0, + turnOnlyIfPageFit = false; switch (evt.keyCode) { case 38: case 33: + if (pdfViewer.isVerticalScrollbarEnabled) { + turnOnlyIfPageFit = true; + } + turnPage = -1; + break; case 8: - if (!isViewerInPresentationMode && pdfViewer.currentScaleValue !== 'page-fit') { - break; + if (!isViewerInPresentationMode) { + turnOnlyIfPageFit = true; } + turnPage = -1; + break; case 37: if (pdfViewer.isHorizontalScrollbarEnabled) { - break; + turnOnlyIfPageFit = true; } case 75: case 80: - if (PDFViewerApplication.page > 1) { - PDFViewerApplication.page--; - } - handled = true; + turnPage = -1; break; case 27: if (PDFViewerApplication.secondaryToolbar.isOpen) { @@ -2352,23 +2471,27 @@ function webViewerKeyDown(evt) { handled = true; } break; - case 13: case 40: case 34: + if (pdfViewer.isVerticalScrollbarEnabled) { + turnOnlyIfPageFit = true; + } + turnPage = 1; + break; + case 13: case 32: - if (!isViewerInPresentationMode && pdfViewer.currentScaleValue !== 'page-fit') { - break; + if (!isViewerInPresentationMode) { + turnOnlyIfPageFit = true; } + turnPage = 1; + break; case 39: if (pdfViewer.isHorizontalScrollbarEnabled) { - break; + turnOnlyIfPageFit = true; } case 74: case 78: - if (PDFViewerApplication.page < PDFViewerApplication.pagesCount) { - PDFViewerApplication.page++; - } - handled = true; + turnPage = 1; break; case 36: if (isViewerInPresentationMode || PDFViewerApplication.page > 1) { @@ -2394,6 +2517,18 @@ function webViewerKeyDown(evt) { PDFViewerApplication.rotatePages(90); break; } + if (turnPage !== 0 && (!turnOnlyIfPageFit || pdfViewer.currentScaleValue === 'page-fit')) { + if (turnPage > 0) { + if (PDFViewerApplication.page < PDFViewerApplication.pagesCount) { + PDFViewerApplication.page++; + } + } else { + if (PDFViewerApplication.page > 1) { + PDFViewerApplication.page--; + } + } + handled = true; + } } if (cmd === 4) { switch (evt.keyCode) { @@ -2796,7 +2931,7 @@ Object.defineProperty(exports, "__esModule", { }); exports.PDFCursorTools = exports.CursorTool = undefined; -var _grab_to_pan = __webpack_require__(11); +var _grab_to_pan = __webpack_require__(12); const CursorTool = { SELECT: 0, @@ -3465,1131 +3600,900 @@ exports.PDFFindController = PDFFindController; "use strict"; -; -let pdfjsWebApp, pdfjsWebAppOptions; -{ - pdfjsWebApp = __webpack_require__(4); - pdfjsWebAppOptions = __webpack_require__(7); -} -{ - __webpack_require__(32); - __webpack_require__(35); -} -; -; -; -function getViewerConfiguration() { - return { - appContainer: document.body, - mainContainer: document.getElementById('viewerContainer'), - viewerContainer: document.getElementById('viewer'), - eventBus: null, - toolbar: { - container: document.getElementById('toolbarViewer'), - numPages: document.getElementById('numPages'), - pageNumber: document.getElementById('pageNumber'), - scaleSelectContainer: document.getElementById('scaleSelectContainer'), - scaleSelect: document.getElementById('scaleSelect'), - customScaleOption: document.getElementById('customScaleOption'), - previous: document.getElementById('previous'), - next: document.getElementById('next'), - zoomIn: document.getElementById('zoomIn'), - zoomOut: document.getElementById('zoomOut'), - viewFind: document.getElementById('viewFind'), - openFile: document.getElementById('openFile'), - print: document.getElementById('print'), - presentationModeButton: document.getElementById('presentationMode'), - download: document.getElementById('download'), - viewBookmark: document.getElementById('viewBookmark') - }, - secondaryToolbar: { - toolbar: document.getElementById('secondaryToolbar'), - toggleButton: document.getElementById('secondaryToolbarToggle'), - toolbarButtonContainer: document.getElementById('secondaryToolbarButtonContainer'), - presentationModeButton: document.getElementById('secondaryPresentationMode'), - openFileButton: document.getElementById('secondaryOpenFile'), - printButton: document.getElementById('secondaryPrint'), - downloadButton: document.getElementById('secondaryDownload'), - viewBookmarkButton: document.getElementById('secondaryViewBookmark'), - firstPageButton: document.getElementById('firstPage'), - lastPageButton: document.getElementById('lastPage'), - pageRotateCwButton: document.getElementById('pageRotateCw'), - pageRotateCcwButton: document.getElementById('pageRotateCcw'), - cursorSelectToolButton: document.getElementById('cursorSelectTool'), - cursorHandToolButton: document.getElementById('cursorHandTool'), - documentPropertiesButton: document.getElementById('documentProperties') - }, - fullscreen: { - contextFirstPage: document.getElementById('contextFirstPage'), - contextLastPage: document.getElementById('contextLastPage'), - contextPageRotateCw: document.getElementById('contextPageRotateCw'), - contextPageRotateCcw: document.getElementById('contextPageRotateCcw') - }, - sidebar: { - outerContainer: document.getElementById('outerContainer'), - viewerContainer: document.getElementById('viewerContainer'), - toggleButton: document.getElementById('sidebarToggle'), - thumbnailButton: document.getElementById('viewThumbnail'), - outlineButton: document.getElementById('viewOutline'), - attachmentsButton: document.getElementById('viewAttachments'), - thumbnailView: document.getElementById('thumbnailView'), - outlineView: document.getElementById('outlineView'), - attachmentsView: document.getElementById('attachmentsView') - }, - sidebarResizer: { - outerContainer: document.getElementById('outerContainer'), - resizer: document.getElementById('sidebarResizer') - }, - findBar: { - bar: document.getElementById('findbar'), - toggleButton: document.getElementById('viewFind'), - findField: document.getElementById('findInput'), - highlightAllCheckbox: document.getElementById('findHighlightAll'), - caseSensitiveCheckbox: document.getElementById('findMatchCase'), - findMsg: document.getElementById('findMsg'), - findResultsCount: document.getElementById('findResultsCount'), - findStatusIcon: document.getElementById('findStatusIcon'), - findPreviousButton: document.getElementById('findPrevious'), - findNextButton: document.getElementById('findNext') - }, - passwordOverlay: { - overlayName: 'passwordOverlay', - container: document.getElementById('passwordOverlay'), - label: document.getElementById('passwordText'), - input: document.getElementById('password'), - submitButton: document.getElementById('passwordSubmit'), - cancelButton: document.getElementById('passwordCancel') - }, - documentProperties: { - overlayName: 'documentPropertiesOverlay', - container: document.getElementById('documentPropertiesOverlay'), - closeButton: document.getElementById('documentPropertiesClose'), - fields: { - 'fileName': document.getElementById('fileNameField'), - 'fileSize': document.getElementById('fileSizeField'), - 'title': document.getElementById('titleField'), - 'author': document.getElementById('authorField'), - 'subject': document.getElementById('subjectField'), - 'keywords': document.getElementById('keywordsField'), - 'creationDate': document.getElementById('creationDateField'), - 'modificationDate': document.getElementById('modificationDateField'), - 'creator': document.getElementById('creatorField'), - 'producer': document.getElementById('producerField'), - 'version': document.getElementById('versionField'), - 'pageCount': document.getElementById('pageCountField'), - 'pageSize': document.getElementById('pageSizeField') - } - }, - errorWrapper: { - container: document.getElementById('errorWrapper'), - errorMessage: document.getElementById('errorMessage'), - closeButton: document.getElementById('errorClose'), - errorMoreInfo: document.getElementById('errorMoreInfo'), - moreInfoButton: document.getElementById('errorShowMore'), - lessInfoButton: document.getElementById('errorShowLess') - }, - printContainer: document.getElementById('printContainer'), - openFileInputName: 'fileInput', - debuggerScriptPath: './debugger.js' - }; -} -function webViewerLoad() { - let config = getViewerConfiguration(); - window.PDFViewerApplication = pdfjsWebApp.PDFViewerApplication; - window.PDFViewerApplicationOptions = pdfjsWebAppOptions.AppOptions; - pdfjsWebApp.PDFViewerApplication.run(config); -} -if (document.readyState === 'interactive' || document.readyState === 'complete') { - webViewerLoad(); -} else { - document.addEventListener('DOMContentLoaded', webViewerLoad, true); -} +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.SpreadMode = exports.ScrollMode = exports.BaseViewer = undefined; -/***/ }), -/* 11 */ -/***/ (function(module, exports, __webpack_require__) { +var _ui_utils = __webpack_require__(0); -"use strict"; +var _pdf_rendering_queue = __webpack_require__(3); +var _annotation_layer_builder = __webpack_require__(26); -Object.defineProperty(exports, "__esModule", { - value: true -}); -function GrabToPan(options) { - this.element = options.element; - this.document = options.element.ownerDocument; - if (typeof options.ignoreTarget === 'function') { - this.ignoreTarget = options.ignoreTarget; - } - this.onActiveChanged = options.onActiveChanged; - this.activate = this.activate.bind(this); - this.deactivate = this.deactivate.bind(this); - this.toggle = this.toggle.bind(this); - this._onmousedown = this._onmousedown.bind(this); - this._onmousemove = this._onmousemove.bind(this); - this._endPan = this._endPan.bind(this); - var overlay = this.overlay = document.createElement('div'); - overlay.className = 'grab-to-pan-grabbing'; -} -GrabToPan.prototype = { - CSS_CLASS_GRAB: 'grab-to-pan-grab', - activate: function GrabToPan_activate() { - if (!this.active) { - this.active = true; - this.element.addEventListener('mousedown', this._onmousedown, true); - this.element.classList.add(this.CSS_CLASS_GRAB); - if (this.onActiveChanged) { - this.onActiveChanged(true); - } - } - }, - deactivate: function GrabToPan_deactivate() { - if (this.active) { - this.active = false; - this.element.removeEventListener('mousedown', this._onmousedown, true); - this._endPan(); - this.element.classList.remove(this.CSS_CLASS_GRAB); - if (this.onActiveChanged) { - this.onActiveChanged(false); - } - } - }, - toggle: function GrabToPan_toggle() { - if (this.active) { - this.deactivate(); - } else { - this.activate(); +var _pdfjsLib = __webpack_require__(1); + +var _dom_events = __webpack_require__(2); + +var _pdf_page_view = __webpack_require__(27); + +var _pdf_link_service = __webpack_require__(5); + +var _text_layer_builder = __webpack_require__(28); + +const DEFAULT_CACHE_SIZE = 10; +const ScrollMode = { + VERTICAL: 0, + HORIZONTAL: 1, + WRAPPED: 2 +}; +const SpreadMode = { + NONE: 0, + ODD: 1, + EVEN: 2 +}; +function PDFPageViewBuffer(size) { + let data = []; + this.push = function (view) { + let i = data.indexOf(view); + if (i >= 0) { + data.splice(i, 1); } - }, - ignoreTarget: function GrabToPan_ignoreTarget(node) { - return node[matchesSelector]('a[href], a[href] *, input, textarea, button, button *, select, option'); - }, - _onmousedown: function GrabToPan__onmousedown(event) { - if (event.button !== 0 || this.ignoreTarget(event.target)) { - return; + data.push(view); + if (data.length > size) { + data.shift().destroy(); } - if (event.originalTarget) { - try { - event.originalTarget.tagName; - } catch (e) { - return; + }; + this.resize = function (newSize, pagesToKeep) { + size = newSize; + if (pagesToKeep) { + const pageIdsToKeep = new Set(); + for (let i = 0, iMax = pagesToKeep.length; i < iMax; ++i) { + pageIdsToKeep.add(pagesToKeep[i].id); } - } - this.scrollLeftStart = this.element.scrollLeft; - this.scrollTopStart = this.element.scrollTop; - this.clientXStart = event.clientX; - this.clientYStart = event.clientY; - this.document.addEventListener('mousemove', this._onmousemove, true); - this.document.addEventListener('mouseup', this._endPan, true); - this.element.addEventListener('scroll', this._endPan, true); - event.preventDefault(); - event.stopPropagation(); - var focusedElement = document.activeElement; - if (focusedElement && !focusedElement.contains(event.target)) { - focusedElement.blur(); - } - }, - _onmousemove: function GrabToPan__onmousemove(event) { - this.element.removeEventListener('scroll', this._endPan, true); - if (isLeftMouseReleased(event)) { - this._endPan(); - return; - } - var xDiff = event.clientX - this.clientXStart; - var yDiff = event.clientY - this.clientYStart; - var scrollTop = this.scrollTopStart - yDiff; - var scrollLeft = this.scrollLeftStart - xDiff; - if (this.element.scrollTo) { - this.element.scrollTo({ - top: scrollTop, - left: scrollLeft, - behavior: 'instant' + (0, _ui_utils.moveToEndOfArray)(data, function (page) { + return pageIdsToKeep.has(page.id); }); - } else { - this.element.scrollTop = scrollTop; - this.element.scrollLeft = scrollLeft; } - if (!this.overlay.parentNode) { - document.body.appendChild(this.overlay); + while (data.length > size) { + data.shift().destroy(); } - }, - _endPan: function GrabToPan__endPan() { - this.element.removeEventListener('scroll', this._endPan, true); - this.document.removeEventListener('mousemove', this._onmousemove, true); - this.document.removeEventListener('mouseup', this._endPan, true); - this.overlay.remove(); - } -}; -var matchesSelector; -['webkitM', 'mozM', 'msM', 'oM', 'm'].some(function (prefix) { - var name = prefix + 'atches'; - if (name in document.documentElement) { - matchesSelector = name; - } - name += 'Selector'; - if (name in document.documentElement) { - matchesSelector = name; - } - return matchesSelector; -}); -var isNotIEorIsIE10plus = !document.documentMode || document.documentMode > 9; -var chrome = window.chrome; -var isChrome15OrOpera15plus = chrome && (chrome.webstore || chrome.app); -var isSafari6plus = /Apple/.test(navigator.vendor) && /Version\/([6-9]\d*|[1-5]\d+)/.test(navigator.userAgent); -function isLeftMouseReleased(event) { - if ('buttons' in event && isNotIEorIsIE10plus) { - return !(event.buttons & 1); + }; +} +function isSameScale(oldScale, newScale) { + if (newScale === oldScale) { + return true; } - if (isChrome15OrOpera15plus || isSafari6plus) { - return event.which === 0; + if (Math.abs(newScale - oldScale) < 1e-15) { + return true; } + return false; } -exports.GrabToPan = GrabToPan; - -/***/ }), -/* 12 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.PDFSidebar = exports.SidebarView = undefined; - -var _ui_utils = __webpack_require__(0); - -var _pdf_rendering_queue = __webpack_require__(3); - -const UI_NOTIFICATION_CLASS = 'pdfSidebarNotification'; -const SidebarView = { - NONE: 0, - THUMBS: 1, - OUTLINE: 2, - ATTACHMENTS: 3 -}; -class PDFSidebar { - constructor(options, l10n = _ui_utils.NullL10n) { - this.isOpen = false; - this.active = SidebarView.THUMBS; - this.isInitialViewSet = false; - this.onToggled = null; - this.pdfViewer = options.pdfViewer; - this.pdfThumbnailViewer = options.pdfThumbnailViewer; - this.pdfOutlineViewer = options.pdfOutlineViewer; - this.outerContainer = options.outerContainer; - this.viewerContainer = options.viewerContainer; - this.eventBus = options.eventBus; - this.toggleButton = options.toggleButton; - this.thumbnailButton = options.thumbnailButton; - this.outlineButton = options.outlineButton; - this.attachmentsButton = options.attachmentsButton; - this.thumbnailView = options.thumbnailView; - this.outlineView = options.outlineView; - this.attachmentsView = options.attachmentsView; - this.disableNotification = options.disableNotification || false; - this.l10n = l10n; - this._addEventListeners(); +class BaseViewer { + constructor(options) { + if (this.constructor === BaseViewer) { + throw new Error('Cannot initialize BaseViewer.'); + } + this._name = this.constructor.name; + this.container = options.container; + this.viewer = options.viewer || options.container.firstElementChild; + this.eventBus = options.eventBus || (0, _dom_events.getGlobalEventBus)(); + this.linkService = options.linkService || new _pdf_link_service.SimpleLinkService(); + this.downloadManager = options.downloadManager || null; + this.removePageBorders = options.removePageBorders || false; + this.textLayerMode = Number.isInteger(options.textLayerMode) ? options.textLayerMode : _ui_utils.TextLayerMode.ENABLE; + this.enhanceTextSelection = options.enhanceTextSelection || false; + this.imageResourcesPath = options.imageResourcesPath || ''; + this.renderInteractiveForms = options.renderInteractiveForms || false; + this.enablePrintAutoRotate = options.enablePrintAutoRotate || false; + this.renderer = options.renderer || _ui_utils.RendererType.CANVAS; + this.enableWebGL = options.enableWebGL || false; + this.useOnlyCssZoom = options.useOnlyCssZoom || false; + this.maxCanvasPixels = options.maxCanvasPixels; + this.l10n = options.l10n || _ui_utils.NullL10n; + this.scrollMode = options.scrollMode || ScrollMode.VERTICAL; + this.spreadMode = options.spreadMode || SpreadMode.NONE; + this.defaultRenderingQueue = !options.renderingQueue; + if (this.defaultRenderingQueue) { + this.renderingQueue = new _pdf_rendering_queue.PDFRenderingQueue(); + this.renderingQueue.setViewer(this); + } else { + this.renderingQueue = options.renderingQueue; + } + this.scroll = (0, _ui_utils.watchScroll)(this.container, this._scrollUpdate.bind(this)); + this.presentationModeState = _ui_utils.PresentationModeState.UNKNOWN; + this._resetView(); + if (this.removePageBorders) { + this.viewer.classList.add('removePageBorders'); + } + this._updateScrollModeClasses(); } - reset() { - this.isInitialViewSet = false; - this._hideUINotification(null); - this.switchView(SidebarView.THUMBS); - this.outlineButton.disabled = false; - this.attachmentsButton.disabled = false; + get pagesCount() { + return this._pages.length; } - get visibleView() { - return this.isOpen ? this.active : SidebarView.NONE; + getPageView(index) { + return this._pages[index]; } - get isThumbnailViewVisible() { - return this.isOpen && this.active === SidebarView.THUMBS; + get pageViewsReady() { + return this._pageViewsReady; } - get isOutlineViewVisible() { - return this.isOpen && this.active === SidebarView.OUTLINE; + get currentPageNumber() { + return this._currentPageNumber; } - get isAttachmentsViewVisible() { - return this.isOpen && this.active === SidebarView.ATTACHMENTS; + set currentPageNumber(val) { + if (!Number.isInteger(val)) { + throw new Error('Invalid page number.'); + } + if (!this.pdfDocument) { + return; + } + this._setCurrentPageNumber(val, true); } - setInitialView(view = SidebarView.NONE) { - if (this.isInitialViewSet) { + _setCurrentPageNumber(val, resetCurrentPageView = false) { + if (this._currentPageNumber === val) { + if (resetCurrentPageView) { + this._resetCurrentPageView(); + } return; } - this.isInitialViewSet = true; - if (this.isOpen && view === SidebarView.NONE) { - this._dispatchEvent(); + if (!(0 < val && val <= this.pagesCount)) { + console.error(`${this._name}._setCurrentPageNumber: "${val}" is out of bounds.`); return; } - let isViewPreserved = view === this.visibleView; - this.switchView(view, true); - if (isViewPreserved) { - this._dispatchEvent(); + let arg = { + source: this, + pageNumber: val, + pageLabel: this._pageLabels && this._pageLabels[val - 1] + }; + this._currentPageNumber = val; + this.eventBus.dispatch('pagechanging', arg); + this.eventBus.dispatch('pagechange', arg); + if (resetCurrentPageView) { + this._resetCurrentPageView(); } } - switchView(view, forceOpen = false) { - if (view === SidebarView.NONE) { - this.close(); - return; + get currentPageLabel() { + return this._pageLabels && this._pageLabels[this._currentPageNumber - 1]; + } + set currentPageLabel(val) { + let pageNumber = val | 0; + if (this._pageLabels) { + let i = this._pageLabels.indexOf(val); + if (i >= 0) { + pageNumber = i + 1; + } } - let isViewChanged = view !== this.active; - let shouldForceRendering = false; - switch (view) { - case SidebarView.THUMBS: - this.thumbnailButton.classList.add('toggled'); - this.outlineButton.classList.remove('toggled'); - this.attachmentsButton.classList.remove('toggled'); - this.thumbnailView.classList.remove('hidden'); - this.outlineView.classList.add('hidden'); - this.attachmentsView.classList.add('hidden'); - if (this.isOpen && isViewChanged) { - this._updateThumbnailViewer(); - shouldForceRendering = true; - } - break; - case SidebarView.OUTLINE: - if (this.outlineButton.disabled) { - return; - } - this.thumbnailButton.classList.remove('toggled'); - this.outlineButton.classList.add('toggled'); - this.attachmentsButton.classList.remove('toggled'); - this.thumbnailView.classList.add('hidden'); - this.outlineView.classList.remove('hidden'); - this.attachmentsView.classList.add('hidden'); - break; - case SidebarView.ATTACHMENTS: - if (this.attachmentsButton.disabled) { - return; - } - this.thumbnailButton.classList.remove('toggled'); - this.outlineButton.classList.remove('toggled'); - this.attachmentsButton.classList.add('toggled'); - this.thumbnailView.classList.add('hidden'); - this.outlineView.classList.add('hidden'); - this.attachmentsView.classList.remove('hidden'); - break; - default: - console.error('PDFSidebar_switchView: "' + view + '" is an unsupported value.'); - return; + this.currentPageNumber = pageNumber; + } + get currentScale() { + return this._currentScale !== _ui_utils.UNKNOWN_SCALE ? this._currentScale : _ui_utils.DEFAULT_SCALE; + } + set currentScale(val) { + if (isNaN(val)) { + throw new Error('Invalid numeric scale'); } - this.active = view | 0; - if (forceOpen && !this.isOpen) { - this.open(); + if (!this.pdfDocument) { return; } - if (shouldForceRendering) { - this._forceRendering(); - } - if (isViewChanged) { - this._dispatchEvent(); - } - this._hideUINotification(this.active); + this._setScale(val, false); } - open() { - if (this.isOpen) { - return; - } - this.isOpen = true; - this.toggleButton.classList.add('toggled'); - this.outerContainer.classList.add('sidebarMoving'); - this.outerContainer.classList.add('sidebarOpen'); - if (this.active === SidebarView.THUMBS) { - this._updateThumbnailViewer(); - } - this._forceRendering(); - this._dispatchEvent(); - this._hideUINotification(this.active); + get currentScaleValue() { + return this._currentScaleValue; } - close() { - if (!this.isOpen) { + set currentScaleValue(val) { + if (!this.pdfDocument) { return; } - this.isOpen = false; - this.toggleButton.classList.remove('toggled'); - this.outerContainer.classList.add('sidebarMoving'); - this.outerContainer.classList.remove('sidebarOpen'); - this._forceRendering(); - this._dispatchEvent(); - } - toggle() { - if (this.isOpen) { - this.close(); - } else { - this.open(); - } - } - _dispatchEvent() { - this.eventBus.dispatch('sidebarviewchanged', { - source: this, - view: this.visibleView - }); + this._setScale(val, false); } - _forceRendering() { - if (this.onToggled) { - this.onToggled(); - } else { - this.pdfViewer.forceRendering(); - this.pdfThumbnailViewer.forceRendering(); - } + get pagesRotation() { + return this._pagesRotation; } - _updateThumbnailViewer() { - let { pdfViewer, pdfThumbnailViewer } = this; - let pagesCount = pdfViewer.pagesCount; - for (let pageIndex = 0; pageIndex < pagesCount; pageIndex++) { - let pageView = pdfViewer.getPageView(pageIndex); - if (pageView && pageView.renderingState === _pdf_rendering_queue.RenderingStates.FINISHED) { - let thumbnailView = pdfThumbnailViewer.getThumbnail(pageIndex); - thumbnailView.setImage(pageView); - } + set pagesRotation(rotation) { + if (!(0, _ui_utils.isValidRotation)(rotation)) { + throw new Error('Invalid pages rotation angle.'); } - pdfThumbnailViewer.scrollThumbnailIntoView(pdfViewer.currentPageNumber); - } - _showUINotification(view) { - if (this.disableNotification) { + if (!this.pdfDocument) { return; } - this.l10n.get('toggle_sidebar_notification.title', null, 'Toggle Sidebar (document contains outline/attachments)').then(msg => { - this.toggleButton.title = msg; - }); - if (!this.isOpen) { - this.toggleButton.classList.add(UI_NOTIFICATION_CLASS); - } else if (view === this.active) { + if (this._pagesRotation === rotation) { return; } - switch (view) { - case SidebarView.OUTLINE: - this.outlineButton.classList.add(UI_NOTIFICATION_CLASS); - break; - case SidebarView.ATTACHMENTS: - this.attachmentsButton.classList.add(UI_NOTIFICATION_CLASS); - break; + this._pagesRotation = rotation; + let pageNumber = this._currentPageNumber; + for (let i = 0, ii = this._pages.length; i < ii; i++) { + let pageView = this._pages[i]; + pageView.update(pageView.scale, rotation); } - } - _hideUINotification(view) { - if (this.disableNotification) { - return; + if (this._currentScaleValue) { + this._setScale(this._currentScaleValue, true); } - let removeNotification = view => { - switch (view) { - case SidebarView.OUTLINE: - this.outlineButton.classList.remove(UI_NOTIFICATION_CLASS); - break; - case SidebarView.ATTACHMENTS: - this.attachmentsButton.classList.remove(UI_NOTIFICATION_CLASS); - break; - } - }; - if (!this.isOpen && view !== null) { - return; + this.eventBus.dispatch('rotationchanging', { + source: this, + pagesRotation: rotation, + pageNumber + }); + if (this.defaultRenderingQueue) { + this.update(); } - this.toggleButton.classList.remove(UI_NOTIFICATION_CLASS); - if (view !== null) { - removeNotification(view); - return; + } + get _setDocumentViewerElement() { + throw new Error('Not implemented: _setDocumentViewerElement'); + } + setDocument(pdfDocument) { + if (this.pdfDocument) { + this._cancelRendering(); + this._resetView(); } - for (view in SidebarView) { - removeNotification(SidebarView[view]); + this.pdfDocument = pdfDocument; + if (!pdfDocument) { + return; } - this.l10n.get('toggle_sidebar.title', null, 'Toggle Sidebar').then(msg => { - this.toggleButton.title = msg; - }); - } - _addEventListeners() { - this.viewerContainer.addEventListener('transitionend', evt => { - if (evt.target === this.viewerContainer) { - this.outerContainer.classList.remove('sidebarMoving'); - } - }); - this.thumbnailButton.addEventListener('click', () => { - this.switchView(SidebarView.THUMBS); - }); - this.outlineButton.addEventListener('click', () => { - this.switchView(SidebarView.OUTLINE); - }); - this.outlineButton.addEventListener('dblclick', () => { - this.pdfOutlineViewer.toggleOutlineTree(); - }); - this.attachmentsButton.addEventListener('click', () => { - this.switchView(SidebarView.ATTACHMENTS); - }); - this.eventBus.on('outlineloaded', evt => { - let outlineCount = evt.outlineCount; - this.outlineButton.disabled = !outlineCount; - if (outlineCount) { - this._showUINotification(SidebarView.OUTLINE); - } else if (this.active === SidebarView.OUTLINE) { - this.switchView(SidebarView.THUMBS); - } - }); - this.eventBus.on('attachmentsloaded', evt => { - if (evt.attachmentsCount) { - this.attachmentsButton.disabled = false; - this._showUINotification(SidebarView.ATTACHMENTS); - return; - } - Promise.resolve().then(() => { - if (this.attachmentsView.hasChildNodes()) { - return; - } - this.attachmentsButton.disabled = true; - if (this.active === SidebarView.ATTACHMENTS) { - this.switchView(SidebarView.THUMBS); - } + let pagesCount = pdfDocument.numPages; + let pagesCapability = (0, _pdfjsLib.createPromiseCapability)(); + this.pagesPromise = pagesCapability.promise; + pagesCapability.promise.then(() => { + this._pageViewsReady = true; + this.eventBus.dispatch('pagesloaded', { + source: this, + pagesCount }); }); - this.eventBus.on('presentationmodechanged', evt => { - if (!evt.active && !evt.switchInProgress && this.isThumbnailViewVisible) { - this._updateThumbnailViewer(); - } - }); - } -} -exports.SidebarView = SidebarView; -exports.PDFSidebar = PDFSidebar; - -/***/ }), -/* 13 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); -class OverlayManager { - constructor() { - this._overlays = {}; - this._active = null; - this._keyDownBound = this._keyDown.bind(this); - } - get active() { - return this._active; - } - register(name, element, callerCloseMethod = null, canForceClose = false) { - return new Promise(resolve => { - let container; - if (!name || !element || !(container = element.parentNode)) { - throw new Error('Not enough parameters.'); - } else if (this._overlays[name]) { - throw new Error('The overlay is already registered.'); - } - this._overlays[name] = { - element, - container, - callerCloseMethod, - canForceClose + let isOnePageRenderedResolved = false; + let onePageRenderedCapability = (0, _pdfjsLib.createPromiseCapability)(); + this.onePageRendered = onePageRenderedCapability.promise; + let bindOnAfterAndBeforeDraw = pageView => { + pageView.onBeforeDraw = () => { + this._buffer.push(pageView); }; - resolve(); - }); - } - unregister(name) { - return new Promise(resolve => { - if (!this._overlays[name]) { - throw new Error('The overlay does not exist.'); - } else if (this._active === name) { - throw new Error('The overlay cannot be removed while it is active.'); + pageView.onAfterDraw = () => { + if (!isOnePageRenderedResolved) { + isOnePageRenderedResolved = true; + onePageRenderedCapability.resolve(); + } + }; + }; + let firstPagePromise = pdfDocument.getPage(1); + this.firstPagePromise = firstPagePromise; + firstPagePromise.then(pdfPage => { + let scale = this.currentScale; + let viewport = pdfPage.getViewport(scale * _ui_utils.CSS_UNITS); + for (let pageNum = 1; pageNum <= pagesCount; ++pageNum) { + let textLayerFactory = null; + if (this.textLayerMode !== _ui_utils.TextLayerMode.DISABLE) { + textLayerFactory = this; + } + let pageView = new _pdf_page_view.PDFPageView({ + container: this._setDocumentViewerElement, + eventBus: this.eventBus, + id: pageNum, + scale, + defaultViewport: viewport.clone(), + renderingQueue: this.renderingQueue, + textLayerFactory, + textLayerMode: this.textLayerMode, + annotationLayerFactory: this, + imageResourcesPath: this.imageResourcesPath, + renderInteractiveForms: this.renderInteractiveForms, + renderer: this.renderer, + enableWebGL: this.enableWebGL, + useOnlyCssZoom: this.useOnlyCssZoom, + maxCanvasPixels: this.maxCanvasPixels, + l10n: this.l10n + }); + bindOnAfterAndBeforeDraw(pageView); + this._pages.push(pageView); } - delete this._overlays[name]; - resolve(); - }); - } - open(name) { - return new Promise(resolve => { - if (!this._overlays[name]) { - throw new Error('The overlay does not exist.'); - } else if (this._active) { - if (this._overlays[name].canForceClose) { - this._closeThroughCaller(); - } else if (this._active === name) { - throw new Error('The overlay is already active.'); - } else { - throw new Error('Another overlay is currently active.'); + if (this.spreadMode !== SpreadMode.NONE) { + this._regroupSpreads(); + } + onePageRenderedCapability.promise.then(() => { + if (pdfDocument.loadingParams['disableAutoFetch']) { + pagesCapability.resolve(); + return; + } + let getPagesLeft = pagesCount; + for (let pageNum = 1; pageNum <= pagesCount; ++pageNum) { + pdfDocument.getPage(pageNum).then(pdfPage => { + let pageView = this._pages[pageNum - 1]; + if (!pageView.pdfPage) { + pageView.setPdfPage(pdfPage); + } + this.linkService.cachePageRef(pageNum, pdfPage.ref); + if (--getPagesLeft === 0) { + pagesCapability.resolve(); + } + }, reason => { + console.error(`Unable to get page ${pageNum} to initialize viewer`, reason); + if (--getPagesLeft === 0) { + pagesCapability.resolve(); + } + }); } + }); + this.eventBus.dispatch('pagesinit', { source: this }); + if (this.defaultRenderingQueue) { + this.update(); } - this._active = name; - this._overlays[this._active].element.classList.remove('hidden'); - this._overlays[this._active].container.classList.remove('hidden'); - window.addEventListener('keydown', this._keyDownBound); - resolve(); - }); - } - close(name) { - return new Promise(resolve => { - if (!this._overlays[name]) { - throw new Error('The overlay does not exist.'); - } else if (!this._active) { - throw new Error('The overlay is currently not active.'); - } else if (this._active !== name) { - throw new Error('Another overlay is currently active.'); + if (this.findController) { + this.findController.resolveFirstPage(); } - this._overlays[this._active].container.classList.add('hidden'); - this._overlays[this._active].element.classList.add('hidden'); - this._active = null; - window.removeEventListener('keydown', this._keyDownBound); - resolve(); + }).catch(reason => { + console.error('Unable to initialize viewer', reason); }); } - _keyDown(evt) { - if (this._active && evt.keyCode === 27) { - this._closeThroughCaller(); - evt.preventDefault(); + setPageLabels(labels) { + if (!this.pdfDocument) { + return; } - } - _closeThroughCaller() { - if (this._overlays[this._active].callerCloseMethod) { - this._overlays[this._active].callerCloseMethod(); + if (!labels) { + this._pageLabels = null; + } else if (!(labels instanceof Array && this.pdfDocument.numPages === labels.length)) { + this._pageLabels = null; + console.error(`${this._name}.setPageLabels: Invalid page labels.`); + } else { + this._pageLabels = labels; } - if (this._active) { - this.close(this._active); + for (let i = 0, ii = this._pages.length; i < ii; i++) { + let pageView = this._pages[i]; + let label = this._pageLabels && this._pageLabels[i]; + pageView.setPageLabel(label); } } -} -exports.OverlayManager = OverlayManager; - -/***/ }), -/* 14 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.PasswordPrompt = undefined; - -var _ui_utils = __webpack_require__(0); - -var _pdfjsLib = __webpack_require__(1); - -class PasswordPrompt { - constructor(options, overlayManager, l10n = _ui_utils.NullL10n) { - this.overlayName = options.overlayName; - this.container = options.container; - this.label = options.label; - this.input = options.input; - this.submitButton = options.submitButton; - this.cancelButton = options.cancelButton; - this.overlayManager = overlayManager; - this.l10n = l10n; - this.updateCallback = null; - this.reason = null; - this.submitButton.addEventListener('click', this.verify.bind(this)); - this.cancelButton.addEventListener('click', this.close.bind(this)); - this.input.addEventListener('keydown', e => { - if (e.keyCode === 13) { - this.verify(); - } - }); - this.overlayManager.register(this.overlayName, this.container, this.close.bind(this), true); + _resetView() { + this._pages = []; + this._currentPageNumber = 1; + this._currentScale = _ui_utils.UNKNOWN_SCALE; + this._currentScaleValue = null; + this._pageLabels = null; + this._buffer = new PDFPageViewBuffer(DEFAULT_CACHE_SIZE); + this._location = null; + this._pagesRotation = 0; + this._pagesRequests = []; + this._pageViewsReady = false; + this.viewer.textContent = ''; } - open() { - this.overlayManager.open(this.overlayName).then(() => { - this.input.focus(); - let promptString; - if (this.reason === _pdfjsLib.PasswordResponses.INCORRECT_PASSWORD) { - promptString = this.l10n.get('password_invalid', null, 'Invalid password. Please try again.'); - } else { - promptString = this.l10n.get('password_label', null, 'Enter the password to open this PDF file.'); - } - promptString.then(msg => { - this.label.textContent = msg; - }); - }); + _scrollUpdate() { + if (this.pagesCount === 0) { + return; + } + this.update(); } - close() { - this.overlayManager.close(this.overlayName).then(() => { - this.input.value = ''; - }); + _scrollIntoView({ pageDiv, pageSpot = null, pageNumber = null }) { + throw new Error('Not implemented: _scrollIntoView'); } - verify() { - let password = this.input.value; - if (password && password.length > 0) { - this.close(); - return this.updateCallback(password); - } - } - setUpdateCallback(updateCallback, reason) { - this.updateCallback = updateCallback; - this.reason = reason; - } -} -exports.PasswordPrompt = PasswordPrompt; - -/***/ }), -/* 15 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.PDFAttachmentViewer = undefined; - -var _pdfjsLib = __webpack_require__(1); - -class PDFAttachmentViewer { - constructor({ container, eventBus, downloadManager }) { - this.container = container; - this.eventBus = eventBus; - this.downloadManager = downloadManager; - this.reset(); - this.eventBus.on('fileattachmentannotation', this._appendAttachment.bind(this)); - } - reset(keepRenderedCapability = false) { - this.attachments = null; - this.container.textContent = ''; - if (!keepRenderedCapability) { - this._renderedCapability = (0, _pdfjsLib.createPromiseCapability)(); - } - } - _dispatchEvent(attachmentsCount) { - this._renderedCapability.resolve(); - this.eventBus.dispatch('attachmentsloaded', { + _setScaleDispatchEvent(newScale, newValue, preset = false) { + let arg = { source: this, - attachmentsCount - }); - } - _bindPdfLink(button, content, filename) { - if (this.downloadManager.disableCreateObjectURL) { - throw new Error('bindPdfLink: Unsupported "disableCreateObjectURL" value.'); - } - let blobUrl; - button.onclick = function () { - if (!blobUrl) { - blobUrl = (0, _pdfjsLib.createObjectURL)(content, 'application/pdf'); - } - let viewerUrl; - viewerUrl = blobUrl + '?' + encodeURIComponent(filename); - window.open(viewerUrl); - return false; - }; - } - _bindLink(button, content, filename) { - button.onclick = () => { - this.downloadManager.downloadData(content, filename, ''); - return false; + scale: newScale, + presetValue: preset ? newValue : undefined }; + this.eventBus.dispatch('scalechanging', arg); + this.eventBus.dispatch('scalechange', arg); } - render({ attachments, keepRenderedCapability = false }) { - let attachmentsCount = 0; - if (this.attachments) { - this.reset(keepRenderedCapability === true); - } - this.attachments = attachments || null; - if (!attachments) { - this._dispatchEvent(attachmentsCount); + _setScaleUpdatePages(newScale, newValue, noScroll = false, preset = false) { + this._currentScaleValue = newValue.toString(); + if (isSameScale(this._currentScale, newScale)) { + if (preset) { + this._setScaleDispatchEvent(newScale, newValue, true); + } return; } - let names = Object.keys(attachments).sort(function (a, b) { - return a.toLowerCase().localeCompare(b.toLowerCase()); - }); - attachmentsCount = names.length; - for (let i = 0; i < attachmentsCount; i++) { - let item = attachments[names[i]]; - let filename = (0, _pdfjsLib.removeNullCharacters)((0, _pdfjsLib.getFilenameFromUrl)(item.filename)); - let div = document.createElement('div'); - div.className = 'attachmentsItem'; - let button = document.createElement('button'); - button.textContent = filename; - if (/\.pdf$/i.test(filename) && !this.downloadManager.disableCreateObjectURL) { - this._bindPdfLink(button, item.content, filename); - } else { - this._bindLink(button, item.content, filename); - } - div.appendChild(button); - this.container.appendChild(div); + for (let i = 0, ii = this._pages.length; i < ii; i++) { + this._pages[i].update(newScale); } - this._dispatchEvent(attachmentsCount); - } - _appendAttachment({ id, filename, content }) { - this._renderedCapability.promise.then(() => { - let attachments = this.attachments; - if (!attachments) { - attachments = Object.create(null); - } else { - for (let name in attachments) { - if (id === name) { - return; - } - } + this._currentScale = newScale; + if (!noScroll) { + let page = this._currentPageNumber, + dest; + if (this._location && !(this.isInPresentationMode || this.isChangingPresentationMode)) { + page = this._location.pageNumber; + dest = [null, { name: 'XYZ' }, this._location.left, this._location.top, null]; } - attachments[id] = { - filename, - content - }; - this.render({ - attachments, - keepRenderedCapability: true + this.scrollPageIntoView({ + pageNumber: page, + destArray: dest, + allowNegativeOffset: true }); - }); - } -} -exports.PDFAttachmentViewer = PDFAttachmentViewer; - -/***/ }), -/* 16 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.PDFDocumentProperties = undefined; - -var _ui_utils = __webpack_require__(0); - -var _pdfjsLib = __webpack_require__(1); - -const DEFAULT_FIELD_CONTENT = '-'; -const NON_METRIC_LOCALES = ['en-us', 'en-lr', 'my']; -const US_PAGE_NAMES = { - '8.5x11': 'Letter', - '8.5x14': 'Legal' -}; -const METRIC_PAGE_NAMES = { - '297x420': 'A3', - '210x297': 'A4' -}; -function getPageName(size, isPortrait, pageNames) { - const width = isPortrait ? size.width : size.height; - const height = isPortrait ? size.height : size.width; - return pageNames[`${width}x${height}`]; -} -class PDFDocumentProperties { - constructor({ overlayName, fields, container, closeButton }, overlayManager, eventBus, l10n = _ui_utils.NullL10n) { - this.overlayName = overlayName; - this.fields = fields; - this.container = container; - this.overlayManager = overlayManager; - this.l10n = l10n; - this._reset(); - if (closeButton) { - closeButton.addEventListener('click', this.close.bind(this)); } - this.overlayManager.register(this.overlayName, this.container, this.close.bind(this)); - if (eventBus) { - eventBus.on('pagechanging', evt => { - this._currentPageNumber = evt.pageNumber; - }); - eventBus.on('rotationchanging', evt => { - this._pagesRotation = evt.pagesRotation; - }); + this._setScaleDispatchEvent(newScale, newValue, preset); + if (this.defaultRenderingQueue) { + this.update(); } - this._isNonMetricLocale = true; - l10n.getLanguage().then(locale => { - this._isNonMetricLocale = NON_METRIC_LOCALES.includes(locale); - }); } - open() { - let freezeFieldData = data => { - Object.defineProperty(this, 'fieldData', { - value: Object.freeze(data), - writable: false, - enumerable: true, - configurable: true - }); - }; - Promise.all([this.overlayManager.open(this.overlayName), this._dataAvailableCapability.promise]).then(() => { - const currentPageNumber = this._currentPageNumber; - const pagesRotation = this._pagesRotation; - if (this.fieldData && currentPageNumber === this.fieldData['_currentPageNumber'] && pagesRotation === this.fieldData['_pagesRotation']) { - this._updateUI(); + _setScale(value, noScroll = false) { + let scale = parseFloat(value); + if (scale > 0) { + this._setScaleUpdatePages(scale, value, noScroll, false); + } else { + let currentPage = this._pages[this._currentPageNumber - 1]; + if (!currentPage) { return; } - this.pdfDocument.getMetadata().then(({ info, metadata, contentDispositionFilename }) => { - return Promise.all([info, metadata, contentDispositionFilename || (0, _ui_utils.getPDFFileNameFromURL)(this.url), this._parseFileSize(this.maybeFileSize), this._parseDate(info.CreationDate), this._parseDate(info.ModDate), this.pdfDocument.getPage(currentPageNumber).then(pdfPage => { - return this._parsePageSize((0, _ui_utils.getPageSizeInches)(pdfPage), pagesRotation); - })]); - }).then(([info, metadata, fileName, fileSize, creationDate, modDate, pageSize]) => { - freezeFieldData({ - 'fileName': fileName, - 'fileSize': fileSize, - 'title': info.Title, - 'author': info.Author, - 'subject': info.Subject, - 'keywords': info.Keywords, - 'creationDate': creationDate, - 'modificationDate': modDate, - 'creator': info.Creator, - 'producer': info.Producer, - 'version': info.PDFFormatVersion, - 'pageCount': this.pdfDocument.numPages, - 'pageSize': pageSize, - '_currentPageNumber': currentPageNumber, - '_pagesRotation': pagesRotation - }); - this._updateUI(); - return this.pdfDocument.getDownloadInfo(); - }).then(({ length }) => { - this.maybeFileSize = length; - return this._parseFileSize(length); - }).then(fileSize => { - if (fileSize === this.fieldData['fileSize']) { + let hPadding = this.isInPresentationMode || this.removePageBorders ? 0 : _ui_utils.SCROLLBAR_PADDING; + let vPadding = this.isInPresentationMode || this.removePageBorders ? 0 : _ui_utils.VERTICAL_PADDING; + if (this.scrollMode === ScrollMode.HORIZONTAL) { + const temp = hPadding; + hPadding = vPadding; + vPadding = temp; + } + let pageWidthScale = (this.container.clientWidth - hPadding) / currentPage.width * currentPage.scale; + let pageHeightScale = (this.container.clientHeight - vPadding) / currentPage.height * currentPage.scale; + switch (value) { + case 'page-actual': + scale = 1; + break; + case 'page-width': + scale = pageWidthScale; + break; + case 'page-height': + scale = pageHeightScale; + break; + case 'page-fit': + scale = Math.min(pageWidthScale, pageHeightScale); + break; + case 'auto': + let horizontalScale = (0, _ui_utils.isPortraitOrientation)(currentPage) ? pageWidthScale : Math.min(pageHeightScale, pageWidthScale); + scale = Math.min(_ui_utils.MAX_AUTO_SCALE, horizontalScale); + break; + default: + console.error(`${this._name}._setScale: "${value}" is an unknown zoom value.`); return; + } + this._setScaleUpdatePages(scale, value, noScroll, true); + } + } + _resetCurrentPageView() { + if (this.isInPresentationMode) { + this._setScale(this._currentScaleValue, true); + } + let pageView = this._pages[this._currentPageNumber - 1]; + this._scrollIntoView({ pageDiv: pageView.div }); + } + scrollPageIntoView(params) { + if (!this.pdfDocument) { + return; + } + let pageNumber = params.pageNumber || 0; + let dest = params.destArray || null; + let allowNegativeOffset = params.allowNegativeOffset || false; + if (this.isInPresentationMode || !dest) { + this._setCurrentPageNumber(pageNumber, true); + return; + } + let pageView = this._pages[pageNumber - 1]; + if (!pageView) { + console.error(`${this._name}.scrollPageIntoView: Invalid "pageNumber" parameter.`); + return; + } + let x = 0, + y = 0; + let width = 0, + height = 0, + widthScale, + heightScale; + let changeOrientation = pageView.rotation % 180 === 0 ? false : true; + let pageWidth = (changeOrientation ? pageView.height : pageView.width) / pageView.scale / _ui_utils.CSS_UNITS; + let pageHeight = (changeOrientation ? pageView.width : pageView.height) / pageView.scale / _ui_utils.CSS_UNITS; + let scale = 0; + switch (dest[1].name) { + case 'XYZ': + x = dest[2]; + y = dest[3]; + scale = dest[4]; + x = x !== null ? x : 0; + y = y !== null ? y : pageHeight; + break; + case 'Fit': + case 'FitB': + scale = 'page-fit'; + break; + case 'FitH': + case 'FitBH': + y = dest[2]; + scale = 'page-width'; + if (y === null && this._location) { + x = this._location.left; + y = this._location.top; } - let data = (0, _ui_utils.cloneObj)(this.fieldData); - data['fileSize'] = fileSize; - freezeFieldData(data); - this._updateUI(); + break; + case 'FitV': + case 'FitBV': + x = dest[2]; + width = pageWidth; + height = pageHeight; + scale = 'page-height'; + break; + case 'FitR': + x = dest[2]; + y = dest[3]; + width = dest[4] - x; + height = dest[5] - y; + let hPadding = this.removePageBorders ? 0 : _ui_utils.SCROLLBAR_PADDING; + let vPadding = this.removePageBorders ? 0 : _ui_utils.VERTICAL_PADDING; + widthScale = (this.container.clientWidth - hPadding) / width / _ui_utils.CSS_UNITS; + heightScale = (this.container.clientHeight - vPadding) / height / _ui_utils.CSS_UNITS; + scale = Math.min(Math.abs(widthScale), Math.abs(heightScale)); + break; + default: + console.error(`${this._name}.scrollPageIntoView: "${dest[1].name}" ` + 'is not a valid destination type.'); + return; + } + if (scale && scale !== this._currentScale) { + this.currentScaleValue = scale; + } else if (this._currentScale === _ui_utils.UNKNOWN_SCALE) { + this.currentScaleValue = _ui_utils.DEFAULT_SCALE_VALUE; + } + if (scale === 'page-fit' && !dest[4]) { + this._scrollIntoView({ + pageDiv: pageView.div, + pageNumber }); + return; + } + let boundingRect = [pageView.viewport.convertToViewportPoint(x, y), pageView.viewport.convertToViewportPoint(x + width, y + height)]; + let left = Math.min(boundingRect[0][0], boundingRect[1][0]); + let top = Math.min(boundingRect[0][1], boundingRect[1][1]); + if (!allowNegativeOffset) { + left = Math.max(left, 0); + top = Math.max(top, 0); + } + this._scrollIntoView({ + pageDiv: pageView.div, + pageSpot: { + left, + top + }, + pageNumber }); } - close() { - this.overlayManager.close(this.overlayName); + _resizeBuffer(numVisiblePages, visiblePages) { + let suggestedCacheSize = Math.max(DEFAULT_CACHE_SIZE, 2 * numVisiblePages + 1); + this._buffer.resize(suggestedCacheSize, visiblePages); + } + _updateLocation(firstPage) { + let currentScale = this._currentScale; + let currentScaleValue = this._currentScaleValue; + let normalizedScaleValue = parseFloat(currentScaleValue) === currentScale ? Math.round(currentScale * 10000) / 100 : currentScaleValue; + let pageNumber = firstPage.id; + let pdfOpenParams = '#page=' + pageNumber; + pdfOpenParams += '&zoom=' + normalizedScaleValue; + let currentPageView = this._pages[pageNumber - 1]; + let container = this.container; + let topLeft = currentPageView.getPagePoint(container.scrollLeft - firstPage.x, container.scrollTop - firstPage.y); + let intLeft = Math.round(topLeft[0]); + let intTop = Math.round(topLeft[1]); + pdfOpenParams += ',' + intLeft + ',' + intTop; + this._location = { + pageNumber, + scale: normalizedScaleValue, + top: intTop, + left: intLeft, + rotation: this._pagesRotation, + pdfOpenParams + }; + } + update() { + throw new Error('Not implemented: update'); + } + containsElement(element) { + return this.container.contains(element); + } + focus() { + this.container.focus(); + } + get isInPresentationMode() { + return this.presentationModeState === _ui_utils.PresentationModeState.FULLSCREEN; + } + get isChangingPresentationMode() { + return this.presentationModeState === _ui_utils.PresentationModeState.CHANGING; + } + get isHorizontalScrollbarEnabled() { + return this.isInPresentationMode ? false : this.container.scrollWidth > this.container.clientWidth; + } + get isVerticalScrollbarEnabled() { + return this.isInPresentationMode ? false : this.container.scrollHeight > this.container.clientHeight; } - setDocument(pdfDocument, url) { - if (this.pdfDocument) { - this._reset(); - this._updateUI(true); - } - if (!pdfDocument) { - return; - } - this.pdfDocument = pdfDocument; - this.url = url; - this._dataAvailableCapability.resolve(); + _getVisiblePages() { + throw new Error('Not implemented: _getVisiblePages'); } - setFileSize(fileSize) { - if (Number.isInteger(fileSize) && fileSize > 0) { - this.maybeFileSize = fileSize; + cleanup() { + for (let i = 0, ii = this._pages.length; i < ii; i++) { + if (this._pages[i] && this._pages[i].renderingState !== _pdf_rendering_queue.RenderingStates.FINISHED) { + this._pages[i].reset(); + } } } - _reset() { - this.pdfDocument = null; - this.url = null; - this.maybeFileSize = 0; - delete this.fieldData; - this._dataAvailableCapability = (0, _pdfjsLib.createPromiseCapability)(); - this._currentPageNumber = 1; - this._pagesRotation = 0; - } - _updateUI(reset = false) { - if (reset || !this.fieldData) { - for (let id in this.fields) { - this.fields[id].textContent = DEFAULT_FIELD_CONTENT; + _cancelRendering() { + for (let i = 0, ii = this._pages.length; i < ii; i++) { + if (this._pages[i]) { + this._pages[i].cancelRendering(); } - return; } - if (this.overlayManager.active !== this.overlayName) { - return; + } + _ensurePdfPageLoaded(pageView) { + if (pageView.pdfPage) { + return Promise.resolve(pageView.pdfPage); } - for (let id in this.fields) { - let content = this.fieldData[id]; - this.fields[id].textContent = content || content === 0 ? content : DEFAULT_FIELD_CONTENT; + let pageNumber = pageView.id; + if (this._pagesRequests[pageNumber]) { + return this._pagesRequests[pageNumber]; } + let promise = this.pdfDocument.getPage(pageNumber).then(pdfPage => { + if (!pageView.pdfPage) { + pageView.setPdfPage(pdfPage); + } + this._pagesRequests[pageNumber] = null; + return pdfPage; + }).catch(reason => { + console.error('Unable to get page for page view', reason); + this._pagesRequests[pageNumber] = null; + }); + this._pagesRequests[pageNumber] = promise; + return promise; } - _parseFileSize(fileSize = 0) { - let kb = fileSize / 1024; - if (!kb) { - return Promise.resolve(undefined); - } else if (kb < 1024) { - return this.l10n.get('document_properties_kb', { - size_kb: (+kb.toPrecision(3)).toLocaleString(), - size_b: fileSize.toLocaleString() - }, '{{size_kb}} KB ({{size_b}} bytes)'); + forceRendering(currentlyVisiblePages) { + let visiblePages = currentlyVisiblePages || this._getVisiblePages(); + let scrollAhead = this.scrollMode === ScrollMode.HORIZONTAL ? this.scroll.right : this.scroll.down; + let pageView = this.renderingQueue.getHighestPriority(visiblePages, this._pages, scrollAhead); + if (pageView) { + this._ensurePdfPageLoaded(pageView).then(() => { + this.renderingQueue.renderView(pageView); + }); + return true; } - return this.l10n.get('document_properties_mb', { - size_mb: (+(kb / 1024).toPrecision(3)).toLocaleString(), - size_b: fileSize.toLocaleString() - }, '{{size_mb}} MB ({{size_b}} bytes)'); + return false; } - _parsePageSize(pageSizeInches, pagesRotation) { - if (!pageSizeInches) { - return Promise.resolve(undefined); + getPageTextContent(pageIndex) { + return this.pdfDocument.getPage(pageIndex + 1).then(function (page) { + return page.getTextContent({ normalizeWhitespace: true }); + }); + } + createTextLayerBuilder(textLayerDiv, pageIndex, viewport, enhanceTextSelection = false) { + return new _text_layer_builder.TextLayerBuilder({ + textLayerDiv, + eventBus: this.eventBus, + pageIndex, + viewport, + findController: this.isInPresentationMode ? null : this.findController, + enhanceTextSelection: this.isInPresentationMode ? false : enhanceTextSelection + }); + } + createAnnotationLayerBuilder(pageDiv, pdfPage, imageResourcesPath = '', renderInteractiveForms = false, l10n = _ui_utils.NullL10n) { + return new _annotation_layer_builder.AnnotationLayerBuilder({ + pageDiv, + pdfPage, + imageResourcesPath, + renderInteractiveForms, + linkService: this.linkService, + downloadManager: this.downloadManager, + l10n + }); + } + setFindController(findController) { + this.findController = findController; + } + get hasEqualPageSizes() { + let firstPageView = this._pages[0]; + for (let i = 1, ii = this._pages.length; i < ii; ++i) { + let pageView = this._pages[i]; + if (pageView.width !== firstPageView.width || pageView.height !== firstPageView.height) { + return false; + } } - if (pagesRotation % 180 !== 0) { - pageSizeInches = { - width: pageSizeInches.height, - height: pageSizeInches.width + return true; + } + getPagesOverview() { + let pagesOverview = this._pages.map(function (pageView) { + let viewport = pageView.pdfPage.getViewport(1); + return { + width: viewport.width, + height: viewport.height, + rotation: viewport.rotation }; + }); + if (!this.enablePrintAutoRotate) { + return pagesOverview; } - const isPortrait = (0, _ui_utils.isPortraitOrientation)(pageSizeInches); - let sizeInches = { - width: Math.round(pageSizeInches.width * 100) / 100, - height: Math.round(pageSizeInches.height * 100) / 100 - }; - let sizeMillimeters = { - width: Math.round(pageSizeInches.width * 25.4 * 10) / 10, - height: Math.round(pageSizeInches.height * 25.4 * 10) / 10 - }; - let pageName = null; - let name = getPageName(sizeInches, isPortrait, US_PAGE_NAMES) || getPageName(sizeMillimeters, isPortrait, METRIC_PAGE_NAMES); - if (!name && !(Number.isInteger(sizeMillimeters.width) && Number.isInteger(sizeMillimeters.height))) { - const exactMillimeters = { - width: pageSizeInches.width * 25.4, - height: pageSizeInches.height * 25.4 - }; - const intMillimeters = { - width: Math.round(sizeMillimeters.width), - height: Math.round(sizeMillimeters.height) + let isFirstPagePortrait = (0, _ui_utils.isPortraitOrientation)(pagesOverview[0]); + return pagesOverview.map(function (size) { + if (isFirstPagePortrait === (0, _ui_utils.isPortraitOrientation)(size)) { + return size; + } + return { + width: size.height, + height: size.width, + rotation: (size.rotation + 90) % 360 }; - if (Math.abs(exactMillimeters.width - intMillimeters.width) < 0.1 && Math.abs(exactMillimeters.height - intMillimeters.height) < 0.1) { - name = getPageName(intMillimeters, isPortrait, METRIC_PAGE_NAMES); - if (name) { - sizeInches = { - width: Math.round(intMillimeters.width / 25.4 * 100) / 100, - height: Math.round(intMillimeters.height / 25.4 * 100) / 100 - }; - sizeMillimeters = intMillimeters; - } + }); + } + setScrollMode(mode) { + if (mode !== this.scrollMode) { + this.scrollMode = mode; + this._updateScrollModeClasses(); + this.eventBus.dispatch('scrollmodechanged', { mode }); + const pageNumber = this._currentPageNumber; + if (isNaN(this._currentScaleValue)) { + this._setScale(this._currentScaleValue, this.isInPresentationMode); + } + this.scrollPageIntoView({ pageNumber }); + this.update(); + } + } + _updateScrollModeClasses() { + const mode = this.scrollMode, + { classList } = this.viewer; + classList.toggle('scrollHorizontal', mode === ScrollMode.HORIZONTAL); + classList.toggle('scrollWrapped', mode === ScrollMode.WRAPPED); + } + setSpreadMode(mode) { + if (mode !== this.spreadMode) { + this.spreadMode = mode; + this.eventBus.dispatch('spreadmodechanged', { mode }); + this._regroupSpreads(); + } + } + _regroupSpreads() {} +} +exports.BaseViewer = BaseViewer; +exports.ScrollMode = ScrollMode; +exports.SpreadMode = SpreadMode; + +/***/ }), +/* 11 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +; +let pdfjsWebApp, pdfjsWebAppOptions; +{ + pdfjsWebApp = __webpack_require__(4); + pdfjsWebAppOptions = __webpack_require__(7); +} +{ + __webpack_require__(32); + __webpack_require__(35); +} +; +; +; +function getViewerConfiguration() { + return { + appContainer: document.body, + mainContainer: document.getElementById('viewerContainer'), + viewerContainer: document.getElementById('viewer'), + eventBus: null, + toolbar: { + container: document.getElementById('toolbarViewer'), + numPages: document.getElementById('numPages'), + pageNumber: document.getElementById('pageNumber'), + scaleSelectContainer: document.getElementById('scaleSelectContainer'), + scaleSelect: document.getElementById('scaleSelect'), + customScaleOption: document.getElementById('customScaleOption'), + previous: document.getElementById('previous'), + next: document.getElementById('next'), + zoomIn: document.getElementById('zoomIn'), + zoomOut: document.getElementById('zoomOut'), + viewFind: document.getElementById('viewFind'), + openFile: document.getElementById('openFile'), + print: document.getElementById('print'), + presentationModeButton: document.getElementById('presentationMode'), + download: document.getElementById('download'), + viewBookmark: document.getElementById('viewBookmark') + }, + secondaryToolbar: { + toolbar: document.getElementById('secondaryToolbar'), + toggleButton: document.getElementById('secondaryToolbarToggle'), + toolbarButtonContainer: document.getElementById('secondaryToolbarButtonContainer'), + presentationModeButton: document.getElementById('secondaryPresentationMode'), + openFileButton: document.getElementById('secondaryOpenFile'), + printButton: document.getElementById('secondaryPrint'), + downloadButton: document.getElementById('secondaryDownload'), + viewBookmarkButton: document.getElementById('secondaryViewBookmark'), + firstPageButton: document.getElementById('firstPage'), + lastPageButton: document.getElementById('lastPage'), + pageRotateCwButton: document.getElementById('pageRotateCw'), + pageRotateCcwButton: document.getElementById('pageRotateCcw'), + cursorSelectToolButton: document.getElementById('cursorSelectTool'), + cursorHandToolButton: document.getElementById('cursorHandTool'), + scrollVerticalButton: document.getElementById('scrollVertical'), + scrollHorizontalButton: document.getElementById('scrollHorizontal'), + scrollWrappedButton: document.getElementById('scrollWrapped'), + spreadNoneButton: document.getElementById('spreadNone'), + spreadOddButton: document.getElementById('spreadOdd'), + spreadEvenButton: document.getElementById('spreadEven'), + documentPropertiesButton: document.getElementById('documentProperties') + }, + fullscreen: { + contextFirstPage: document.getElementById('contextFirstPage'), + contextLastPage: document.getElementById('contextLastPage'), + contextPageRotateCw: document.getElementById('contextPageRotateCw'), + contextPageRotateCcw: document.getElementById('contextPageRotateCcw') + }, + sidebar: { + outerContainer: document.getElementById('outerContainer'), + viewerContainer: document.getElementById('viewerContainer'), + toggleButton: document.getElementById('sidebarToggle'), + thumbnailButton: document.getElementById('viewThumbnail'), + outlineButton: document.getElementById('viewOutline'), + attachmentsButton: document.getElementById('viewAttachments'), + thumbnailView: document.getElementById('thumbnailView'), + outlineView: document.getElementById('outlineView'), + attachmentsView: document.getElementById('attachmentsView') + }, + sidebarResizer: { + outerContainer: document.getElementById('outerContainer'), + resizer: document.getElementById('sidebarResizer') + }, + findBar: { + bar: document.getElementById('findbar'), + toggleButton: document.getElementById('viewFind'), + findField: document.getElementById('findInput'), + highlightAllCheckbox: document.getElementById('findHighlightAll'), + caseSensitiveCheckbox: document.getElementById('findMatchCase'), + findMsg: document.getElementById('findMsg'), + findResultsCount: document.getElementById('findResultsCount'), + findStatusIcon: document.getElementById('findStatusIcon'), + findPreviousButton: document.getElementById('findPrevious'), + findNextButton: document.getElementById('findNext') + }, + passwordOverlay: { + overlayName: 'passwordOverlay', + container: document.getElementById('passwordOverlay'), + label: document.getElementById('passwordText'), + input: document.getElementById('password'), + submitButton: document.getElementById('passwordSubmit'), + cancelButton: document.getElementById('passwordCancel') + }, + documentProperties: { + overlayName: 'documentPropertiesOverlay', + container: document.getElementById('documentPropertiesOverlay'), + closeButton: document.getElementById('documentPropertiesClose'), + fields: { + 'fileName': document.getElementById('fileNameField'), + 'fileSize': document.getElementById('fileSizeField'), + 'title': document.getElementById('titleField'), + 'author': document.getElementById('authorField'), + 'subject': document.getElementById('subjectField'), + 'keywords': document.getElementById('keywordsField'), + 'creationDate': document.getElementById('creationDateField'), + 'modificationDate': document.getElementById('modificationDateField'), + 'creator': document.getElementById('creatorField'), + 'producer': document.getElementById('producerField'), + 'version': document.getElementById('versionField'), + 'pageCount': document.getElementById('pageCountField'), + 'pageSize': document.getElementById('pageSizeField') } - } - if (name) { - pageName = this.l10n.get('document_properties_page_size_name_' + name.toLowerCase(), null, name); - } - return Promise.all([this._isNonMetricLocale ? sizeInches : sizeMillimeters, this.l10n.get('document_properties_page_size_unit_' + (this._isNonMetricLocale ? 'inches' : 'millimeters'), null, this._isNonMetricLocale ? 'in' : 'mm'), pageName, this.l10n.get('document_properties_page_size_orientation_' + (isPortrait ? 'portrait' : 'landscape'), null, isPortrait ? 'portrait' : 'landscape')]).then(([{ width, height }, unit, name, orientation]) => { - return this.l10n.get('document_properties_page_size_dimension_' + (name ? 'name_' : '') + 'string', { - width: width.toLocaleString(), - height: height.toLocaleString(), - unit, - name, - orientation - }, '{{width}} Ă— {{height}} {{unit}} (' + (name ? '{{name}}, ' : '') + '{{orientation}})'); - }); - } - _parseDate(inputDate) { - if (!inputDate) { - return; - } - let dateToParse = inputDate; - if (dateToParse.substring(0, 2) === 'D:') { - dateToParse = dateToParse.substring(2); - } - let year = parseInt(dateToParse.substring(0, 4), 10); - let month = parseInt(dateToParse.substring(4, 6), 10) - 1; - let day = parseInt(dateToParse.substring(6, 8), 10); - let hours = parseInt(dateToParse.substring(8, 10), 10); - let minutes = parseInt(dateToParse.substring(10, 12), 10); - let seconds = parseInt(dateToParse.substring(12, 14), 10); - let utRel = dateToParse.substring(14, 15); - let offsetHours = parseInt(dateToParse.substring(15, 17), 10); - let offsetMinutes = parseInt(dateToParse.substring(18, 20), 10); - if (utRel === '-') { - hours += offsetHours; - minutes += offsetMinutes; - } else if (utRel === '+') { - hours -= offsetHours; - minutes -= offsetMinutes; - } - let date = new Date(Date.UTC(year, month, day, hours, minutes, seconds)); - let dateString = date.toLocaleDateString(); - let timeString = date.toLocaleTimeString(); - return this.l10n.get('document_properties_date_string', { - date: dateString, - time: timeString - }, '{{date}}, {{time}}'); - } + }, + errorWrapper: { + container: document.getElementById('errorWrapper'), + errorMessage: document.getElementById('errorMessage'), + closeButton: document.getElementById('errorClose'), + errorMoreInfo: document.getElementById('errorMoreInfo'), + moreInfoButton: document.getElementById('errorShowMore'), + lessInfoButton: document.getElementById('errorShowLess') + }, + printContainer: document.getElementById('printContainer'), + openFileInputName: 'fileInput', + debuggerScriptPath: './debugger.js' + }; +} +function webViewerLoad() { + let config = getViewerConfiguration(); + window.PDFViewerApplication = pdfjsWebApp.PDFViewerApplication; + window.PDFViewerApplicationOptions = pdfjsWebAppOptions.AppOptions; + pdfjsWebApp.PDFViewerApplication.run(config); +} +if (document.readyState === 'interactive' || document.readyState === 'complete') { + webViewerLoad(); +} else { + document.addEventListener('DOMContentLoaded', webViewerLoad, true); } -exports.PDFDocumentProperties = PDFDocumentProperties; /***/ }), -/* 17 */ +/* 12 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -4598,166 +4502,139 @@ exports.PDFDocumentProperties = PDFDocumentProperties; Object.defineProperty(exports, "__esModule", { value: true }); -exports.PDFFindBar = undefined; - -var _pdf_find_controller = __webpack_require__(9); - -var _ui_utils = __webpack_require__(0); - -class PDFFindBar { - constructor(options, l10n = _ui_utils.NullL10n) { - this.opened = false; - this.bar = options.bar || null; - this.toggleButton = options.toggleButton || null; - this.findField = options.findField || null; - this.highlightAll = options.highlightAllCheckbox || null; - this.caseSensitive = options.caseSensitiveCheckbox || null; - this.findMsg = options.findMsg || null; - this.findResultsCount = options.findResultsCount || null; - this.findStatusIcon = options.findStatusIcon || null; - this.findPreviousButton = options.findPreviousButton || null; - this.findNextButton = options.findNextButton || null; - this.findController = options.findController || null; - this.eventBus = options.eventBus; - this.l10n = l10n; - if (this.findController === null) { - throw new Error('PDFFindBar cannot be used without a ' + 'PDFFindController instance.'); +function GrabToPan(options) { + this.element = options.element; + this.document = options.element.ownerDocument; + if (typeof options.ignoreTarget === 'function') { + this.ignoreTarget = options.ignoreTarget; + } + this.onActiveChanged = options.onActiveChanged; + this.activate = this.activate.bind(this); + this.deactivate = this.deactivate.bind(this); + this.toggle = this.toggle.bind(this); + this._onmousedown = this._onmousedown.bind(this); + this._onmousemove = this._onmousemove.bind(this); + this._endPan = this._endPan.bind(this); + var overlay = this.overlay = document.createElement('div'); + overlay.className = 'grab-to-pan-grabbing'; +} +GrabToPan.prototype = { + CSS_CLASS_GRAB: 'grab-to-pan-grab', + activate: function GrabToPan_activate() { + if (!this.active) { + this.active = true; + this.element.addEventListener('mousedown', this._onmousedown, true); + this.element.classList.add(this.CSS_CLASS_GRAB); + if (this.onActiveChanged) { + this.onActiveChanged(true); + } } - this.toggleButton.addEventListener('click', () => { - this.toggle(); - }); - this.findField.addEventListener('input', () => { - this.dispatchEvent(''); - }); - this.bar.addEventListener('keydown', e => { - switch (e.keyCode) { - case 13: - if (e.target === this.findField) { - this.dispatchEvent('again', e.shiftKey); - } - break; - case 27: - this.close(); - break; + }, + deactivate: function GrabToPan_deactivate() { + if (this.active) { + this.active = false; + this.element.removeEventListener('mousedown', this._onmousedown, true); + this._endPan(); + this.element.classList.remove(this.CSS_CLASS_GRAB); + if (this.onActiveChanged) { + this.onActiveChanged(false); } - }); - this.findPreviousButton.addEventListener('click', () => { - this.dispatchEvent('again', true); - }); - this.findNextButton.addEventListener('click', () => { - this.dispatchEvent('again', false); - }); - this.highlightAll.addEventListener('click', () => { - this.dispatchEvent('highlightallchange'); - }); - this.caseSensitive.addEventListener('click', () => { - this.dispatchEvent('casesensitivitychange'); - }); - this.eventBus.on('resize', this._adjustWidth.bind(this)); - } - reset() { - this.updateUIState(); - } - dispatchEvent(type, findPrev) { - this.eventBus.dispatch('find', { - source: this, - type, - query: this.findField.value, - caseSensitive: this.caseSensitive.checked, - phraseSearch: true, - highlightAll: this.highlightAll.checked, - findPrevious: findPrev - }); - } - updateUIState(state, previous, matchCount) { - let notFound = false; - let findMsg = ''; - let status = ''; - switch (state) { - case _pdf_find_controller.FindState.FOUND: - break; - case _pdf_find_controller.FindState.PENDING: - status = 'pending'; - break; - case _pdf_find_controller.FindState.NOT_FOUND: - findMsg = this.l10n.get('find_not_found', null, 'Phrase not found'); - notFound = true; - break; - case _pdf_find_controller.FindState.WRAPPED: - if (previous) { - findMsg = this.l10n.get('find_reached_top', null, 'Reached top of document, continued from bottom'); - } else { - findMsg = this.l10n.get('find_reached_bottom', null, 'Reached end of document, continued from top'); - } - break; } - if (notFound) { - this.findField.classList.add('notFound'); + }, + toggle: function GrabToPan_toggle() { + if (this.active) { + this.deactivate(); } else { - this.findField.classList.remove('notFound'); + this.activate(); } - this.findField.setAttribute('data-status', status); - Promise.resolve(findMsg).then(msg => { - this.findMsg.textContent = msg; - this._adjustWidth(); - }); - this.updateResultsCount(matchCount); - } - updateResultsCount(matchCount) { - if (!this.findResultsCount) { + }, + ignoreTarget: function GrabToPan_ignoreTarget(node) { + return node[matchesSelector]('a[href], a[href] *, input, textarea, button, button *, select, option'); + }, + _onmousedown: function GrabToPan__onmousedown(event) { + if (event.button !== 0 || this.ignoreTarget(event.target)) { return; } - if (!matchCount) { - this.findResultsCount.classList.add('hidden'); - this.findResultsCount.textContent = ''; - } else { - this.findResultsCount.textContent = matchCount.toLocaleString(); - this.findResultsCount.classList.remove('hidden'); + if (event.originalTarget) { + try { + event.originalTarget.tagName; + } catch (e) { + return; + } } - this._adjustWidth(); - } - open() { - if (!this.opened) { - this.opened = true; - this.toggleButton.classList.add('toggled'); - this.bar.classList.remove('hidden'); + this.scrollLeftStart = this.element.scrollLeft; + this.scrollTopStart = this.element.scrollTop; + this.clientXStart = event.clientX; + this.clientYStart = event.clientY; + this.document.addEventListener('mousemove', this._onmousemove, true); + this.document.addEventListener('mouseup', this._endPan, true); + this.element.addEventListener('scroll', this._endPan, true); + event.preventDefault(); + event.stopPropagation(); + var focusedElement = document.activeElement; + if (focusedElement && !focusedElement.contains(event.target)) { + focusedElement.blur(); } - this.findField.select(); - this.findField.focus(); - this._adjustWidth(); - } - close() { - if (!this.opened) { + }, + _onmousemove: function GrabToPan__onmousemove(event) { + this.element.removeEventListener('scroll', this._endPan, true); + if (isLeftMouseReleased(event)) { + this._endPan(); return; } - this.opened = false; - this.toggleButton.classList.remove('toggled'); - this.bar.classList.add('hidden'); - this.findController.active = false; - } - toggle() { - if (this.opened) { - this.close(); + var xDiff = event.clientX - this.clientXStart; + var yDiff = event.clientY - this.clientYStart; + var scrollTop = this.scrollTopStart - yDiff; + var scrollLeft = this.scrollLeftStart - xDiff; + if (this.element.scrollTo) { + this.element.scrollTo({ + top: scrollTop, + left: scrollLeft, + behavior: 'instant' + }); } else { - this.open(); - } - } - _adjustWidth() { - if (!this.opened) { - return; + this.element.scrollTop = scrollTop; + this.element.scrollLeft = scrollLeft; } - this.bar.classList.remove('wrapContainers'); - let findbarHeight = this.bar.clientHeight; - let inputContainerHeight = this.bar.firstElementChild.clientHeight; - if (findbarHeight > inputContainerHeight) { - this.bar.classList.add('wrapContainers'); + if (!this.overlay.parentNode) { + document.body.appendChild(this.overlay); } + }, + _endPan: function GrabToPan__endPan() { + this.element.removeEventListener('scroll', this._endPan, true); + this.document.removeEventListener('mousemove', this._onmousemove, true); + this.document.removeEventListener('mouseup', this._endPan, true); + this.overlay.remove(); + } +}; +var matchesSelector; +['webkitM', 'mozM', 'msM', 'oM', 'm'].some(function (prefix) { + var name = prefix + 'atches'; + if (name in document.documentElement) { + matchesSelector = name; + } + name += 'Selector'; + if (name in document.documentElement) { + matchesSelector = name; + } + return matchesSelector; +}); +var isNotIEorIsIE10plus = !document.documentMode || document.documentMode > 9; +var chrome = window.chrome; +var isChrome15OrOpera15plus = chrome && (chrome.webstore || chrome.app); +var isSafari6plus = /Apple/.test(navigator.vendor) && /Version\/([6-9]\d*|[1-5]\d+)/.test(navigator.userAgent); +function isLeftMouseReleased(event) { + if ('buttons' in event && isNotIEorIsIE10plus) { + return !(event.buttons & 1); + } + if (isChrome15OrOpera15plus || isSafari6plus) { + return event.which === 0; } } -exports.PDFFindBar = PDFFindBar; +exports.GrabToPan = GrabToPan; /***/ }), -/* 18 */ +/* 13 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -4766,375 +4643,469 @@ exports.PDFFindBar = PDFFindBar; Object.defineProperty(exports, "__esModule", { value: true }); -exports.isDestArraysEqual = exports.isDestHashesEqual = exports.PDFHistory = undefined; +exports.PDFSidebar = exports.SidebarView = undefined; var _ui_utils = __webpack_require__(0); -var _dom_events = __webpack_require__(2); +var _pdf_rendering_queue = __webpack_require__(3); -const HASH_CHANGE_TIMEOUT = 1000; -const POSITION_UPDATED_THRESHOLD = 50; -const UPDATE_VIEWAREA_TIMEOUT = 1000; -function getCurrentHash() { - return document.location.hash; -} -function parseCurrentHash(linkService) { - let hash = unescape(getCurrentHash()).substring(1); - let params = (0, _ui_utils.parseQueryString)(hash); - let page = params.page | 0; - if (!(Number.isInteger(page) && page > 0 && page <= linkService.pagesCount)) { - page = null; - } - return { - hash, - page, - rotation: linkService.rotation - }; -} -class PDFHistory { - constructor({ linkService, eventBus }) { - this.linkService = linkService; - this.eventBus = eventBus || (0, _dom_events.getGlobalEventBus)(); - this.initialized = false; - this.initialBookmark = null; - this.initialRotation = null; - this._boundEvents = Object.create(null); - this._isViewerInPresentationMode = false; - this._isPagesLoaded = false; - this.eventBus.on('presentationmodechanged', evt => { - this._isViewerInPresentationMode = evt.active || evt.switchInProgress; - }); - this.eventBus.on('pagesloaded', evt => { - this._isPagesLoaded = !!evt.pagesCount; - }); - } - initialize(fingerprint, resetHistory = false) { - if (!fingerprint || typeof fingerprint !== 'string') { - console.error('PDFHistory.initialize: The "fingerprint" must be a non-empty string.'); - return; - } - let reInitialized = this.initialized && this.fingerprint !== fingerprint; - this.fingerprint = fingerprint; - if (!this.initialized) { - this._bindEvents(); - } - let state = window.history.state; - this.initialized = true; - this.initialBookmark = null; - this.initialRotation = null; - this._popStateInProgress = false; - this._blockHashChange = 0; - this._currentHash = getCurrentHash(); - this._numPositionUpdates = 0; - this._uid = this._maxUid = 0; - this._destination = null; - this._position = null; - if (!this._isValidState(state) || resetHistory) { - let { hash, page, rotation } = parseCurrentHash(this.linkService); - if (!hash || reInitialized || resetHistory) { - this._pushOrReplaceState(null, true); - return; - } - this._pushOrReplaceState({ - hash, - page, - rotation - }, true); - return; - } - let destination = state.destination; - this._updateInternalState(destination, state.uid, true); - if (this._uid > this._maxUid) { - this._maxUid = this._uid; - } - if (destination.rotation !== undefined) { - this.initialRotation = destination.rotation; - } - if (destination.dest) { - this.initialBookmark = JSON.stringify(destination.dest); - this._destination.page = null; - } else if (destination.hash) { - this.initialBookmark = destination.hash; - } else if (destination.page) { - this.initialBookmark = `page=${destination.page}`; - } - } - push({ namedDest, explicitDest, pageNumber }) { - if (!this.initialized) { - return; - } - if (namedDest && typeof namedDest !== 'string' || !(explicitDest instanceof Array) || !(Number.isInteger(pageNumber) && pageNumber > 0 && pageNumber <= this.linkService.pagesCount)) { - console.error('PDFHistory.push: Invalid parameters.'); - return; - } - let hash = namedDest || JSON.stringify(explicitDest); - if (!hash) { - return; - } - let forceReplace = false; - if (this._destination && (isDestHashesEqual(this._destination.hash, hash) || isDestArraysEqual(this._destination.dest, explicitDest))) { - if (this._destination.page) { - return; - } - forceReplace = true; - } - if (this._popStateInProgress && !forceReplace) { - return; - } - this._pushOrReplaceState({ - dest: explicitDest, - hash, - page: pageNumber, - rotation: this.linkService.rotation - }, forceReplace); - if (!this._popStateInProgress) { - this._popStateInProgress = true; - Promise.resolve().then(() => { - this._popStateInProgress = false; - }); - } +const UI_NOTIFICATION_CLASS = 'pdfSidebarNotification'; +const SidebarView = { + NONE: 0, + THUMBS: 1, + OUTLINE: 2, + ATTACHMENTS: 3 +}; +class PDFSidebar { + constructor(options, l10n = _ui_utils.NullL10n) { + this.isOpen = false; + this.active = SidebarView.THUMBS; + this.isInitialViewSet = false; + this.onToggled = null; + this.pdfViewer = options.pdfViewer; + this.pdfThumbnailViewer = options.pdfThumbnailViewer; + this.pdfOutlineViewer = options.pdfOutlineViewer; + this.outerContainer = options.outerContainer; + this.viewerContainer = options.viewerContainer; + this.eventBus = options.eventBus; + this.toggleButton = options.toggleButton; + this.thumbnailButton = options.thumbnailButton; + this.outlineButton = options.outlineButton; + this.attachmentsButton = options.attachmentsButton; + this.thumbnailView = options.thumbnailView; + this.outlineView = options.outlineView; + this.attachmentsView = options.attachmentsView; + this.disableNotification = options.disableNotification || false; + this.l10n = l10n; + this._addEventListeners(); } - pushCurrentPosition() { - if (!this.initialized || this._popStateInProgress) { - return; - } - this._tryPushCurrentPosition(); + reset() { + this.isInitialViewSet = false; + this._hideUINotification(null); + this.switchView(SidebarView.THUMBS); + this.outlineButton.disabled = false; + this.attachmentsButton.disabled = false; } - back() { - if (!this.initialized || this._popStateInProgress) { - return; - } - let state = window.history.state; - if (this._isValidState(state) && state.uid > 0) { - window.history.back(); - } + get visibleView() { + return this.isOpen ? this.active : SidebarView.NONE; } - forward() { - if (!this.initialized || this._popStateInProgress) { - return; - } - let state = window.history.state; - if (this._isValidState(state) && state.uid < this._maxUid) { - window.history.forward(); - } + get isThumbnailViewVisible() { + return this.isOpen && this.active === SidebarView.THUMBS; } - get popStateInProgress() { - return this.initialized && (this._popStateInProgress || this._blockHashChange > 0); + get isOutlineViewVisible() { + return this.isOpen && this.active === SidebarView.OUTLINE; } - _pushOrReplaceState(destination, forceReplace = false) { - let shouldReplace = forceReplace || !this._destination; - let newState = { - fingerprint: this.fingerprint, - uid: shouldReplace ? this._uid : this._uid + 1, - destination - }; - this._updateInternalState(destination, newState.uid); - if (shouldReplace) { - window.history.replaceState(newState, ''); - } else { - this._maxUid = this._uid; - window.history.pushState(newState, ''); - } + get isAttachmentsViewVisible() { + return this.isOpen && this.active === SidebarView.ATTACHMENTS; } - _tryPushCurrentPosition(temporary = false) { - if (!this._position) { - return; - } - let position = this._position; - if (temporary) { - position = (0, _ui_utils.cloneObj)(this._position); - position.temporary = true; - } - if (!this._destination) { - this._pushOrReplaceState(position); + setInitialView(view = SidebarView.NONE) { + if (this.isInitialViewSet) { return; } - if (this._destination.temporary) { - this._pushOrReplaceState(position, true); + this.isInitialViewSet = true; + if (this.isOpen && view === SidebarView.NONE) { + this._dispatchEvent(); return; } - if (this._destination.hash === position.hash) { - return; + let isViewPreserved = view === this.visibleView; + this.switchView(view, true); + if (isViewPreserved) { + this._dispatchEvent(); } - if (!this._destination.page && (POSITION_UPDATED_THRESHOLD <= 0 || this._numPositionUpdates <= POSITION_UPDATED_THRESHOLD)) { + } + switchView(view, forceOpen = false) { + if (view === SidebarView.NONE) { + this.close(); return; } - let forceReplace = false; - if (this._destination.page === position.first || this._destination.page === position.page) { - if (this._destination.dest || !this._destination.first) { + let isViewChanged = view !== this.active; + let shouldForceRendering = false; + switch (view) { + case SidebarView.THUMBS: + this.thumbnailButton.classList.add('toggled'); + this.outlineButton.classList.remove('toggled'); + this.attachmentsButton.classList.remove('toggled'); + this.thumbnailView.classList.remove('hidden'); + this.outlineView.classList.add('hidden'); + this.attachmentsView.classList.add('hidden'); + if (this.isOpen && isViewChanged) { + this._updateThumbnailViewer(); + shouldForceRendering = true; + } + break; + case SidebarView.OUTLINE: + if (this.outlineButton.disabled) { + return; + } + this.thumbnailButton.classList.remove('toggled'); + this.outlineButton.classList.add('toggled'); + this.attachmentsButton.classList.remove('toggled'); + this.thumbnailView.classList.add('hidden'); + this.outlineView.classList.remove('hidden'); + this.attachmentsView.classList.add('hidden'); + break; + case SidebarView.ATTACHMENTS: + if (this.attachmentsButton.disabled) { + return; + } + this.thumbnailButton.classList.remove('toggled'); + this.outlineButton.classList.remove('toggled'); + this.attachmentsButton.classList.add('toggled'); + this.thumbnailView.classList.add('hidden'); + this.outlineView.classList.add('hidden'); + this.attachmentsView.classList.remove('hidden'); + break; + default: + console.error('PDFSidebar_switchView: "' + view + '" is an unsupported value.'); return; - } - forceReplace = true; - } - this._pushOrReplaceState(position, forceReplace); - } - _isValidState(state) { - if (!state) { - return false; } - if (state.fingerprint !== this.fingerprint) { - return false; + this.active = view | 0; + if (forceOpen && !this.isOpen) { + this.open(); + return; } - if (!Number.isInteger(state.uid) || state.uid < 0) { - return false; + if (shouldForceRendering) { + this._forceRendering(); } - if (state.destination === null || typeof state.destination !== 'object') { - return false; + if (isViewChanged) { + this._dispatchEvent(); } - return true; + this._hideUINotification(this.active); } - _updateInternalState(destination, uid, removeTemporary = false) { - if (this._updateViewareaTimeout) { - clearTimeout(this._updateViewareaTimeout); - this._updateViewareaTimeout = null; + open() { + if (this.isOpen) { + return; } - if (removeTemporary && destination && destination.temporary) { - delete destination.temporary; + this.isOpen = true; + this.toggleButton.classList.add('toggled'); + this.outerContainer.classList.add('sidebarMoving'); + this.outerContainer.classList.add('sidebarOpen'); + if (this.active === SidebarView.THUMBS) { + this._updateThumbnailViewer(); } - this._destination = destination; - this._uid = uid; - this._numPositionUpdates = 0; + this._forceRendering(); + this._dispatchEvent(); + this._hideUINotification(this.active); } - _updateViewarea({ location }) { - if (this._updateViewareaTimeout) { - clearTimeout(this._updateViewareaTimeout); - this._updateViewareaTimeout = null; - } - this._position = { - hash: this._isViewerInPresentationMode ? `page=${location.pageNumber}` : location.pdfOpenParams.substring(1), - page: this.linkService.page, - first: location.pageNumber, - rotation: location.rotation - }; - if (this._popStateInProgress) { + close() { + if (!this.isOpen) { return; } - if (POSITION_UPDATED_THRESHOLD > 0 && this._isPagesLoaded && this._destination && !this._destination.page) { - this._numPositionUpdates++; + this.isOpen = false; + this.toggleButton.classList.remove('toggled'); + this.outerContainer.classList.add('sidebarMoving'); + this.outerContainer.classList.remove('sidebarOpen'); + this._forceRendering(); + this._dispatchEvent(); + } + toggle() { + if (this.isOpen) { + this.close(); + } else { + this.open(); } - if (UPDATE_VIEWAREA_TIMEOUT > 0) { - this._updateViewareaTimeout = setTimeout(() => { - if (!this._popStateInProgress) { - this._tryPushCurrentPosition(true); - } - this._updateViewareaTimeout = null; - }, UPDATE_VIEWAREA_TIMEOUT); + } + _dispatchEvent() { + this.eventBus.dispatch('sidebarviewchanged', { + source: this, + view: this.visibleView + }); + } + _forceRendering() { + if (this.onToggled) { + this.onToggled(); + } else { + this.pdfViewer.forceRendering(); + this.pdfThumbnailViewer.forceRendering(); } } - _popState({ state }) { - let newHash = getCurrentHash(), - hashChanged = this._currentHash !== newHash; - this._currentHash = newHash; - if (!state || false) { - this._uid++; - let { hash, page, rotation } = parseCurrentHash(this.linkService); - this._pushOrReplaceState({ - hash, - page, - rotation - }, true); + _updateThumbnailViewer() { + let { pdfViewer, pdfThumbnailViewer } = this; + let pagesCount = pdfViewer.pagesCount; + for (let pageIndex = 0; pageIndex < pagesCount; pageIndex++) { + let pageView = pdfViewer.getPageView(pageIndex); + if (pageView && pageView.renderingState === _pdf_rendering_queue.RenderingStates.FINISHED) { + let thumbnailView = pdfThumbnailViewer.getThumbnail(pageIndex); + thumbnailView.setImage(pageView); + } + } + pdfThumbnailViewer.scrollThumbnailIntoView(pdfViewer.currentPageNumber); + } + _showUINotification(view) { + if (this.disableNotification) { return; } - if (!this._isValidState(state)) { + this.l10n.get('toggle_sidebar_notification.title', null, 'Toggle Sidebar (document contains outline/attachments)').then(msg => { + this.toggleButton.title = msg; + }); + if (!this.isOpen) { + this.toggleButton.classList.add(UI_NOTIFICATION_CLASS); + } else if (view === this.active) { return; } - this._popStateInProgress = true; - if (hashChanged) { - this._blockHashChange++; - (0, _ui_utils.waitOnEventOrTimeout)({ - target: window, - name: 'hashchange', - delay: HASH_CHANGE_TIMEOUT - }).then(() => { - this._blockHashChange--; - }); + switch (view) { + case SidebarView.OUTLINE: + this.outlineButton.classList.add(UI_NOTIFICATION_CLASS); + break; + case SidebarView.ATTACHMENTS: + this.attachmentsButton.classList.add(UI_NOTIFICATION_CLASS); + break; } - let destination = state.destination; - this._updateInternalState(destination, state.uid, true); - if (this._uid > this._maxUid) { - this._maxUid = this._uid; + } + _hideUINotification(view) { + if (this.disableNotification) { + return; } - if ((0, _ui_utils.isValidRotation)(destination.rotation)) { - this.linkService.rotation = destination.rotation; + let removeNotification = view => { + switch (view) { + case SidebarView.OUTLINE: + this.outlineButton.classList.remove(UI_NOTIFICATION_CLASS); + break; + case SidebarView.ATTACHMENTS: + this.attachmentsButton.classList.remove(UI_NOTIFICATION_CLASS); + break; + } + }; + if (!this.isOpen && view !== null) { + return; } - if (destination.dest) { - this.linkService.navigateTo(destination.dest); - } else if (destination.hash) { - this.linkService.setHash(destination.hash); - } else if (destination.page) { - this.linkService.page = destination.page; + this.toggleButton.classList.remove(UI_NOTIFICATION_CLASS); + if (view !== null) { + removeNotification(view); + return; } - Promise.resolve().then(() => { - this._popStateInProgress = false; + for (view in SidebarView) { + removeNotification(SidebarView[view]); + } + this.l10n.get('toggle_sidebar.title', null, 'Toggle Sidebar').then(msg => { + this.toggleButton.title = msg; }); } - _bindEvents() { - let { _boundEvents, eventBus } = this; - _boundEvents.updateViewarea = this._updateViewarea.bind(this); - _boundEvents.popState = this._popState.bind(this); - _boundEvents.pageHide = evt => { - if (!this._destination || this._destination.temporary) { - this._tryPushCurrentPosition(); + _addEventListeners() { + this.viewerContainer.addEventListener('transitionend', evt => { + if (evt.target === this.viewerContainer) { + this.outerContainer.classList.remove('sidebarMoving'); } - }; - eventBus.on('updateviewarea', _boundEvents.updateViewarea); - window.addEventListener('popstate', _boundEvents.popState); - window.addEventListener('pagehide', _boundEvents.pageHide); + }); + this.thumbnailButton.addEventListener('click', () => { + this.switchView(SidebarView.THUMBS); + }); + this.outlineButton.addEventListener('click', () => { + this.switchView(SidebarView.OUTLINE); + }); + this.outlineButton.addEventListener('dblclick', () => { + this.pdfOutlineViewer.toggleOutlineTree(); + }); + this.attachmentsButton.addEventListener('click', () => { + this.switchView(SidebarView.ATTACHMENTS); + }); + this.eventBus.on('outlineloaded', evt => { + let outlineCount = evt.outlineCount; + this.outlineButton.disabled = !outlineCount; + if (outlineCount) { + this._showUINotification(SidebarView.OUTLINE); + } else if (this.active === SidebarView.OUTLINE) { + this.switchView(SidebarView.THUMBS); + } + }); + this.eventBus.on('attachmentsloaded', evt => { + if (evt.attachmentsCount) { + this.attachmentsButton.disabled = false; + this._showUINotification(SidebarView.ATTACHMENTS); + return; + } + Promise.resolve().then(() => { + if (this.attachmentsView.hasChildNodes()) { + return; + } + this.attachmentsButton.disabled = true; + if (this.active === SidebarView.ATTACHMENTS) { + this.switchView(SidebarView.THUMBS); + } + }); + }); + this.eventBus.on('presentationmodechanged', evt => { + if (!evt.active && !evt.switchInProgress && this.isThumbnailViewVisible) { + this._updateThumbnailViewer(); + } + }); } } -function isDestHashesEqual(destHash, pushHash) { - if (typeof destHash !== 'string' || typeof pushHash !== 'string') { - return false; +exports.SidebarView = SidebarView; +exports.PDFSidebar = PDFSidebar; + +/***/ }), +/* 14 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", { + value: true +}); +class OverlayManager { + constructor() { + this._overlays = {}; + this._active = null; + this._keyDownBound = this._keyDown.bind(this); } - if (destHash === pushHash) { - return true; + get active() { + return this._active; } - let { nameddest } = (0, _ui_utils.parseQueryString)(destHash); - if (nameddest === pushHash) { - return true; + register(name, element, callerCloseMethod = null, canForceClose = false) { + return new Promise(resolve => { + let container; + if (!name || !element || !(container = element.parentNode)) { + throw new Error('Not enough parameters.'); + } else if (this._overlays[name]) { + throw new Error('The overlay is already registered.'); + } + this._overlays[name] = { + element, + container, + callerCloseMethod, + canForceClose + }; + resolve(); + }); } - return false; -} -function isDestArraysEqual(firstDest, secondDest) { - function isEntryEqual(first, second) { - if (typeof first !== typeof second) { - return false; - } - if (first instanceof Array || second instanceof Array) { - return false; - } - if (first !== null && typeof first === 'object' && second !== null) { - if (Object.keys(first).length !== Object.keys(second).length) { - return false; + unregister(name) { + return new Promise(resolve => { + if (!this._overlays[name]) { + throw new Error('The overlay does not exist.'); + } else if (this._active === name) { + throw new Error('The overlay cannot be removed while it is active.'); } - for (let key in first) { - if (!isEntryEqual(first[key], second[key])) { - return false; + delete this._overlays[name]; + resolve(); + }); + } + open(name) { + return new Promise(resolve => { + if (!this._overlays[name]) { + throw new Error('The overlay does not exist.'); + } else if (this._active) { + if (this._overlays[name].canForceClose) { + this._closeThroughCaller(); + } else if (this._active === name) { + throw new Error('The overlay is already active.'); + } else { + throw new Error('Another overlay is currently active.'); } } - return true; - } - return first === second || Number.isNaN(first) && Number.isNaN(second); + this._active = name; + this._overlays[this._active].element.classList.remove('hidden'); + this._overlays[this._active].container.classList.remove('hidden'); + window.addEventListener('keydown', this._keyDownBound); + resolve(); + }); + } + close(name) { + return new Promise(resolve => { + if (!this._overlays[name]) { + throw new Error('The overlay does not exist.'); + } else if (!this._active) { + throw new Error('The overlay is currently not active.'); + } else if (this._active !== name) { + throw new Error('Another overlay is currently active.'); + } + this._overlays[this._active].container.classList.add('hidden'); + this._overlays[this._active].element.classList.add('hidden'); + this._active = null; + window.removeEventListener('keydown', this._keyDownBound); + resolve(); + }); + } + _keyDown(evt) { + if (this._active && evt.keyCode === 27) { + this._closeThroughCaller(); + evt.preventDefault(); + } + } + _closeThroughCaller() { + if (this._overlays[this._active].callerCloseMethod) { + this._overlays[this._active].callerCloseMethod(); + } + if (this._active) { + this.close(this._active); + } + } +} +exports.OverlayManager = OverlayManager; + +/***/ }), +/* 15 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.PasswordPrompt = undefined; + +var _ui_utils = __webpack_require__(0); + +var _pdfjsLib = __webpack_require__(1); + +class PasswordPrompt { + constructor(options, overlayManager, l10n = _ui_utils.NullL10n) { + this.overlayName = options.overlayName; + this.container = options.container; + this.label = options.label; + this.input = options.input; + this.submitButton = options.submitButton; + this.cancelButton = options.cancelButton; + this.overlayManager = overlayManager; + this.l10n = l10n; + this.updateCallback = null; + this.reason = null; + this.submitButton.addEventListener('click', this.verify.bind(this)); + this.cancelButton.addEventListener('click', this.close.bind(this)); + this.input.addEventListener('keydown', e => { + if (e.keyCode === 13) { + this.verify(); + } + }); + this.overlayManager.register(this.overlayName, this.container, this.close.bind(this), true); } - if (!(firstDest instanceof Array && secondDest instanceof Array)) { - return false; + open() { + this.overlayManager.open(this.overlayName).then(() => { + this.input.focus(); + let promptString; + if (this.reason === _pdfjsLib.PasswordResponses.INCORRECT_PASSWORD) { + promptString = this.l10n.get('password_invalid', null, 'Invalid password. Please try again.'); + } else { + promptString = this.l10n.get('password_label', null, 'Enter the password to open this PDF file.'); + } + promptString.then(msg => { + this.label.textContent = msg; + }); + }); } - if (firstDest.length !== secondDest.length) { - return false; + close() { + this.overlayManager.close(this.overlayName).then(() => { + this.input.value = ''; + }); } - for (let i = 0, ii = firstDest.length; i < ii; i++) { - if (!isEntryEqual(firstDest[i], secondDest[i])) { - return false; + verify() { + let password = this.input.value; + if (password && password.length > 0) { + this.close(); + return this.updateCallback(password); } } - return true; + setUpdateCallback(updateCallback, reason) { + this.updateCallback = updateCallback; + this.reason = reason; + } } -exports.PDFHistory = PDFHistory; -exports.isDestHashesEqual = isDestHashesEqual; -exports.isDestArraysEqual = isDestArraysEqual; +exports.PasswordPrompt = PasswordPrompt; /***/ }), -/* 19 */ +/* 16 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -5143,139 +5114,111 @@ exports.isDestArraysEqual = isDestArraysEqual; Object.defineProperty(exports, "__esModule", { value: true }); -exports.PDFOutlineViewer = undefined; +exports.PDFAttachmentViewer = undefined; var _pdfjsLib = __webpack_require__(1); -const DEFAULT_TITLE = '\u2013'; -class PDFOutlineViewer { - constructor({ container, linkService, eventBus }) { +class PDFAttachmentViewer { + constructor({ container, eventBus, downloadManager }) { this.container = container; - this.linkService = linkService; this.eventBus = eventBus; + this.downloadManager = downloadManager; this.reset(); + this.eventBus.on('fileattachmentannotation', this._appendAttachment.bind(this)); } - reset() { - this.outline = null; - this.lastToggleIsShow = true; + reset(keepRenderedCapability = false) { + this.attachments = null; this.container.textContent = ''; - this.container.classList.remove('outlineWithDeepNesting'); + if (!keepRenderedCapability) { + this._renderedCapability = (0, _pdfjsLib.createPromiseCapability)(); + } } - _dispatchEvent(outlineCount) { - this.eventBus.dispatch('outlineloaded', { + _dispatchEvent(attachmentsCount) { + this._renderedCapability.resolve(); + this.eventBus.dispatch('attachmentsloaded', { source: this, - outlineCount + attachmentsCount }); } - _bindLink(element, { url, newWindow, dest }) { - let { linkService } = this; - if (url) { - (0, _pdfjsLib.addLinkAttributes)(element, { - url, - target: newWindow ? _pdfjsLib.LinkTarget.BLANK : linkService.externalLinkTarget, - rel: linkService.externalLinkRel - }); - return; + _bindPdfLink(button, content, filename) { + if (this.downloadManager.disableCreateObjectURL) { + throw new Error('bindPdfLink: Unsupported "disableCreateObjectURL" value.'); } - element.href = linkService.getDestinationHash(dest); - element.onclick = () => { - if (dest) { - linkService.navigateTo(dest); + let blobUrl; + button.onclick = function () { + if (!blobUrl) { + blobUrl = (0, _pdfjsLib.createObjectURL)(content, 'application/pdf'); } + let viewerUrl; + viewerUrl = blobUrl + '?' + encodeURIComponent(filename); + window.open(viewerUrl); return false; }; } - _setStyles(element, { bold, italic }) { - let styleStr = ''; - if (bold) { - styleStr += 'font-weight: bold;'; - } - if (italic) { - styleStr += 'font-style: italic;'; - } - if (styleStr) { - element.setAttribute('style', styleStr); - } - } - _addToggleButton(div) { - let toggler = document.createElement('div'); - toggler.className = 'outlineItemToggler'; - toggler.onclick = evt => { - evt.stopPropagation(); - toggler.classList.toggle('outlineItemsHidden'); - if (evt.shiftKey) { - let shouldShowAll = !toggler.classList.contains('outlineItemsHidden'); - this._toggleOutlineItem(div, shouldShowAll); - } + _bindLink(button, content, filename) { + button.onclick = () => { + this.downloadManager.downloadData(content, filename, ''); + return false; }; - div.insertBefore(toggler, div.firstChild); } - _toggleOutlineItem(root, show) { - this.lastToggleIsShow = show; - let togglers = root.querySelectorAll('.outlineItemToggler'); - for (let i = 0, ii = togglers.length; i < ii; ++i) { - togglers[i].classList[show ? 'remove' : 'add']('outlineItemsHidden'); + render({ attachments, keepRenderedCapability = false }) { + let attachmentsCount = 0; + if (this.attachments) { + this.reset(keepRenderedCapability === true); } - } - toggleOutlineTree() { - if (!this.outline) { + this.attachments = attachments || null; + if (!attachments) { + this._dispatchEvent(attachmentsCount); return; } - this._toggleOutlineItem(this.container, !this.lastToggleIsShow); - } - render({ outline }) { - let outlineCount = 0; - if (this.outline) { - this.reset(); - } - this.outline = outline || null; - if (!outline) { - this._dispatchEvent(outlineCount); - return; + let names = Object.keys(attachments).sort(function (a, b) { + return a.toLowerCase().localeCompare(b.toLowerCase()); + }); + attachmentsCount = names.length; + for (let i = 0; i < attachmentsCount; i++) { + let item = attachments[names[i]]; + let filename = (0, _pdfjsLib.removeNullCharacters)((0, _pdfjsLib.getFilenameFromUrl)(item.filename)); + let div = document.createElement('div'); + div.className = 'attachmentsItem'; + let button = document.createElement('button'); + button.textContent = filename; + if (/\.pdf$/i.test(filename) && !this.downloadManager.disableCreateObjectURL) { + this._bindPdfLink(button, item.content, filename); + } else { + this._bindLink(button, item.content, filename); + } + div.appendChild(button); + this.container.appendChild(div); } - let fragment = document.createDocumentFragment(); - let queue = [{ - parent: fragment, - items: this.outline - }]; - let hasAnyNesting = false; - while (queue.length > 0) { - let levelData = queue.shift(); - for (let i = 0, len = levelData.items.length; i < len; i++) { - let item = levelData.items[i]; - let div = document.createElement('div'); - div.className = 'outlineItem'; - let element = document.createElement('a'); - this._bindLink(element, item); - this._setStyles(element, item); - element.textContent = (0, _pdfjsLib.removeNullCharacters)(item.title) || DEFAULT_TITLE; - div.appendChild(element); - if (item.items.length > 0) { - hasAnyNesting = true; - this._addToggleButton(div); - let itemsDiv = document.createElement('div'); - itemsDiv.className = 'outlineItems'; - div.appendChild(itemsDiv); - queue.push({ - parent: itemsDiv, - items: item.items - }); + this._dispatchEvent(attachmentsCount); + } + _appendAttachment({ id, filename, content }) { + this._renderedCapability.promise.then(() => { + let attachments = this.attachments; + if (!attachments) { + attachments = Object.create(null); + } else { + for (let name in attachments) { + if (id === name) { + return; + } } - levelData.parent.appendChild(div); - outlineCount++; } - } - if (hasAnyNesting) { - this.container.classList.add('outlineWithDeepNesting'); - } - this.container.appendChild(fragment); - this._dispatchEvent(outlineCount); + attachments[id] = { + filename, + content + }; + this.render({ + attachments, + keepRenderedCapability: true + }); + }); } } -exports.PDFOutlineViewer = PDFOutlineViewer; +exports.PDFAttachmentViewer = PDFAttachmentViewer; /***/ }), -/* 20 */ +/* 17 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -5284,315 +5227,424 @@ exports.PDFOutlineViewer = PDFOutlineViewer; Object.defineProperty(exports, "__esModule", { value: true }); -exports.PDFPresentationMode = undefined; +exports.PDFDocumentProperties = undefined; var _ui_utils = __webpack_require__(0); -const DELAY_BEFORE_RESETTING_SWITCH_IN_PROGRESS = 1500; -const DELAY_BEFORE_HIDING_CONTROLS = 3000; -const ACTIVE_SELECTOR = 'pdfPresentationMode'; -const CONTROLS_SELECTOR = 'pdfPresentationModeControls'; -const MOUSE_SCROLL_COOLDOWN_TIME = 50; -const PAGE_SWITCH_THRESHOLD = 0.1; -const SWIPE_MIN_DISTANCE_THRESHOLD = 50; -const SWIPE_ANGLE_THRESHOLD = Math.PI / 6; -class PDFPresentationMode { - constructor({ container, viewer = null, pdfViewer, eventBus, contextMenuItems = null }) { +var _pdfjsLib = __webpack_require__(1); + +const DEFAULT_FIELD_CONTENT = '-'; +const NON_METRIC_LOCALES = ['en-us', 'en-lr', 'my']; +const US_PAGE_NAMES = { + '8.5x11': 'Letter', + '8.5x14': 'Legal' +}; +const METRIC_PAGE_NAMES = { + '297x420': 'A3', + '210x297': 'A4' +}; +function getPageName(size, isPortrait, pageNames) { + const width = isPortrait ? size.width : size.height; + const height = isPortrait ? size.height : size.width; + return pageNames[`${width}x${height}`]; +} +class PDFDocumentProperties { + constructor({ overlayName, fields, container, closeButton }, overlayManager, eventBus, l10n = _ui_utils.NullL10n) { + this.overlayName = overlayName; + this.fields = fields; this.container = container; - this.viewer = viewer || container.firstElementChild; - this.pdfViewer = pdfViewer; - this.eventBus = eventBus; - this.active = false; - this.args = null; - this.contextMenuOpen = false; - this.mouseScrollTimeStamp = 0; - this.mouseScrollDelta = 0; - this.touchSwipeState = null; - if (contextMenuItems) { - contextMenuItems.contextFirstPage.addEventListener('click', () => { - this.contextMenuOpen = false; - this.eventBus.dispatch('firstpage'); - }); - contextMenuItems.contextLastPage.addEventListener('click', () => { - this.contextMenuOpen = false; - this.eventBus.dispatch('lastpage'); - }); - contextMenuItems.contextPageRotateCw.addEventListener('click', () => { - this.contextMenuOpen = false; - this.eventBus.dispatch('rotatecw'); + this.overlayManager = overlayManager; + this.l10n = l10n; + this._reset(); + if (closeButton) { + closeButton.addEventListener('click', this.close.bind(this)); + } + this.overlayManager.register(this.overlayName, this.container, this.close.bind(this)); + if (eventBus) { + eventBus.on('pagechanging', evt => { + this._currentPageNumber = evt.pageNumber; }); - contextMenuItems.contextPageRotateCcw.addEventListener('click', () => { - this.contextMenuOpen = false; - this.eventBus.dispatch('rotateccw'); + eventBus.on('rotationchanging', evt => { + this._pagesRotation = evt.pagesRotation; }); } + this._isNonMetricLocale = true; + l10n.getLanguage().then(locale => { + this._isNonMetricLocale = NON_METRIC_LOCALES.includes(locale); + }); } - request() { - if (this.switchInProgress || this.active || !this.viewer.hasChildNodes()) { - return false; - } - this._addFullscreenChangeListeners(); - this._setSwitchInProgress(); - this._notifyStateChange(); - if (this.container.requestFullscreen) { - this.container.requestFullscreen(); - } else if (this.container.mozRequestFullScreen) { - this.container.mozRequestFullScreen(); - } else if (this.container.webkitRequestFullscreen) { - this.container.webkitRequestFullscreen(Element.ALLOW_KEYBOARD_INPUT); - } else if (this.container.msRequestFullscreen) { - this.container.msRequestFullscreen(); - } else { - return false; - } - this.args = { - page: this.pdfViewer.currentPageNumber, - previousScale: this.pdfViewer.currentScaleValue + open() { + let freezeFieldData = data => { + Object.defineProperty(this, 'fieldData', { + value: Object.freeze(data), + writable: false, + enumerable: true, + configurable: true + }); }; - return true; - } - _mouseWheel(evt) { - if (!this.active) { - return; - } - evt.preventDefault(); - let delta = (0, _ui_utils.normalizeWheelEventDelta)(evt); - let currentTime = new Date().getTime(); - let storedTime = this.mouseScrollTimeStamp; - if (currentTime > storedTime && currentTime - storedTime < MOUSE_SCROLL_COOLDOWN_TIME) { - return; - } - if (this.mouseScrollDelta > 0 && delta < 0 || this.mouseScrollDelta < 0 && delta > 0) { - this._resetMouseScrollState(); - } - this.mouseScrollDelta += delta; - if (Math.abs(this.mouseScrollDelta) >= PAGE_SWITCH_THRESHOLD) { - let totalDelta = this.mouseScrollDelta; - this._resetMouseScrollState(); - let success = totalDelta > 0 ? this._goToPreviousPage() : this._goToNextPage(); - if (success) { - this.mouseScrollTimeStamp = currentTime; + Promise.all([this.overlayManager.open(this.overlayName), this._dataAvailableCapability.promise]).then(() => { + const currentPageNumber = this._currentPageNumber; + const pagesRotation = this._pagesRotation; + if (this.fieldData && currentPageNumber === this.fieldData['_currentPageNumber'] && pagesRotation === this.fieldData['_pagesRotation']) { + this._updateUI(); + return; } - } - } - get isFullscreen() { - return !!(document.fullscreenElement || document.mozFullScreen || document.webkitIsFullScreen || document.msFullscreenElement); + this.pdfDocument.getMetadata().then(({ info, metadata, contentDispositionFilename }) => { + return Promise.all([info, metadata, contentDispositionFilename || (0, _ui_utils.getPDFFileNameFromURL)(this.url), this._parseFileSize(this.maybeFileSize), this._parseDate(info.CreationDate), this._parseDate(info.ModDate), this.pdfDocument.getPage(currentPageNumber).then(pdfPage => { + return this._parsePageSize((0, _ui_utils.getPageSizeInches)(pdfPage), pagesRotation); + })]); + }).then(([info, metadata, fileName, fileSize, creationDate, modDate, pageSize]) => { + freezeFieldData({ + 'fileName': fileName, + 'fileSize': fileSize, + 'title': info.Title, + 'author': info.Author, + 'subject': info.Subject, + 'keywords': info.Keywords, + 'creationDate': creationDate, + 'modificationDate': modDate, + 'creator': info.Creator, + 'producer': info.Producer, + 'version': info.PDFFormatVersion, + 'pageCount': this.pdfDocument.numPages, + 'pageSize': pageSize, + '_currentPageNumber': currentPageNumber, + '_pagesRotation': pagesRotation + }); + this._updateUI(); + return this.pdfDocument.getDownloadInfo(); + }).then(({ length }) => { + this.maybeFileSize = length; + return this._parseFileSize(length); + }).then(fileSize => { + if (fileSize === this.fieldData['fileSize']) { + return; + } + let data = (0, _ui_utils.cloneObj)(this.fieldData); + data['fileSize'] = fileSize; + freezeFieldData(data); + this._updateUI(); + }); + }); } - _goToPreviousPage() { - let page = this.pdfViewer.currentPageNumber; - if (page <= 1) { - return false; - } - this.pdfViewer.currentPageNumber = page - 1; - return true; + close() { + this.overlayManager.close(this.overlayName); } - _goToNextPage() { - let page = this.pdfViewer.currentPageNumber; - if (page >= this.pdfViewer.pagesCount) { - return false; + setDocument(pdfDocument, url) { + if (this.pdfDocument) { + this._reset(); + this._updateUI(true); } - this.pdfViewer.currentPageNumber = page + 1; - return true; - } - _notifyStateChange() { - this.eventBus.dispatch('presentationmodechanged', { - source: this, - active: this.active, - switchInProgress: !!this.switchInProgress - }); - } - _setSwitchInProgress() { - if (this.switchInProgress) { - clearTimeout(this.switchInProgress); + if (!pdfDocument) { + return; } - this.switchInProgress = setTimeout(() => { - this._removeFullscreenChangeListeners(); - delete this.switchInProgress; - this._notifyStateChange(); - }, DELAY_BEFORE_RESETTING_SWITCH_IN_PROGRESS); + this.pdfDocument = pdfDocument; + this.url = url; + this._dataAvailableCapability.resolve(); } - _resetSwitchInProgress() { - if (this.switchInProgress) { - clearTimeout(this.switchInProgress); - delete this.switchInProgress; + setFileSize(fileSize) { + if (Number.isInteger(fileSize) && fileSize > 0) { + this.maybeFileSize = fileSize; } } - _enter() { - this.active = true; - this._resetSwitchInProgress(); - this._notifyStateChange(); - this.container.classList.add(ACTIVE_SELECTOR); - setTimeout(() => { - this.pdfViewer.currentPageNumber = this.args.page; - this.pdfViewer.currentScaleValue = 'page-fit'; - }, 0); - this._addWindowListeners(); - this._showControls(); - this.contextMenuOpen = false; - this.container.setAttribute('contextmenu', 'viewerContextMenu'); - window.getSelection().removeAllRanges(); - } - _exit() { - let page = this.pdfViewer.currentPageNumber; - this.container.classList.remove(ACTIVE_SELECTOR); - setTimeout(() => { - this.active = false; - this._removeFullscreenChangeListeners(); - this._notifyStateChange(); - this.pdfViewer.currentScaleValue = this.args.previousScale; - this.pdfViewer.currentPageNumber = page; - this.args = null; - }, 0); - this._removeWindowListeners(); - this._hideControls(); - this._resetMouseScrollState(); - this.container.removeAttribute('contextmenu'); - this.contextMenuOpen = false; + _reset() { + this.pdfDocument = null; + this.url = null; + this.maybeFileSize = 0; + delete this.fieldData; + this._dataAvailableCapability = (0, _pdfjsLib.createPromiseCapability)(); + this._currentPageNumber = 1; + this._pagesRotation = 0; } - _mouseDown(evt) { - if (this.contextMenuOpen) { - this.contextMenuOpen = false; - evt.preventDefault(); + _updateUI(reset = false) { + if (reset || !this.fieldData) { + for (let id in this.fields) { + this.fields[id].textContent = DEFAULT_FIELD_CONTENT; + } return; } - if (evt.button === 0) { - let isInternalLink = evt.target.href && evt.target.classList.contains('internalLink'); - if (!isInternalLink) { - evt.preventDefault(); - if (evt.shiftKey) { - this._goToPreviousPage(); - } else { - this._goToNextPage(); - } - } + if (this.overlayManager.active !== this.overlayName) { + return; } - } - _contextMenu() { - this.contextMenuOpen = true; - } - _showControls() { - if (this.controlsTimeout) { - clearTimeout(this.controlsTimeout); - } else { - this.container.classList.add(CONTROLS_SELECTOR); + for (let id in this.fields) { + let content = this.fieldData[id]; + this.fields[id].textContent = content || content === 0 ? content : DEFAULT_FIELD_CONTENT; } - this.controlsTimeout = setTimeout(() => { - this.container.classList.remove(CONTROLS_SELECTOR); - delete this.controlsTimeout; - }, DELAY_BEFORE_HIDING_CONTROLS); } - _hideControls() { - if (!this.controlsTimeout) { - return; + _parseFileSize(fileSize = 0) { + let kb = fileSize / 1024; + if (!kb) { + return Promise.resolve(undefined); + } else if (kb < 1024) { + return this.l10n.get('document_properties_kb', { + size_kb: (+kb.toPrecision(3)).toLocaleString(), + size_b: fileSize.toLocaleString() + }, '{{size_kb}} KB ({{size_b}} bytes)'); } - clearTimeout(this.controlsTimeout); - this.container.classList.remove(CONTROLS_SELECTOR); - delete this.controlsTimeout; + return this.l10n.get('document_properties_mb', { + size_mb: (+(kb / 1024).toPrecision(3)).toLocaleString(), + size_b: fileSize.toLocaleString() + }, '{{size_mb}} MB ({{size_b}} bytes)'); } - _resetMouseScrollState() { - this.mouseScrollTimeStamp = 0; - this.mouseScrollDelta = 0; + _parsePageSize(pageSizeInches, pagesRotation) { + if (!pageSizeInches) { + return Promise.resolve(undefined); + } + if (pagesRotation % 180 !== 0) { + pageSizeInches = { + width: pageSizeInches.height, + height: pageSizeInches.width + }; + } + const isPortrait = (0, _ui_utils.isPortraitOrientation)(pageSizeInches); + let sizeInches = { + width: Math.round(pageSizeInches.width * 100) / 100, + height: Math.round(pageSizeInches.height * 100) / 100 + }; + let sizeMillimeters = { + width: Math.round(pageSizeInches.width * 25.4 * 10) / 10, + height: Math.round(pageSizeInches.height * 25.4 * 10) / 10 + }; + let pageName = null; + let name = getPageName(sizeInches, isPortrait, US_PAGE_NAMES) || getPageName(sizeMillimeters, isPortrait, METRIC_PAGE_NAMES); + if (!name && !(Number.isInteger(sizeMillimeters.width) && Number.isInteger(sizeMillimeters.height))) { + const exactMillimeters = { + width: pageSizeInches.width * 25.4, + height: pageSizeInches.height * 25.4 + }; + const intMillimeters = { + width: Math.round(sizeMillimeters.width), + height: Math.round(sizeMillimeters.height) + }; + if (Math.abs(exactMillimeters.width - intMillimeters.width) < 0.1 && Math.abs(exactMillimeters.height - intMillimeters.height) < 0.1) { + name = getPageName(intMillimeters, isPortrait, METRIC_PAGE_NAMES); + if (name) { + sizeInches = { + width: Math.round(intMillimeters.width / 25.4 * 100) / 100, + height: Math.round(intMillimeters.height / 25.4 * 100) / 100 + }; + sizeMillimeters = intMillimeters; + } + } + } + if (name) { + pageName = this.l10n.get('document_properties_page_size_name_' + name.toLowerCase(), null, name); + } + return Promise.all([this._isNonMetricLocale ? sizeInches : sizeMillimeters, this.l10n.get('document_properties_page_size_unit_' + (this._isNonMetricLocale ? 'inches' : 'millimeters'), null, this._isNonMetricLocale ? 'in' : 'mm'), pageName, this.l10n.get('document_properties_page_size_orientation_' + (isPortrait ? 'portrait' : 'landscape'), null, isPortrait ? 'portrait' : 'landscape')]).then(([{ width, height }, unit, name, orientation]) => { + return this.l10n.get('document_properties_page_size_dimension_' + (name ? 'name_' : '') + 'string', { + width: width.toLocaleString(), + height: height.toLocaleString(), + unit, + name, + orientation + }, '{{width}} Ă— {{height}} {{unit}} (' + (name ? '{{name}}, ' : '') + '{{orientation}})'); + }); } - _touchSwipe(evt) { - if (!this.active) { + _parseDate(inputDate) { + if (!inputDate) { return; } - if (evt.touches.length > 1) { - this.touchSwipeState = null; - return; + let dateToParse = inputDate; + if (dateToParse.substring(0, 2) === 'D:') { + dateToParse = dateToParse.substring(2); } - switch (evt.type) { - case 'touchstart': - this.touchSwipeState = { - startX: evt.touches[0].pageX, - startY: evt.touches[0].pageY, - endX: evt.touches[0].pageX, - endY: evt.touches[0].pageY - }; + let year = parseInt(dateToParse.substring(0, 4), 10); + let month = parseInt(dateToParse.substring(4, 6), 10) - 1; + let day = parseInt(dateToParse.substring(6, 8), 10); + let hours = parseInt(dateToParse.substring(8, 10), 10); + let minutes = parseInt(dateToParse.substring(10, 12), 10); + let seconds = parseInt(dateToParse.substring(12, 14), 10); + let utRel = dateToParse.substring(14, 15); + let offsetHours = parseInt(dateToParse.substring(15, 17), 10); + let offsetMinutes = parseInt(dateToParse.substring(18, 20), 10); + if (utRel === '-') { + hours += offsetHours; + minutes += offsetMinutes; + } else if (utRel === '+') { + hours -= offsetHours; + minutes -= offsetMinutes; + } + let date = new Date(Date.UTC(year, month, day, hours, minutes, seconds)); + let dateString = date.toLocaleDateString(); + let timeString = date.toLocaleTimeString(); + return this.l10n.get('document_properties_date_string', { + date: dateString, + time: timeString + }, '{{date}}, {{time}}'); + } +} +exports.PDFDocumentProperties = PDFDocumentProperties; + +/***/ }), +/* 18 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.PDFFindBar = undefined; + +var _pdf_find_controller = __webpack_require__(9); + +var _ui_utils = __webpack_require__(0); + +class PDFFindBar { + constructor(options, l10n = _ui_utils.NullL10n) { + this.opened = false; + this.bar = options.bar || null; + this.toggleButton = options.toggleButton || null; + this.findField = options.findField || null; + this.highlightAll = options.highlightAllCheckbox || null; + this.caseSensitive = options.caseSensitiveCheckbox || null; + this.findMsg = options.findMsg || null; + this.findResultsCount = options.findResultsCount || null; + this.findStatusIcon = options.findStatusIcon || null; + this.findPreviousButton = options.findPreviousButton || null; + this.findNextButton = options.findNextButton || null; + this.findController = options.findController || null; + this.eventBus = options.eventBus; + this.l10n = l10n; + if (this.findController === null) { + throw new Error('PDFFindBar cannot be used without a ' + 'PDFFindController instance.'); + } + this.toggleButton.addEventListener('click', () => { + this.toggle(); + }); + this.findField.addEventListener('input', () => { + this.dispatchEvent(''); + }); + this.bar.addEventListener('keydown', e => { + switch (e.keyCode) { + case 13: + if (e.target === this.findField) { + this.dispatchEvent('again', e.shiftKey); + } + break; + case 27: + this.close(); + break; + } + }); + this.findPreviousButton.addEventListener('click', () => { + this.dispatchEvent('again', true); + }); + this.findNextButton.addEventListener('click', () => { + this.dispatchEvent('again', false); + }); + this.highlightAll.addEventListener('click', () => { + this.dispatchEvent('highlightallchange'); + }); + this.caseSensitive.addEventListener('click', () => { + this.dispatchEvent('casesensitivitychange'); + }); + this.eventBus.on('resize', this._adjustWidth.bind(this)); + } + reset() { + this.updateUIState(); + } + dispatchEvent(type, findPrev) { + this.eventBus.dispatch('find', { + source: this, + type, + query: this.findField.value, + caseSensitive: this.caseSensitive.checked, + phraseSearch: true, + highlightAll: this.highlightAll.checked, + findPrevious: findPrev + }); + } + updateUIState(state, previous, matchCount) { + let notFound = false; + let findMsg = ''; + let status = ''; + switch (state) { + case _pdf_find_controller.FindState.FOUND: break; - case 'touchmove': - if (this.touchSwipeState === null) { - return; - } - this.touchSwipeState.endX = evt.touches[0].pageX; - this.touchSwipeState.endY = evt.touches[0].pageY; - evt.preventDefault(); + case _pdf_find_controller.FindState.PENDING: + status = 'pending'; + break; + case _pdf_find_controller.FindState.NOT_FOUND: + findMsg = this.l10n.get('find_not_found', null, 'Phrase not found'); + notFound = true; break; - case 'touchend': - if (this.touchSwipeState === null) { - return; - } - let delta = 0; - let dx = this.touchSwipeState.endX - this.touchSwipeState.startX; - let dy = this.touchSwipeState.endY - this.touchSwipeState.startY; - let absAngle = Math.abs(Math.atan2(dy, dx)); - if (Math.abs(dx) > SWIPE_MIN_DISTANCE_THRESHOLD && (absAngle <= SWIPE_ANGLE_THRESHOLD || absAngle >= Math.PI - SWIPE_ANGLE_THRESHOLD)) { - delta = dx; - } else if (Math.abs(dy) > SWIPE_MIN_DISTANCE_THRESHOLD && Math.abs(absAngle - Math.PI / 2) <= SWIPE_ANGLE_THRESHOLD) { - delta = dy; - } - if (delta > 0) { - this._goToPreviousPage(); - } else if (delta < 0) { - this._goToNextPage(); + case _pdf_find_controller.FindState.WRAPPED: + if (previous) { + findMsg = this.l10n.get('find_reached_top', null, 'Reached top of document, continued from bottom'); + } else { + findMsg = this.l10n.get('find_reached_bottom', null, 'Reached end of document, continued from top'); } break; } + if (notFound) { + this.findField.classList.add('notFound'); + } else { + this.findField.classList.remove('notFound'); + } + this.findField.setAttribute('data-status', status); + Promise.resolve(findMsg).then(msg => { + this.findMsg.textContent = msg; + this._adjustWidth(); + }); + this.updateResultsCount(matchCount); } - _addWindowListeners() { - this.showControlsBind = this._showControls.bind(this); - this.mouseDownBind = this._mouseDown.bind(this); - this.mouseWheelBind = this._mouseWheel.bind(this); - this.resetMouseScrollStateBind = this._resetMouseScrollState.bind(this); - this.contextMenuBind = this._contextMenu.bind(this); - this.touchSwipeBind = this._touchSwipe.bind(this); - window.addEventListener('mousemove', this.showControlsBind); - window.addEventListener('mousedown', this.mouseDownBind); - window.addEventListener('wheel', this.mouseWheelBind); - window.addEventListener('keydown', this.resetMouseScrollStateBind); - window.addEventListener('contextmenu', this.contextMenuBind); - window.addEventListener('touchstart', this.touchSwipeBind); - window.addEventListener('touchmove', this.touchSwipeBind); - window.addEventListener('touchend', this.touchSwipeBind); + updateResultsCount(matchCount) { + if (!this.findResultsCount) { + return; + } + if (!matchCount) { + this.findResultsCount.classList.add('hidden'); + this.findResultsCount.textContent = ''; + } else { + this.findResultsCount.textContent = matchCount.toLocaleString(); + this.findResultsCount.classList.remove('hidden'); + } + this._adjustWidth(); } - _removeWindowListeners() { - window.removeEventListener('mousemove', this.showControlsBind); - window.removeEventListener('mousedown', this.mouseDownBind); - window.removeEventListener('wheel', this.mouseWheelBind); - window.removeEventListener('keydown', this.resetMouseScrollStateBind); - window.removeEventListener('contextmenu', this.contextMenuBind); - window.removeEventListener('touchstart', this.touchSwipeBind); - window.removeEventListener('touchmove', this.touchSwipeBind); - window.removeEventListener('touchend', this.touchSwipeBind); - delete this.showControlsBind; - delete this.mouseDownBind; - delete this.mouseWheelBind; - delete this.resetMouseScrollStateBind; - delete this.contextMenuBind; - delete this.touchSwipeBind; + open() { + if (!this.opened) { + this.opened = true; + this.toggleButton.classList.add('toggled'); + this.bar.classList.remove('hidden'); + } + this.findField.select(); + this.findField.focus(); + this._adjustWidth(); } - _fullscreenChange() { - if (this.isFullscreen) { - this._enter(); - } else { - this._exit(); + close() { + if (!this.opened) { + return; } + this.opened = false; + this.toggleButton.classList.remove('toggled'); + this.bar.classList.add('hidden'); + this.findController.active = false; } - _addFullscreenChangeListeners() { - this.fullscreenChangeBind = this._fullscreenChange.bind(this); - window.addEventListener('fullscreenchange', this.fullscreenChangeBind); - window.addEventListener('mozfullscreenchange', this.fullscreenChangeBind); + toggle() { + if (this.opened) { + this.close(); + } else { + this.open(); + } } - _removeFullscreenChangeListeners() { - window.removeEventListener('fullscreenchange', this.fullscreenChangeBind); - window.removeEventListener('mozfullscreenchange', this.fullscreenChangeBind); - delete this.fullscreenChangeBind; + _adjustWidth() { + if (!this.opened) { + return; + } + this.bar.classList.remove('wrapContainers'); + let findbarHeight = this.bar.clientHeight; + let inputContainerHeight = this.bar.firstElementChild.clientHeight; + if (findbarHeight > inputContainerHeight) { + this.bar.classList.add('wrapContainers'); + } } } -exports.PDFPresentationMode = PDFPresentationMode; +exports.PDFFindBar = PDFFindBar; /***/ }), -/* 21 */ +/* 19 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -5601,307 +5653,375 @@ exports.PDFPresentationMode = PDFPresentationMode; Object.defineProperty(exports, "__esModule", { value: true }); -exports.PDFSidebarResizer = undefined; +exports.isDestArraysEqual = exports.isDestHashesEqual = exports.PDFHistory = undefined; var _ui_utils = __webpack_require__(0); -const SIDEBAR_WIDTH_VAR = '--sidebar-width'; -const SIDEBAR_MIN_WIDTH = 200; -const SIDEBAR_RESIZING_CLASS = 'sidebarResizing'; -class PDFSidebarResizer { - constructor(options, eventBus, l10n = _ui_utils.NullL10n) { - this.enabled = false; - this.isRTL = false; - this.sidebarOpen = false; - this.doc = document.documentElement; - this._width = null; - this._outerContainerWidth = null; +var _dom_events = __webpack_require__(2); + +const HASH_CHANGE_TIMEOUT = 1000; +const POSITION_UPDATED_THRESHOLD = 50; +const UPDATE_VIEWAREA_TIMEOUT = 1000; +function getCurrentHash() { + return document.location.hash; +} +function parseCurrentHash(linkService) { + let hash = unescape(getCurrentHash()).substring(1); + let params = (0, _ui_utils.parseQueryString)(hash); + let page = params.page | 0; + if (!(Number.isInteger(page) && page > 0 && page <= linkService.pagesCount)) { + page = null; + } + return { + hash, + page, + rotation: linkService.rotation + }; +} +class PDFHistory { + constructor({ linkService, eventBus }) { + this.linkService = linkService; + this.eventBus = eventBus || (0, _dom_events.getGlobalEventBus)(); + this.initialized = false; + this.initialBookmark = null; + this.initialRotation = null; this._boundEvents = Object.create(null); - this.outerContainer = options.outerContainer; - this.resizer = options.resizer; - this.eventBus = eventBus; - this.l10n = l10n; - if (typeof CSS === 'undefined' || typeof CSS.supports !== 'function' || !CSS.supports(SIDEBAR_WIDTH_VAR, `calc(-1 * ${SIDEBAR_MIN_WIDTH}px)`)) { - console.warn('PDFSidebarResizer: ' + 'The browser does not support resizing of the sidebar.'); + this._isViewerInPresentationMode = false; + this._isPagesLoaded = false; + this.eventBus.on('presentationmodechanged', evt => { + this._isViewerInPresentationMode = evt.active || evt.switchInProgress; + }); + this.eventBus.on('pagesloaded', evt => { + this._isPagesLoaded = !!evt.pagesCount; + }); + } + initialize(fingerprint, resetHistory = false) { + if (!fingerprint || typeof fingerprint !== 'string') { + console.error('PDFHistory.initialize: The "fingerprint" must be a non-empty string.'); + return; + } + let reInitialized = this.initialized && this.fingerprint !== fingerprint; + this.fingerprint = fingerprint; + if (!this.initialized) { + this._bindEvents(); + } + let state = window.history.state; + this.initialized = true; + this.initialBookmark = null; + this.initialRotation = null; + this._popStateInProgress = false; + this._blockHashChange = 0; + this._currentHash = getCurrentHash(); + this._numPositionUpdates = 0; + this._uid = this._maxUid = 0; + this._destination = null; + this._position = null; + if (!this._isValidState(state) || resetHistory) { + let { hash, page, rotation } = parseCurrentHash(this.linkService); + if (!hash || reInitialized || resetHistory) { + this._pushOrReplaceState(null, true); + return; + } + this._pushOrReplaceState({ + hash, + page, + rotation + }, true); + return; + } + let destination = state.destination; + this._updateInternalState(destination, state.uid, true); + if (this._uid > this._maxUid) { + this._maxUid = this._uid; + } + if (destination.rotation !== undefined) { + this.initialRotation = destination.rotation; + } + if (destination.dest) { + this.initialBookmark = JSON.stringify(destination.dest); + this._destination.page = null; + } else if (destination.hash) { + this.initialBookmark = destination.hash; + } else if (destination.page) { + this.initialBookmark = `page=${destination.page}`; + } + } + push({ namedDest, explicitDest, pageNumber }) { + if (!this.initialized) { + return; + } + if (namedDest && typeof namedDest !== 'string' || !(explicitDest instanceof Array) || !(Number.isInteger(pageNumber) && pageNumber > 0 && pageNumber <= this.linkService.pagesCount)) { + console.error('PDFHistory.push: Invalid parameters.'); + return; + } + let hash = namedDest || JSON.stringify(explicitDest); + if (!hash) { + return; + } + let forceReplace = false; + if (this._destination && (isDestHashesEqual(this._destination.hash, hash) || isDestArraysEqual(this._destination.dest, explicitDest))) { + if (this._destination.page) { + return; + } + forceReplace = true; + } + if (this._popStateInProgress && !forceReplace) { return; } - this.enabled = true; - this.resizer.classList.remove('hidden'); - this.l10n.getDirection().then(dir => { - this.isRTL = dir === 'rtl'; - }); - this._addEventListeners(); + this._pushOrReplaceState({ + dest: explicitDest, + hash, + page: pageNumber, + rotation: this.linkService.rotation + }, forceReplace); + if (!this._popStateInProgress) { + this._popStateInProgress = true; + Promise.resolve().then(() => { + this._popStateInProgress = false; + }); + } } - get outerContainerWidth() { - if (!this._outerContainerWidth) { - this._outerContainerWidth = this.outerContainer.clientWidth; + pushCurrentPosition() { + if (!this.initialized || this._popStateInProgress) { + return; } - return this._outerContainerWidth; + this._tryPushCurrentPosition(); } - _updateWidth(width = 0) { - if (!this.enabled) { - return false; + back() { + if (!this.initialized || this._popStateInProgress) { + return; } - const maxWidth = Math.floor(this.outerContainerWidth / 2); - if (width > maxWidth) { - width = maxWidth; + let state = window.history.state; + if (this._isValidState(state) && state.uid > 0) { + window.history.back(); } - if (width < SIDEBAR_MIN_WIDTH) { - width = SIDEBAR_MIN_WIDTH; + } + forward() { + if (!this.initialized || this._popStateInProgress) { + return; } - if (width === this._width) { - return false; + let state = window.history.state; + if (this._isValidState(state) && state.uid < this._maxUid) { + window.history.forward(); } - this._width = width; - this.doc.style.setProperty(SIDEBAR_WIDTH_VAR, `${width}px`); - return true; } - _mouseMove(evt) { - let width = evt.clientX; - if (this.isRTL) { - width = this.outerContainerWidth - width; - } - this._updateWidth(width); + get popStateInProgress() { + return this.initialized && (this._popStateInProgress || this._blockHashChange > 0); } - _mouseUp(evt) { - this.outerContainer.classList.remove(SIDEBAR_RESIZING_CLASS); - this.eventBus.dispatch('resize', { source: this }); - let _boundEvents = this._boundEvents; - window.removeEventListener('mousemove', _boundEvents.mouseMove); - window.removeEventListener('mouseup', _boundEvents.mouseUp); + _pushOrReplaceState(destination, forceReplace = false) { + let shouldReplace = forceReplace || !this._destination; + let newState = { + fingerprint: this.fingerprint, + uid: shouldReplace ? this._uid : this._uid + 1, + destination + }; + this._updateInternalState(destination, newState.uid); + if (shouldReplace) { + window.history.replaceState(newState, ''); + } else { + this._maxUid = this._uid; + window.history.pushState(newState, ''); + } } - _addEventListeners() { - if (!this.enabled) { + _tryPushCurrentPosition(temporary = false) { + if (!this._position) { return; } - let _boundEvents = this._boundEvents; - _boundEvents.mouseMove = this._mouseMove.bind(this); - _boundEvents.mouseUp = this._mouseUp.bind(this); - this.resizer.addEventListener('mousedown', evt => { - if (evt.button !== 0) { + let position = this._position; + if (temporary) { + position = (0, _ui_utils.cloneObj)(this._position); + position.temporary = true; + } + if (!this._destination) { + this._pushOrReplaceState(position); + return; + } + if (this._destination.temporary) { + this._pushOrReplaceState(position, true); + return; + } + if (this._destination.hash === position.hash) { + return; + } + if (!this._destination.page && (POSITION_UPDATED_THRESHOLD <= 0 || this._numPositionUpdates <= POSITION_UPDATED_THRESHOLD)) { + return; + } + let forceReplace = false; + if (this._destination.page === position.first || this._destination.page === position.page) { + if (this._destination.dest || !this._destination.first) { return; } - this.outerContainer.classList.add(SIDEBAR_RESIZING_CLASS); - window.addEventListener('mousemove', _boundEvents.mouseMove); - window.addEventListener('mouseup', _boundEvents.mouseUp); - }); - this.eventBus.on('sidebarviewchanged', evt => { - this.sidebarOpen = !!(evt && evt.view); - }); - this.eventBus.on('resize', evt => { - if (evt && evt.source === window) { - this._outerContainerWidth = null; - if (this._width) { - if (this.sidebarOpen) { - this.outerContainer.classList.add(SIDEBAR_RESIZING_CLASS); - let updated = this._updateWidth(this._width); - Promise.resolve().then(() => { - this.outerContainer.classList.remove(SIDEBAR_RESIZING_CLASS); - if (updated) { - this.eventBus.dispatch('resize', { source: this }); - } - }); - } else { - this._updateWidth(this._width); - } - } - } - }); - } -} -exports.PDFSidebarResizer = PDFSidebarResizer; - -/***/ }), -/* 22 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.PDFThumbnailViewer = undefined; - -var _ui_utils = __webpack_require__(0); - -var _pdf_thumbnail_view = __webpack_require__(23); - -const THUMBNAIL_SCROLL_MARGIN = -19; -const THUMBNAIL_SELECTED_CLASS = 'selected'; -class PDFThumbnailViewer { - constructor({ container, linkService, renderingQueue, l10n = _ui_utils.NullL10n }) { - this.container = container; - this.linkService = linkService; - this.renderingQueue = renderingQueue; - this.l10n = l10n; - this.scroll = (0, _ui_utils.watchScroll)(this.container, this._scrollUpdated.bind(this)); - this._resetView(); - } - _scrollUpdated() { - this.renderingQueue.renderHighestPriority(); + forceReplace = true; + } + this._pushOrReplaceState(position, forceReplace); } - getThumbnail(index) { - return this._thumbnails[index]; + _isValidState(state) { + if (!state) { + return false; + } + if (state.fingerprint !== this.fingerprint) { + return false; + } + if (!Number.isInteger(state.uid) || state.uid < 0) { + return false; + } + if (state.destination === null || typeof state.destination !== 'object') { + return false; + } + return true; } - _getVisibleThumbs() { - return (0, _ui_utils.getVisibleElements)(this.container, this._thumbnails); + _updateInternalState(destination, uid, removeTemporary = false) { + if (this._updateViewareaTimeout) { + clearTimeout(this._updateViewareaTimeout); + this._updateViewareaTimeout = null; + } + if (removeTemporary && destination && destination.temporary) { + delete destination.temporary; + } + this._destination = destination; + this._uid = uid; + this._numPositionUpdates = 0; } - scrollThumbnailIntoView(pageNumber) { - if (!this.pdfDocument) { - return; + _updateViewarea({ location }) { + if (this._updateViewareaTimeout) { + clearTimeout(this._updateViewareaTimeout); + this._updateViewareaTimeout = null; } - const thumbnailView = this._thumbnails[pageNumber - 1]; - if (!thumbnailView) { - console.error('scrollThumbnailIntoView: Invalid "pageNumber" parameter.'); + this._position = { + hash: this._isViewerInPresentationMode ? `page=${location.pageNumber}` : location.pdfOpenParams.substring(1), + page: this.linkService.page, + first: location.pageNumber, + rotation: location.rotation + }; + if (this._popStateInProgress) { return; } - if (pageNumber !== this._currentPageNumber) { - const prevThumbnailView = this._thumbnails[this._currentPageNumber - 1]; - prevThumbnailView.div.classList.remove(THUMBNAIL_SELECTED_CLASS); - thumbnailView.div.classList.add(THUMBNAIL_SELECTED_CLASS); + if (POSITION_UPDATED_THRESHOLD > 0 && this._isPagesLoaded && this._destination && !this._destination.page) { + this._numPositionUpdates++; } - let visibleThumbs = this._getVisibleThumbs(); - let numVisibleThumbs = visibleThumbs.views.length; - if (numVisibleThumbs > 0) { - let first = visibleThumbs.first.id; - let last = numVisibleThumbs > 1 ? visibleThumbs.last.id : first; - let shouldScroll = false; - if (pageNumber <= first || pageNumber >= last) { - shouldScroll = true; - } else { - visibleThumbs.views.some(function (view) { - if (view.id !== pageNumber) { - return false; - } - shouldScroll = view.percent < 100; - return true; - }); - } - if (shouldScroll) { - (0, _ui_utils.scrollIntoView)(thumbnailView.div, { top: THUMBNAIL_SCROLL_MARGIN }); - } + if (UPDATE_VIEWAREA_TIMEOUT > 0) { + this._updateViewareaTimeout = setTimeout(() => { + if (!this._popStateInProgress) { + this._tryPushCurrentPosition(true); + } + this._updateViewareaTimeout = null; + }, UPDATE_VIEWAREA_TIMEOUT); } - this._currentPageNumber = pageNumber; } - get pagesRotation() { - return this._pagesRotation; - } - set pagesRotation(rotation) { - if (!(0, _ui_utils.isValidRotation)(rotation)) { - throw new Error('Invalid thumbnails rotation angle.'); - } - if (!this.pdfDocument) { + _popState({ state }) { + let newHash = getCurrentHash(), + hashChanged = this._currentHash !== newHash; + this._currentHash = newHash; + if (!state || false) { + this._uid++; + let { hash, page, rotation } = parseCurrentHash(this.linkService); + this._pushOrReplaceState({ + hash, + page, + rotation + }, true); return; } - if (this._pagesRotation === rotation) { + if (!this._isValidState(state)) { return; } - this._pagesRotation = rotation; - for (let i = 0, ii = this._thumbnails.length; i < ii; i++) { - this._thumbnails[i].update(rotation); + this._popStateInProgress = true; + if (hashChanged) { + this._blockHashChange++; + (0, _ui_utils.waitOnEventOrTimeout)({ + target: window, + name: 'hashchange', + delay: HASH_CHANGE_TIMEOUT + }).then(() => { + this._blockHashChange--; + }); } - } - cleanup() { - _pdf_thumbnail_view.PDFThumbnailView.cleanup(); - } - _resetView() { - this._thumbnails = []; - this._currentPageNumber = 1; - this._pageLabels = null; - this._pagesRotation = 0; - this._pagesRequests = []; - this.container.textContent = ''; - } - setDocument(pdfDocument) { - if (this.pdfDocument) { - this._cancelRendering(); - this._resetView(); + let destination = state.destination; + this._updateInternalState(destination, state.uid, true); + if (this._uid > this._maxUid) { + this._maxUid = this._uid; } - this.pdfDocument = pdfDocument; - if (!pdfDocument) { - return; + if ((0, _ui_utils.isValidRotation)(destination.rotation)) { + this.linkService.rotation = destination.rotation; } - pdfDocument.getPage(1).then(firstPage => { - let pagesCount = pdfDocument.numPages; - let viewport = firstPage.getViewport(1.0); - for (let pageNum = 1; pageNum <= pagesCount; ++pageNum) { - let thumbnail = new _pdf_thumbnail_view.PDFThumbnailView({ - container: this.container, - id: pageNum, - defaultViewport: viewport.clone(), - linkService: this.linkService, - renderingQueue: this.renderingQueue, - disableCanvasToImageConversion: false, - l10n: this.l10n - }); - this._thumbnails.push(thumbnail); - } - const thumbnailView = this._thumbnails[this._currentPageNumber - 1]; - thumbnailView.div.classList.add(THUMBNAIL_SELECTED_CLASS); - }).catch(reason => { - console.error('Unable to initialize thumbnail viewer', reason); + if (destination.dest) { + this.linkService.navigateTo(destination.dest); + } else if (destination.hash) { + this.linkService.setHash(destination.hash); + } else if (destination.page) { + this.linkService.page = destination.page; + } + Promise.resolve().then(() => { + this._popStateInProgress = false; }); } - _cancelRendering() { - for (let i = 0, ii = this._thumbnails.length; i < ii; i++) { - if (this._thumbnails[i]) { - this._thumbnails[i].cancelRendering(); + _bindEvents() { + let { _boundEvents, eventBus } = this; + _boundEvents.updateViewarea = this._updateViewarea.bind(this); + _boundEvents.popState = this._popState.bind(this); + _boundEvents.pageHide = evt => { + if (!this._destination || this._destination.temporary) { + this._tryPushCurrentPosition(); } - } + }; + eventBus.on('updateviewarea', _boundEvents.updateViewarea); + window.addEventListener('popstate', _boundEvents.popState); + window.addEventListener('pagehide', _boundEvents.pageHide); } - setPageLabels(labels) { - if (!this.pdfDocument) { - return; - } - if (!labels) { - this._pageLabels = null; - } else if (!(labels instanceof Array && this.pdfDocument.numPages === labels.length)) { - this._pageLabels = null; - console.error('PDFThumbnailViewer_setPageLabels: Invalid page labels.'); - } else { - this._pageLabels = labels; - } - for (let i = 0, ii = this._thumbnails.length; i < ii; i++) { - let label = this._pageLabels && this._pageLabels[i]; - this._thumbnails[i].setPageLabel(label); - } +} +function isDestHashesEqual(destHash, pushHash) { + if (typeof destHash !== 'string' || typeof pushHash !== 'string') { + return false; } - _ensurePdfPageLoaded(thumbView) { - if (thumbView.pdfPage) { - return Promise.resolve(thumbView.pdfPage); + if (destHash === pushHash) { + return true; + } + let { nameddest } = (0, _ui_utils.parseQueryString)(destHash); + if (nameddest === pushHash) { + return true; + } + return false; +} +function isDestArraysEqual(firstDest, secondDest) { + function isEntryEqual(first, second) { + if (typeof first !== typeof second) { + return false; } - let pageNumber = thumbView.id; - if (this._pagesRequests[pageNumber]) { - return this._pagesRequests[pageNumber]; + if (first instanceof Array || second instanceof Array) { + return false; } - let promise = this.pdfDocument.getPage(pageNumber).then(pdfPage => { - thumbView.setPdfPage(pdfPage); - this._pagesRequests[pageNumber] = null; - return pdfPage; - }).catch(reason => { - console.error('Unable to get page for thumb view', reason); - this._pagesRequests[pageNumber] = null; - }); - this._pagesRequests[pageNumber] = promise; - return promise; - } - forceRendering() { - let visibleThumbs = this._getVisibleThumbs(); - let thumbView = this.renderingQueue.getHighestPriority(visibleThumbs, this._thumbnails, this.scroll.down); - if (thumbView) { - this._ensurePdfPageLoaded(thumbView).then(() => { - this.renderingQueue.renderView(thumbView); - }); + if (first !== null && typeof first === 'object' && second !== null) { + if (Object.keys(first).length !== Object.keys(second).length) { + return false; + } + for (let key in first) { + if (!isEntryEqual(first[key], second[key])) { + return false; + } + } return true; } + return first === second || Number.isNaN(first) && Number.isNaN(second); + } + if (!(firstDest instanceof Array && secondDest instanceof Array)) { + return false; + } + if (firstDest.length !== secondDest.length) { return false; } + for (let i = 0, ii = firstDest.length; i < ii; i++) { + if (!isEntryEqual(firstDest[i], secondDest[i])) { + return false; + } + } + return true; } -exports.PDFThumbnailViewer = PDFThumbnailViewer; +exports.PDFHistory = PDFHistory; +exports.isDestHashesEqual = isDestHashesEqual; +exports.isDestArraysEqual = isDestArraysEqual; /***/ }), -/* 23 */ +/* 20 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -5910,382 +6030,456 @@ exports.PDFThumbnailViewer = PDFThumbnailViewer; Object.defineProperty(exports, "__esModule", { value: true }); -exports.PDFThumbnailView = undefined; +exports.PDFOutlineViewer = undefined; var _pdfjsLib = __webpack_require__(1); -var _ui_utils = __webpack_require__(0); - -var _pdf_rendering_queue = __webpack_require__(3); - -const MAX_NUM_SCALING_STEPS = 3; -const THUMBNAIL_CANVAS_BORDER_WIDTH = 1; -const THUMBNAIL_WIDTH = 98; -const TempImageFactory = function TempImageFactoryClosure() { - let tempCanvasCache = null; - return { - getCanvas(width, height) { - let tempCanvas = tempCanvasCache; - if (!tempCanvas) { - tempCanvas = document.createElement('canvas'); - tempCanvasCache = tempCanvas; - } - tempCanvas.width = width; - tempCanvas.height = height; - tempCanvas.mozOpaque = true; - let ctx = tempCanvas.getContext('2d', { alpha: false }); - ctx.save(); - ctx.fillStyle = 'rgb(255, 255, 255)'; - ctx.fillRect(0, 0, width, height); - ctx.restore(); - return tempCanvas; - }, - destroyCanvas() { - let tempCanvas = tempCanvasCache; - if (tempCanvas) { - tempCanvas.width = 0; - tempCanvas.height = 0; - } - tempCanvasCache = null; - } - }; -}(); -class PDFThumbnailView { - constructor({ container, id, defaultViewport, linkService, renderingQueue, disableCanvasToImageConversion = false, l10n = _ui_utils.NullL10n }) { - this.id = id; - this.renderingId = 'thumbnail' + id; - this.pageLabel = null; - this.pdfPage = null; - this.rotation = 0; - this.viewport = defaultViewport; - this.pdfPageRotate = defaultViewport.rotation; +const DEFAULT_TITLE = '\u2013'; +class PDFOutlineViewer { + constructor({ container, linkService, eventBus }) { + this.container = container; this.linkService = linkService; - this.renderingQueue = renderingQueue; - this.renderTask = null; - this.renderingState = _pdf_rendering_queue.RenderingStates.INITIAL; - this.resume = null; - this.disableCanvasToImageConversion = disableCanvasToImageConversion; - this.pageWidth = this.viewport.width; - this.pageHeight = this.viewport.height; - this.pageRatio = this.pageWidth / this.pageHeight; - this.canvasWidth = THUMBNAIL_WIDTH; - this.canvasHeight = this.canvasWidth / this.pageRatio | 0; - this.scale = this.canvasWidth / this.pageWidth; - this.l10n = l10n; - let anchor = document.createElement('a'); - anchor.href = linkService.getAnchorUrl('#page=' + id); - this.l10n.get('thumb_page_title', { page: id }, 'Page {{page}}').then(msg => { - anchor.title = msg; + this.eventBus = eventBus; + this.reset(); + } + reset() { + this.outline = null; + this.lastToggleIsShow = true; + this.container.textContent = ''; + this.container.classList.remove('outlineWithDeepNesting'); + } + _dispatchEvent(outlineCount) { + this.eventBus.dispatch('outlineloaded', { + source: this, + outlineCount }); - anchor.onclick = function () { - linkService.page = id; + } + _bindLink(element, { url, newWindow, dest }) { + let { linkService } = this; + if (url) { + (0, _pdfjsLib.addLinkAttributes)(element, { + url, + target: newWindow ? _pdfjsLib.LinkTarget.BLANK : linkService.externalLinkTarget, + rel: linkService.externalLinkRel + }); + return; + } + element.href = linkService.getDestinationHash(dest); + element.onclick = () => { + if (dest) { + linkService.navigateTo(dest); + } return false; }; - this.anchor = anchor; - let div = document.createElement('div'); - div.className = 'thumbnail'; - div.setAttribute('data-page-number', this.id); - this.div = div; - let ring = document.createElement('div'); - ring.className = 'thumbnailSelectionRing'; - let borderAdjustment = 2 * THUMBNAIL_CANVAS_BORDER_WIDTH; - ring.style.width = this.canvasWidth + borderAdjustment + 'px'; - ring.style.height = this.canvasHeight + borderAdjustment + 'px'; - this.ring = ring; - div.appendChild(ring); - anchor.appendChild(div); - container.appendChild(anchor); - } - setPdfPage(pdfPage) { - this.pdfPage = pdfPage; - this.pdfPageRotate = pdfPage.rotate; - let totalRotation = (this.rotation + this.pdfPageRotate) % 360; - this.viewport = pdfPage.getViewport(1, totalRotation); - this.reset(); } - reset() { - this.cancelRendering(); - this.pageWidth = this.viewport.width; - this.pageHeight = this.viewport.height; - this.pageRatio = this.pageWidth / this.pageHeight; - this.canvasHeight = this.canvasWidth / this.pageRatio | 0; - this.scale = this.canvasWidth / this.pageWidth; - this.div.removeAttribute('data-loaded'); - let ring = this.ring; - let childNodes = ring.childNodes; - for (let i = childNodes.length - 1; i >= 0; i--) { - ring.removeChild(childNodes[i]); + _setStyles(element, { bold, italic }) { + let styleStr = ''; + if (bold) { + styleStr += 'font-weight: bold;'; } - let borderAdjustment = 2 * THUMBNAIL_CANVAS_BORDER_WIDTH; - ring.style.width = this.canvasWidth + borderAdjustment + 'px'; - ring.style.height = this.canvasHeight + borderAdjustment + 'px'; - if (this.canvas) { - this.canvas.width = 0; - this.canvas.height = 0; - delete this.canvas; + if (italic) { + styleStr += 'font-style: italic;'; } - if (this.image) { - this.image.removeAttribute('src'); - delete this.image; + if (styleStr) { + element.setAttribute('style', styleStr); } } - update(rotation) { - if (typeof rotation !== 'undefined') { - this.rotation = rotation; - } - let totalRotation = (this.rotation + this.pdfPageRotate) % 360; - this.viewport = this.viewport.clone({ - scale: 1, - rotation: totalRotation - }); - this.reset(); + _addToggleButton(div) { + let toggler = document.createElement('div'); + toggler.className = 'outlineItemToggler'; + toggler.onclick = evt => { + evt.stopPropagation(); + toggler.classList.toggle('outlineItemsHidden'); + if (evt.shiftKey) { + let shouldShowAll = !toggler.classList.contains('outlineItemsHidden'); + this._toggleOutlineItem(div, shouldShowAll); + } + }; + div.insertBefore(toggler, div.firstChild); } - cancelRendering() { - if (this.renderTask) { - this.renderTask.cancel(); - this.renderTask = null; + _toggleOutlineItem(root, show) { + this.lastToggleIsShow = show; + let togglers = root.querySelectorAll('.outlineItemToggler'); + for (let i = 0, ii = togglers.length; i < ii; ++i) { + togglers[i].classList[show ? 'remove' : 'add']('outlineItemsHidden'); } - this.renderingState = _pdf_rendering_queue.RenderingStates.INITIAL; - this.resume = null; } - _getPageDrawContext(noCtxScale = false) { - let canvas = document.createElement('canvas'); - this.canvas = canvas; - canvas.mozOpaque = true; - let ctx = canvas.getContext('2d', { alpha: false }); - let outputScale = (0, _ui_utils.getOutputScale)(ctx); - canvas.width = this.canvasWidth * outputScale.sx | 0; - canvas.height = this.canvasHeight * outputScale.sy | 0; - canvas.style.width = this.canvasWidth + 'px'; - canvas.style.height = this.canvasHeight + 'px'; - if (!noCtxScale && outputScale.scaled) { - ctx.scale(outputScale.sx, outputScale.sy); + toggleOutlineTree() { + if (!this.outline) { + return; } - return ctx; + this._toggleOutlineItem(this.container, !this.lastToggleIsShow); } - _convertCanvasToImage() { - if (!this.canvas) { - return; + render({ outline }) { + let outlineCount = 0; + if (this.outline) { + this.reset(); } - if (this.renderingState !== _pdf_rendering_queue.RenderingStates.FINISHED) { + this.outline = outline || null; + if (!outline) { + this._dispatchEvent(outlineCount); return; } - let id = this.renderingId; - let className = 'thumbnailImage'; - if (this.disableCanvasToImageConversion) { - this.canvas.id = id; - this.canvas.className = className; - this.l10n.get('thumb_page_canvas', { page: this.pageId }, 'Thumbnail of Page {{page}}').then(msg => { - this.canvas.setAttribute('aria-label', msg); - }); - this.div.setAttribute('data-loaded', true); - this.ring.appendChild(this.canvas); - return; + let fragment = document.createDocumentFragment(); + let queue = [{ + parent: fragment, + items: this.outline + }]; + let hasAnyNesting = false; + while (queue.length > 0) { + let levelData = queue.shift(); + for (let i = 0, len = levelData.items.length; i < len; i++) { + let item = levelData.items[i]; + let div = document.createElement('div'); + div.className = 'outlineItem'; + let element = document.createElement('a'); + this._bindLink(element, item); + this._setStyles(element, item); + element.textContent = (0, _pdfjsLib.removeNullCharacters)(item.title) || DEFAULT_TITLE; + div.appendChild(element); + if (item.items.length > 0) { + hasAnyNesting = true; + this._addToggleButton(div); + let itemsDiv = document.createElement('div'); + itemsDiv.className = 'outlineItems'; + div.appendChild(itemsDiv); + queue.push({ + parent: itemsDiv, + items: item.items + }); + } + levelData.parent.appendChild(div); + outlineCount++; + } } - let image = document.createElement('img'); - image.id = id; - image.className = className; - this.l10n.get('thumb_page_canvas', { page: this.pageId }, 'Thumbnail of Page {{page}}').then(msg => { - image.setAttribute('aria-label', msg); - }); - image.style.width = this.canvasWidth + 'px'; - image.style.height = this.canvasHeight + 'px'; - image.src = this.canvas.toDataURL(); - this.image = image; - this.div.setAttribute('data-loaded', true); - this.ring.appendChild(image); - this.canvas.width = 0; - this.canvas.height = 0; - delete this.canvas; + if (hasAnyNesting) { + this.container.classList.add('outlineWithDeepNesting'); + } + this.container.appendChild(fragment); + this._dispatchEvent(outlineCount); } - draw() { - if (this.renderingState !== _pdf_rendering_queue.RenderingStates.INITIAL) { - console.error('Must be in new state before drawing'); - return Promise.resolve(undefined); +} +exports.PDFOutlineViewer = PDFOutlineViewer; + +/***/ }), +/* 21 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.PDFPresentationMode = undefined; + +var _ui_utils = __webpack_require__(0); + +const DELAY_BEFORE_RESETTING_SWITCH_IN_PROGRESS = 1500; +const DELAY_BEFORE_HIDING_CONTROLS = 3000; +const ACTIVE_SELECTOR = 'pdfPresentationMode'; +const CONTROLS_SELECTOR = 'pdfPresentationModeControls'; +const MOUSE_SCROLL_COOLDOWN_TIME = 50; +const PAGE_SWITCH_THRESHOLD = 0.1; +const SWIPE_MIN_DISTANCE_THRESHOLD = 50; +const SWIPE_ANGLE_THRESHOLD = Math.PI / 6; +class PDFPresentationMode { + constructor({ container, viewer = null, pdfViewer, eventBus, contextMenuItems = null }) { + this.container = container; + this.viewer = viewer || container.firstElementChild; + this.pdfViewer = pdfViewer; + this.eventBus = eventBus; + this.active = false; + this.args = null; + this.contextMenuOpen = false; + this.mouseScrollTimeStamp = 0; + this.mouseScrollDelta = 0; + this.touchSwipeState = null; + if (contextMenuItems) { + contextMenuItems.contextFirstPage.addEventListener('click', () => { + this.contextMenuOpen = false; + this.eventBus.dispatch('firstpage'); + }); + contextMenuItems.contextLastPage.addEventListener('click', () => { + this.contextMenuOpen = false; + this.eventBus.dispatch('lastpage'); + }); + contextMenuItems.contextPageRotateCw.addEventListener('click', () => { + this.contextMenuOpen = false; + this.eventBus.dispatch('rotatecw'); + }); + contextMenuItems.contextPageRotateCcw.addEventListener('click', () => { + this.contextMenuOpen = false; + this.eventBus.dispatch('rotateccw'); + }); } - this.renderingState = _pdf_rendering_queue.RenderingStates.RUNNING; - let renderCapability = (0, _pdfjsLib.createPromiseCapability)(); - let finishRenderTask = error => { - if (renderTask === this.renderTask) { - this.renderTask = null; - } - if (error instanceof _pdfjsLib.RenderingCancelledException) { - renderCapability.resolve(undefined); - return; - } - this.renderingState = _pdf_rendering_queue.RenderingStates.FINISHED; - this._convertCanvasToImage(); - if (!error) { - renderCapability.resolve(undefined); - } else { - renderCapability.reject(error); - } - }; - let ctx = this._getPageDrawContext(); - let drawViewport = this.viewport.clone({ scale: this.scale }); - let renderContinueCallback = cont => { - if (!this.renderingQueue.isHighestPriority(this)) { - this.renderingState = _pdf_rendering_queue.RenderingStates.PAUSED; - this.resume = () => { - this.renderingState = _pdf_rendering_queue.RenderingStates.RUNNING; - cont(); - }; - return; - } - cont(); - }; - let renderContext = { - canvasContext: ctx, - viewport: drawViewport + } + request() { + if (this.switchInProgress || this.active || !this.viewer.hasChildNodes()) { + return false; + } + this._addFullscreenChangeListeners(); + this._setSwitchInProgress(); + this._notifyStateChange(); + if (this.container.requestFullscreen) { + this.container.requestFullscreen(); + } else if (this.container.mozRequestFullScreen) { + this.container.mozRequestFullScreen(); + } else if (this.container.webkitRequestFullscreen) { + this.container.webkitRequestFullscreen(Element.ALLOW_KEYBOARD_INPUT); + } else if (this.container.msRequestFullscreen) { + this.container.msRequestFullscreen(); + } else { + return false; + } + this.args = { + page: this.pdfViewer.currentPageNumber, + previousScale: this.pdfViewer.currentScaleValue }; - let renderTask = this.renderTask = this.pdfPage.render(renderContext); - renderTask.onContinue = renderContinueCallback; - renderTask.promise.then(function () { - finishRenderTask(null); - }, function (error) { - finishRenderTask(error); - }); - return renderCapability.promise; + return true; } - setImage(pageView) { - if (this.renderingState !== _pdf_rendering_queue.RenderingStates.INITIAL) { + _mouseWheel(evt) { + if (!this.active) { return; } - let img = pageView.canvas; - if (!img) { + evt.preventDefault(); + let delta = (0, _ui_utils.normalizeWheelEventDelta)(evt); + let currentTime = new Date().getTime(); + let storedTime = this.mouseScrollTimeStamp; + if (currentTime > storedTime && currentTime - storedTime < MOUSE_SCROLL_COOLDOWN_TIME) { return; } - if (!this.pdfPage) { - this.setPdfPage(pageView.pdfPage); - } - this.renderingState = _pdf_rendering_queue.RenderingStates.FINISHED; - let ctx = this._getPageDrawContext(true); - let canvas = ctx.canvas; - if (img.width <= 2 * canvas.width) { - ctx.drawImage(img, 0, 0, img.width, img.height, 0, 0, canvas.width, canvas.height); - this._convertCanvasToImage(); - return; + if (this.mouseScrollDelta > 0 && delta < 0 || this.mouseScrollDelta < 0 && delta > 0) { + this._resetMouseScrollState(); } - let reducedWidth = canvas.width << MAX_NUM_SCALING_STEPS; - let reducedHeight = canvas.height << MAX_NUM_SCALING_STEPS; - let reducedImage = TempImageFactory.getCanvas(reducedWidth, reducedHeight); - let reducedImageCtx = reducedImage.getContext('2d'); - while (reducedWidth > img.width || reducedHeight > img.height) { - reducedWidth >>= 1; - reducedHeight >>= 1; + this.mouseScrollDelta += delta; + if (Math.abs(this.mouseScrollDelta) >= PAGE_SWITCH_THRESHOLD) { + let totalDelta = this.mouseScrollDelta; + this._resetMouseScrollState(); + let success = totalDelta > 0 ? this._goToPreviousPage() : this._goToNextPage(); + if (success) { + this.mouseScrollTimeStamp = currentTime; + } } - reducedImageCtx.drawImage(img, 0, 0, img.width, img.height, 0, 0, reducedWidth, reducedHeight); - while (reducedWidth > 2 * canvas.width) { - reducedImageCtx.drawImage(reducedImage, 0, 0, reducedWidth, reducedHeight, 0, 0, reducedWidth >> 1, reducedHeight >> 1); - reducedWidth >>= 1; - reducedHeight >>= 1; + } + get isFullscreen() { + return !!(document.fullscreenElement || document.mozFullScreen || document.webkitIsFullScreen || document.msFullscreenElement); + } + _goToPreviousPage() { + let page = this.pdfViewer.currentPageNumber; + if (page <= 1) { + return false; } - ctx.drawImage(reducedImage, 0, 0, reducedWidth, reducedHeight, 0, 0, canvas.width, canvas.height); - this._convertCanvasToImage(); + this.pdfViewer.currentPageNumber = page - 1; + return true; } - get pageId() { - return this.pageLabel !== null ? this.pageLabel : this.id; + _goToNextPage() { + let page = this.pdfViewer.currentPageNumber; + if (page >= this.pdfViewer.pagesCount) { + return false; + } + this.pdfViewer.currentPageNumber = page + 1; + return true; } - setPageLabel(label) { - this.pageLabel = typeof label === 'string' ? label : null; - this.l10n.get('thumb_page_title', { page: this.pageId }, 'Page {{page}}').then(msg => { - this.anchor.title = msg; + _notifyStateChange() { + this.eventBus.dispatch('presentationmodechanged', { + source: this, + active: this.active, + switchInProgress: !!this.switchInProgress }); - if (this.renderingState !== _pdf_rendering_queue.RenderingStates.FINISHED) { + } + _setSwitchInProgress() { + if (this.switchInProgress) { + clearTimeout(this.switchInProgress); + } + this.switchInProgress = setTimeout(() => { + this._removeFullscreenChangeListeners(); + delete this.switchInProgress; + this._notifyStateChange(); + }, DELAY_BEFORE_RESETTING_SWITCH_IN_PROGRESS); + } + _resetSwitchInProgress() { + if (this.switchInProgress) { + clearTimeout(this.switchInProgress); + delete this.switchInProgress; + } + } + _enter() { + this.active = true; + this._resetSwitchInProgress(); + this._notifyStateChange(); + this.container.classList.add(ACTIVE_SELECTOR); + setTimeout(() => { + this.pdfViewer.currentPageNumber = this.args.page; + this.pdfViewer.currentScaleValue = 'page-fit'; + }, 0); + this._addWindowListeners(); + this._showControls(); + this.contextMenuOpen = false; + this.container.setAttribute('contextmenu', 'viewerContextMenu'); + window.getSelection().removeAllRanges(); + } + _exit() { + let page = this.pdfViewer.currentPageNumber; + this.container.classList.remove(ACTIVE_SELECTOR); + setTimeout(() => { + this.active = false; + this._removeFullscreenChangeListeners(); + this._notifyStateChange(); + this.pdfViewer.currentScaleValue = this.args.previousScale; + this.pdfViewer.currentPageNumber = page; + this.args = null; + }, 0); + this._removeWindowListeners(); + this._hideControls(); + this._resetMouseScrollState(); + this.container.removeAttribute('contextmenu'); + this.contextMenuOpen = false; + } + _mouseDown(evt) { + if (this.contextMenuOpen) { + this.contextMenuOpen = false; + evt.preventDefault(); return; } - this.l10n.get('thumb_page_canvas', { page: this.pageId }, 'Thumbnail of Page {{page}}').then(ariaLabel => { - if (this.image) { - this.image.setAttribute('aria-label', ariaLabel); - } else if (this.disableCanvasToImageConversion && this.canvas) { - this.canvas.setAttribute('aria-label', ariaLabel); + if (evt.button === 0) { + let isInternalLink = evt.target.href && evt.target.classList.contains('internalLink'); + if (!isInternalLink) { + evt.preventDefault(); + if (evt.shiftKey) { + this._goToPreviousPage(); + } else { + this._goToNextPage(); + } } - }); + } } - static cleanup() { - TempImageFactory.destroyCanvas(); + _contextMenu() { + this.contextMenuOpen = true; } -} -exports.PDFThumbnailView = PDFThumbnailView; - -/***/ }), -/* 24 */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -Object.defineProperty(exports, "__esModule", { - value: true -}); -exports.PDFViewer = undefined; - -var _ui_utils = __webpack_require__(0); - -var _base_viewer = __webpack_require__(25); - -var _pdfjsLib = __webpack_require__(1); - -class PDFViewer extends _base_viewer.BaseViewer { - get _setDocumentViewerElement() { - return (0, _pdfjsLib.shadow)(this, '_setDocumentViewerElement', this.viewer); + _showControls() { + if (this.controlsTimeout) { + clearTimeout(this.controlsTimeout); + } else { + this.container.classList.add(CONTROLS_SELECTOR); + } + this.controlsTimeout = setTimeout(() => { + this.container.classList.remove(CONTROLS_SELECTOR); + delete this.controlsTimeout; + }, DELAY_BEFORE_HIDING_CONTROLS); } - _scrollIntoView({ pageDiv, pageSpot = null }) { - (0, _ui_utils.scrollIntoView)(pageDiv, pageSpot); + _hideControls() { + if (!this.controlsTimeout) { + return; + } + clearTimeout(this.controlsTimeout); + this.container.classList.remove(CONTROLS_SELECTOR); + delete this.controlsTimeout; + } + _resetMouseScrollState() { + this.mouseScrollTimeStamp = 0; + this.mouseScrollDelta = 0; } - _getVisiblePages() { - if (!this.isInPresentationMode) { - return (0, _ui_utils.getVisibleElements)(this.container, this._pages, true); + _touchSwipe(evt) { + if (!this.active) { + return; } - let currentPage = this._pages[this._currentPageNumber - 1]; - let visible = [{ - id: currentPage.id, - view: currentPage - }]; - return { - first: currentPage, - last: currentPage, - views: visible - }; - } - update() { - let visible = this._getVisiblePages(); - let visiblePages = visible.views, - numVisiblePages = visiblePages.length; - if (numVisiblePages === 0) { + if (evt.touches.length > 1) { + this.touchSwipeState = null; return; } - this._resizeBuffer(numVisiblePages); - this.renderingQueue.renderHighestPriority(visible); - let currentId = this._currentPageNumber; - let stillFullyVisible = false; - for (let i = 0; i < numVisiblePages; ++i) { - let page = visiblePages[i]; - if (page.percent < 100) { + switch (evt.type) { + case 'touchstart': + this.touchSwipeState = { + startX: evt.touches[0].pageX, + startY: evt.touches[0].pageY, + endX: evt.touches[0].pageX, + endY: evt.touches[0].pageY + }; break; - } - if (page.id === currentId) { - stillFullyVisible = true; + case 'touchmove': + if (this.touchSwipeState === null) { + return; + } + this.touchSwipeState.endX = evt.touches[0].pageX; + this.touchSwipeState.endY = evt.touches[0].pageY; + evt.preventDefault(); + break; + case 'touchend': + if (this.touchSwipeState === null) { + return; + } + let delta = 0; + let dx = this.touchSwipeState.endX - this.touchSwipeState.startX; + let dy = this.touchSwipeState.endY - this.touchSwipeState.startY; + let absAngle = Math.abs(Math.atan2(dy, dx)); + if (Math.abs(dx) > SWIPE_MIN_DISTANCE_THRESHOLD && (absAngle <= SWIPE_ANGLE_THRESHOLD || absAngle >= Math.PI - SWIPE_ANGLE_THRESHOLD)) { + delta = dx; + } else if (Math.abs(dy) > SWIPE_MIN_DISTANCE_THRESHOLD && Math.abs(absAngle - Math.PI / 2) <= SWIPE_ANGLE_THRESHOLD) { + delta = dy; + } + if (delta > 0) { + this._goToPreviousPage(); + } else if (delta < 0) { + this._goToNextPage(); + } break; - } - } - if (!stillFullyVisible) { - currentId = visiblePages[0].id; } - if (!this.isInPresentationMode) { - this._setCurrentPageNumber(currentId); + } + _addWindowListeners() { + this.showControlsBind = this._showControls.bind(this); + this.mouseDownBind = this._mouseDown.bind(this); + this.mouseWheelBind = this._mouseWheel.bind(this); + this.resetMouseScrollStateBind = this._resetMouseScrollState.bind(this); + this.contextMenuBind = this._contextMenu.bind(this); + this.touchSwipeBind = this._touchSwipe.bind(this); + window.addEventListener('mousemove', this.showControlsBind); + window.addEventListener('mousedown', this.mouseDownBind); + window.addEventListener('wheel', this.mouseWheelBind); + window.addEventListener('keydown', this.resetMouseScrollStateBind); + window.addEventListener('contextmenu', this.contextMenuBind); + window.addEventListener('touchstart', this.touchSwipeBind); + window.addEventListener('touchmove', this.touchSwipeBind); + window.addEventListener('touchend', this.touchSwipeBind); + } + _removeWindowListeners() { + window.removeEventListener('mousemove', this.showControlsBind); + window.removeEventListener('mousedown', this.mouseDownBind); + window.removeEventListener('wheel', this.mouseWheelBind); + window.removeEventListener('keydown', this.resetMouseScrollStateBind); + window.removeEventListener('contextmenu', this.contextMenuBind); + window.removeEventListener('touchstart', this.touchSwipeBind); + window.removeEventListener('touchmove', this.touchSwipeBind); + window.removeEventListener('touchend', this.touchSwipeBind); + delete this.showControlsBind; + delete this.mouseDownBind; + delete this.mouseWheelBind; + delete this.resetMouseScrollStateBind; + delete this.contextMenuBind; + delete this.touchSwipeBind; + } + _fullscreenChange() { + if (this.isFullscreen) { + this._enter(); + } else { + this._exit(); } - this._updateLocation(visible.first); - this.eventBus.dispatch('updateviewarea', { - source: this, - location: this._location - }); + } + _addFullscreenChangeListeners() { + this.fullscreenChangeBind = this._fullscreenChange.bind(this); + window.addEventListener('fullscreenchange', this.fullscreenChangeBind); + window.addEventListener('mozfullscreenchange', this.fullscreenChangeBind); + } + _removeFullscreenChangeListeners() { + window.removeEventListener('fullscreenchange', this.fullscreenChangeBind); + window.removeEventListener('mozfullscreenchange', this.fullscreenChangeBind); + delete this.fullscreenChangeBind; } } -exports.PDFViewer = PDFViewer; +exports.PDFPresentationMode = PDFPresentationMode; /***/ }), -/* 25 */ +/* 22 */ /***/ (function(module, exports, __webpack_require__) { "use strict"; @@ -6294,173 +6488,195 @@ exports.PDFViewer = PDFViewer; Object.defineProperty(exports, "__esModule", { value: true }); -exports.BaseViewer = undefined; +exports.PDFSidebarResizer = undefined; var _ui_utils = __webpack_require__(0); -var _pdf_rendering_queue = __webpack_require__(3); - -var _annotation_layer_builder = __webpack_require__(26); - -var _pdfjsLib = __webpack_require__(1); - -var _dom_events = __webpack_require__(2); - -var _pdf_page_view = __webpack_require__(27); - -var _pdf_link_service = __webpack_require__(5); - -var _text_layer_builder = __webpack_require__(28); - -const DEFAULT_CACHE_SIZE = 10; -function PDFPageViewBuffer(size) { - let data = []; - this.push = function (view) { - let i = data.indexOf(view); - if (i >= 0) { - data.splice(i, 1); - } - data.push(view); - if (data.length > size) { - data.shift().destroy(); - } - }; - this.resize = function (newSize) { - size = newSize; - while (data.length > size) { - data.shift().destroy(); - } - }; -} -function isSameScale(oldScale, newScale) { - if (newScale === oldScale) { - return true; - } - if (Math.abs(newScale - oldScale) < 1e-15) { - return true; - } - return false; -} -class BaseViewer { - constructor(options) { - if (this.constructor === BaseViewer) { - throw new Error('Cannot initialize BaseViewer.'); - } - this._name = this.constructor.name; - this.container = options.container; - this.viewer = options.viewer || options.container.firstElementChild; - this.eventBus = options.eventBus || (0, _dom_events.getGlobalEventBus)(); - this.linkService = options.linkService || new _pdf_link_service.SimpleLinkService(); - this.downloadManager = options.downloadManager || null; - this.removePageBorders = options.removePageBorders || false; - this.textLayerMode = Number.isInteger(options.textLayerMode) ? options.textLayerMode : _ui_utils.TextLayerMode.ENABLE; - this.enhanceTextSelection = options.enhanceTextSelection || false; - this.imageResourcesPath = options.imageResourcesPath || ''; - this.renderInteractiveForms = options.renderInteractiveForms || false; - this.enablePrintAutoRotate = options.enablePrintAutoRotate || false; - this.renderer = options.renderer || _ui_utils.RendererType.CANVAS; - this.enableWebGL = options.enableWebGL || false; - this.useOnlyCssZoom = options.useOnlyCssZoom || false; - this.maxCanvasPixels = options.maxCanvasPixels; - this.l10n = options.l10n || _ui_utils.NullL10n; - this.defaultRenderingQueue = !options.renderingQueue; - if (this.defaultRenderingQueue) { - this.renderingQueue = new _pdf_rendering_queue.PDFRenderingQueue(); - this.renderingQueue.setViewer(this); - } else { - this.renderingQueue = options.renderingQueue; - } - this.scroll = (0, _ui_utils.watchScroll)(this.container, this._scrollUpdate.bind(this)); - this.presentationModeState = _ui_utils.PresentationModeState.UNKNOWN; - this._resetView(); - if (this.removePageBorders) { - this.viewer.classList.add('removePageBorders'); +const SIDEBAR_WIDTH_VAR = '--sidebar-width'; +const SIDEBAR_MIN_WIDTH = 200; +const SIDEBAR_RESIZING_CLASS = 'sidebarResizing'; +class PDFSidebarResizer { + constructor(options, eventBus, l10n = _ui_utils.NullL10n) { + this.enabled = false; + this.isRTL = false; + this.sidebarOpen = false; + this.doc = document.documentElement; + this._width = null; + this._outerContainerWidth = null; + this._boundEvents = Object.create(null); + this.outerContainer = options.outerContainer; + this.resizer = options.resizer; + this.eventBus = eventBus; + this.l10n = l10n; + if (typeof CSS === 'undefined' || typeof CSS.supports !== 'function' || !CSS.supports(SIDEBAR_WIDTH_VAR, `calc(-1 * ${SIDEBAR_MIN_WIDTH}px)`)) { + console.warn('PDFSidebarResizer: ' + 'The browser does not support resizing of the sidebar.'); + return; } + this.enabled = true; + this.resizer.classList.remove('hidden'); + this.l10n.getDirection().then(dir => { + this.isRTL = dir === 'rtl'; + }); + this._addEventListeners(); } - get pagesCount() { - return this._pages.length; - } - getPageView(index) { - return this._pages[index]; - } - get pageViewsReady() { - return this._pageViewsReady; - } - get currentPageNumber() { - return this._currentPageNumber; - } - set currentPageNumber(val) { - if (!Number.isInteger(val)) { - throw new Error('Invalid page number.'); - } - if (!this.pdfDocument) { - return; + get outerContainerWidth() { + if (!this._outerContainerWidth) { + this._outerContainerWidth = this.outerContainer.clientWidth; } - this._setCurrentPageNumber(val, true); + return this._outerContainerWidth; } - _setCurrentPageNumber(val, resetCurrentPageView = false) { - if (this._currentPageNumber === val) { - if (resetCurrentPageView) { - this._resetCurrentPageView(); - } - return; + _updateWidth(width = 0) { + if (!this.enabled) { + return false; } - if (!(0 < val && val <= this.pagesCount)) { - console.error(`${this._name}._setCurrentPageNumber: "${val}" is out of bounds.`); - return; + const maxWidth = Math.floor(this.outerContainerWidth / 2); + if (width > maxWidth) { + width = maxWidth; } - let arg = { - source: this, - pageNumber: val, - pageLabel: this._pageLabels && this._pageLabels[val - 1] - }; - this._currentPageNumber = val; - this.eventBus.dispatch('pagechanging', arg); - this.eventBus.dispatch('pagechange', arg); - if (resetCurrentPageView) { - this._resetCurrentPageView(); + if (width < SIDEBAR_MIN_WIDTH) { + width = SIDEBAR_MIN_WIDTH; } + if (width === this._width) { + return false; + } + this._width = width; + this.doc.style.setProperty(SIDEBAR_WIDTH_VAR, `${width}px`); + return true; } - get currentPageLabel() { - return this._pageLabels && this._pageLabels[this._currentPageNumber - 1]; - } - set currentPageLabel(val) { - let pageNumber = val | 0; - if (this._pageLabels) { - let i = this._pageLabels.indexOf(val); - if (i >= 0) { - pageNumber = i + 1; - } + _mouseMove(evt) { + let width = evt.clientX; + if (this.isRTL) { + width = this.outerContainerWidth - width; } - this.currentPageNumber = pageNumber; + this._updateWidth(width); } - get currentScale() { - return this._currentScale !== _ui_utils.UNKNOWN_SCALE ? this._currentScale : _ui_utils.DEFAULT_SCALE; + _mouseUp(evt) { + this.outerContainer.classList.remove(SIDEBAR_RESIZING_CLASS); + this.eventBus.dispatch('resize', { source: this }); + let _boundEvents = this._boundEvents; + window.removeEventListener('mousemove', _boundEvents.mouseMove); + window.removeEventListener('mouseup', _boundEvents.mouseUp); } - set currentScale(val) { - if (isNaN(val)) { - throw new Error('Invalid numeric scale'); - } - if (!this.pdfDocument) { + _addEventListeners() { + if (!this.enabled) { return; } - this._setScale(val, false); + let _boundEvents = this._boundEvents; + _boundEvents.mouseMove = this._mouseMove.bind(this); + _boundEvents.mouseUp = this._mouseUp.bind(this); + this.resizer.addEventListener('mousedown', evt => { + if (evt.button !== 0) { + return; + } + this.outerContainer.classList.add(SIDEBAR_RESIZING_CLASS); + window.addEventListener('mousemove', _boundEvents.mouseMove); + window.addEventListener('mouseup', _boundEvents.mouseUp); + }); + this.eventBus.on('sidebarviewchanged', evt => { + this.sidebarOpen = !!(evt && evt.view); + }); + this.eventBus.on('resize', evt => { + if (evt && evt.source === window) { + this._outerContainerWidth = null; + if (this._width) { + if (this.sidebarOpen) { + this.outerContainer.classList.add(SIDEBAR_RESIZING_CLASS); + let updated = this._updateWidth(this._width); + Promise.resolve().then(() => { + this.outerContainer.classList.remove(SIDEBAR_RESIZING_CLASS); + if (updated) { + this.eventBus.dispatch('resize', { source: this }); + } + }); + } else { + this._updateWidth(this._width); + } + } + } + }); } - get currentScaleValue() { - return this._currentScaleValue; +} +exports.PDFSidebarResizer = PDFSidebarResizer; + +/***/ }), +/* 23 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.PDFThumbnailViewer = undefined; + +var _ui_utils = __webpack_require__(0); + +var _pdf_thumbnail_view = __webpack_require__(24); + +const THUMBNAIL_SCROLL_MARGIN = -19; +const THUMBNAIL_SELECTED_CLASS = 'selected'; +class PDFThumbnailViewer { + constructor({ container, linkService, renderingQueue, l10n = _ui_utils.NullL10n }) { + this.container = container; + this.linkService = linkService; + this.renderingQueue = renderingQueue; + this.l10n = l10n; + this.scroll = (0, _ui_utils.watchScroll)(this.container, this._scrollUpdated.bind(this)); + this._resetView(); } - set currentScaleValue(val) { + _scrollUpdated() { + this.renderingQueue.renderHighestPriority(); + } + getThumbnail(index) { + return this._thumbnails[index]; + } + _getVisibleThumbs() { + return (0, _ui_utils.getVisibleElements)(this.container, this._thumbnails); + } + scrollThumbnailIntoView(pageNumber) { if (!this.pdfDocument) { return; } - this._setScale(val, false); + const thumbnailView = this._thumbnails[pageNumber - 1]; + if (!thumbnailView) { + console.error('scrollThumbnailIntoView: Invalid "pageNumber" parameter.'); + return; + } + if (pageNumber !== this._currentPageNumber) { + const prevThumbnailView = this._thumbnails[this._currentPageNumber - 1]; + prevThumbnailView.div.classList.remove(THUMBNAIL_SELECTED_CLASS); + thumbnailView.div.classList.add(THUMBNAIL_SELECTED_CLASS); + } + let visibleThumbs = this._getVisibleThumbs(); + let numVisibleThumbs = visibleThumbs.views.length; + if (numVisibleThumbs > 0) { + let first = visibleThumbs.first.id; + let last = numVisibleThumbs > 1 ? visibleThumbs.last.id : first; + let shouldScroll = false; + if (pageNumber <= first || pageNumber >= last) { + shouldScroll = true; + } else { + visibleThumbs.views.some(function (view) { + if (view.id !== pageNumber) { + return false; + } + shouldScroll = view.percent < 100; + return true; + }); + } + if (shouldScroll) { + (0, _ui_utils.scrollIntoView)(thumbnailView.div, { top: THUMBNAIL_SCROLL_MARGIN }); + } + } + this._currentPageNumber = pageNumber; } get pagesRotation() { return this._pagesRotation; } set pagesRotation(rotation) { if (!(0, _ui_utils.isValidRotation)(rotation)) { - throw new Error('Invalid pages rotation angle.'); + throw new Error('Invalid thumbnails rotation angle.'); } if (!this.pdfDocument) { return; @@ -6469,25 +6685,20 @@ class BaseViewer { return; } this._pagesRotation = rotation; - let pageNumber = this._currentPageNumber; - for (let i = 0, ii = this._pages.length; i < ii; i++) { - let pageView = this._pages[i]; - pageView.update(pageView.scale, rotation); - } - if (this._currentScaleValue) { - this._setScale(this._currentScaleValue, true); - } - this.eventBus.dispatch('rotationchanging', { - source: this, - pagesRotation: rotation, - pageNumber - }); - if (this.defaultRenderingQueue) { - this.update(); + for (let i = 0, ii = this._thumbnails.length; i < ii; i++) { + this._thumbnails[i].update(rotation); } } - get _setDocumentViewerElement() { - throw new Error('Not implemented: _setDocumentViewerElement'); + cleanup() { + _pdf_thumbnail_view.PDFThumbnailView.cleanup(); + } + _resetView() { + this._thumbnails = []; + this._currentPageNumber = 1; + this._pageLabels = null; + this._pagesRotation = 0; + this._pagesRequests = []; + this.container.textContent = ''; } setDocument(pdfDocument) { if (this.pdfDocument) { @@ -6498,96 +6709,34 @@ class BaseViewer { if (!pdfDocument) { return; } - let pagesCount = pdfDocument.numPages; - let pagesCapability = (0, _pdfjsLib.createPromiseCapability)(); - this.pagesPromise = pagesCapability.promise; - pagesCapability.promise.then(() => { - this._pageViewsReady = true; - this.eventBus.dispatch('pagesloaded', { - source: this, - pagesCount - }); - }); - let isOnePageRenderedResolved = false; - let onePageRenderedCapability = (0, _pdfjsLib.createPromiseCapability)(); - this.onePageRendered = onePageRenderedCapability.promise; - let bindOnAfterAndBeforeDraw = pageView => { - pageView.onBeforeDraw = () => { - this._buffer.push(pageView); - }; - pageView.onAfterDraw = () => { - if (!isOnePageRenderedResolved) { - isOnePageRenderedResolved = true; - onePageRenderedCapability.resolve(); - } - }; - }; - let firstPagePromise = pdfDocument.getPage(1); - this.firstPagePromise = firstPagePromise; - firstPagePromise.then(pdfPage => { - let scale = this.currentScale; - let viewport = pdfPage.getViewport(scale * _ui_utils.CSS_UNITS); - for (let pageNum = 1; pageNum <= pagesCount; ++pageNum) { - let textLayerFactory = null; - if (this.textLayerMode !== _ui_utils.TextLayerMode.DISABLE) { - textLayerFactory = this; - } - let pageView = new _pdf_page_view.PDFPageView({ - container: this._setDocumentViewerElement, - eventBus: this.eventBus, - id: pageNum, - scale, - defaultViewport: viewport.clone(), - renderingQueue: this.renderingQueue, - textLayerFactory, - textLayerMode: this.textLayerMode, - annotationLayerFactory: this, - imageResourcesPath: this.imageResourcesPath, - renderInteractiveForms: this.renderInteractiveForms, - renderer: this.renderer, - enableWebGL: this.enableWebGL, - useOnlyCssZoom: this.useOnlyCssZoom, - maxCanvasPixels: this.maxCanvasPixels, + pdfDocument.getPage(1).then(firstPage => { + let pagesCount = pdfDocument.numPages; + let viewport = firstPage.getViewport(1.0); + for (let pageNum = 1; pageNum <= pagesCount; ++pageNum) { + let thumbnail = new _pdf_thumbnail_view.PDFThumbnailView({ + container: this.container, + id: pageNum, + defaultViewport: viewport.clone(), + linkService: this.linkService, + renderingQueue: this.renderingQueue, + disableCanvasToImageConversion: false, l10n: this.l10n }); - bindOnAfterAndBeforeDraw(pageView); - this._pages.push(pageView); - } - onePageRenderedCapability.promise.then(() => { - if (pdfDocument.loadingParams['disableAutoFetch']) { - pagesCapability.resolve(); - return; - } - let getPagesLeft = pagesCount; - for (let pageNum = 1; pageNum <= pagesCount; ++pageNum) { - pdfDocument.getPage(pageNum).then(pdfPage => { - let pageView = this._pages[pageNum - 1]; - if (!pageView.pdfPage) { - pageView.setPdfPage(pdfPage); - } - this.linkService.cachePageRef(pageNum, pdfPage.ref); - if (--getPagesLeft === 0) { - pagesCapability.resolve(); - } - }, reason => { - console.error(`Unable to get page ${pageNum} to initialize viewer`, reason); - if (--getPagesLeft === 0) { - pagesCapability.resolve(); - } - }); - } - }); - this.eventBus.dispatch('pagesinit', { source: this }); - if (this.defaultRenderingQueue) { - this.update(); - } - if (this.findController) { - this.findController.resolveFirstPage(); + this._thumbnails.push(thumbnail); } + const thumbnailView = this._thumbnails[this._currentPageNumber - 1]; + thumbnailView.div.classList.add(THUMBNAIL_SELECTED_CLASS); }).catch(reason => { - console.error('Unable to initialize viewer', reason); + console.error('Unable to initialize thumbnail viewer', reason); }); } + _cancelRendering() { + for (let i = 0, ii = this._thumbnails.length; i < ii; i++) { + if (this._thumbnails[i]) { + this._thumbnails[i].cancelRendering(); + } + } + } setPageLabels(labels) { if (!this.pdfDocument) { return; @@ -6596,376 +6745,470 @@ class BaseViewer { this._pageLabels = null; } else if (!(labels instanceof Array && this.pdfDocument.numPages === labels.length)) { this._pageLabels = null; - console.error(`${this._name}.setPageLabels: Invalid page labels.`); + console.error('PDFThumbnailViewer_setPageLabels: Invalid page labels.'); } else { this._pageLabels = labels; } - for (let i = 0, ii = this._pages.length; i < ii; i++) { - let pageView = this._pages[i]; + for (let i = 0, ii = this._thumbnails.length; i < ii; i++) { let label = this._pageLabels && this._pageLabels[i]; - pageView.setPageLabel(label); + this._thumbnails[i].setPageLabel(label); } } - _resetView() { - this._pages = []; - this._currentPageNumber = 1; - this._currentScale = _ui_utils.UNKNOWN_SCALE; - this._currentScaleValue = null; - this._pageLabels = null; - this._buffer = new PDFPageViewBuffer(DEFAULT_CACHE_SIZE); - this._location = null; - this._pagesRotation = 0; - this._pagesRequests = []; - this._pageViewsReady = false; - this.viewer.textContent = ''; - } - _scrollUpdate() { - if (this.pagesCount === 0) { - return; + _ensurePdfPageLoaded(thumbView) { + if (thumbView.pdfPage) { + return Promise.resolve(thumbView.pdfPage); } - this.update(); - } - _scrollIntoView({ pageDiv, pageSpot = null, pageNumber = null }) { - throw new Error('Not implemented: _scrollIntoView'); + let pageNumber = thumbView.id; + if (this._pagesRequests[pageNumber]) { + return this._pagesRequests[pageNumber]; + } + let promise = this.pdfDocument.getPage(pageNumber).then(pdfPage => { + thumbView.setPdfPage(pdfPage); + this._pagesRequests[pageNumber] = null; + return pdfPage; + }).catch(reason => { + console.error('Unable to get page for thumb view', reason); + this._pagesRequests[pageNumber] = null; + }); + this._pagesRequests[pageNumber] = promise; + return promise; } - _setScaleDispatchEvent(newScale, newValue, preset = false) { - let arg = { - source: this, - scale: newScale, - presetValue: preset ? newValue : undefined - }; - this.eventBus.dispatch('scalechanging', arg); - this.eventBus.dispatch('scalechange', arg); + forceRendering() { + let visibleThumbs = this._getVisibleThumbs(); + let thumbView = this.renderingQueue.getHighestPriority(visibleThumbs, this._thumbnails, this.scroll.down); + if (thumbView) { + this._ensurePdfPageLoaded(thumbView).then(() => { + this.renderingQueue.renderView(thumbView); + }); + return true; + } + return false; } - _setScaleUpdatePages(newScale, newValue, noScroll = false, preset = false) { - this._currentScaleValue = newValue.toString(); - if (isSameScale(this._currentScale, newScale)) { - if (preset) { - this._setScaleDispatchEvent(newScale, newValue, true); +} +exports.PDFThumbnailViewer = PDFThumbnailViewer; + +/***/ }), +/* 24 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.PDFThumbnailView = undefined; + +var _pdfjsLib = __webpack_require__(1); + +var _ui_utils = __webpack_require__(0); + +var _pdf_rendering_queue = __webpack_require__(3); + +const MAX_NUM_SCALING_STEPS = 3; +const THUMBNAIL_CANVAS_BORDER_WIDTH = 1; +const THUMBNAIL_WIDTH = 98; +const TempImageFactory = function TempImageFactoryClosure() { + let tempCanvasCache = null; + return { + getCanvas(width, height) { + let tempCanvas = tempCanvasCache; + if (!tempCanvas) { + tempCanvas = document.createElement('canvas'); + tempCanvasCache = tempCanvas; } - return; + tempCanvas.width = width; + tempCanvas.height = height; + tempCanvas.mozOpaque = true; + let ctx = tempCanvas.getContext('2d', { alpha: false }); + ctx.save(); + ctx.fillStyle = 'rgb(255, 255, 255)'; + ctx.fillRect(0, 0, width, height); + ctx.restore(); + return tempCanvas; + }, + destroyCanvas() { + let tempCanvas = tempCanvasCache; + if (tempCanvas) { + tempCanvas.width = 0; + tempCanvas.height = 0; + } + tempCanvasCache = null; } - for (let i = 0, ii = this._pages.length; i < ii; i++) { - this._pages[i].update(newScale); + }; +}(); +class PDFThumbnailView { + constructor({ container, id, defaultViewport, linkService, renderingQueue, disableCanvasToImageConversion = false, l10n = _ui_utils.NullL10n }) { + this.id = id; + this.renderingId = 'thumbnail' + id; + this.pageLabel = null; + this.pdfPage = null; + this.rotation = 0; + this.viewport = defaultViewport; + this.pdfPageRotate = defaultViewport.rotation; + this.linkService = linkService; + this.renderingQueue = renderingQueue; + this.renderTask = null; + this.renderingState = _pdf_rendering_queue.RenderingStates.INITIAL; + this.resume = null; + this.disableCanvasToImageConversion = disableCanvasToImageConversion; + this.pageWidth = this.viewport.width; + this.pageHeight = this.viewport.height; + this.pageRatio = this.pageWidth / this.pageHeight; + this.canvasWidth = THUMBNAIL_WIDTH; + this.canvasHeight = this.canvasWidth / this.pageRatio | 0; + this.scale = this.canvasWidth / this.pageWidth; + this.l10n = l10n; + let anchor = document.createElement('a'); + anchor.href = linkService.getAnchorUrl('#page=' + id); + this.l10n.get('thumb_page_title', { page: id }, 'Page {{page}}').then(msg => { + anchor.title = msg; + }); + anchor.onclick = function () { + linkService.page = id; + return false; + }; + this.anchor = anchor; + let div = document.createElement('div'); + div.className = 'thumbnail'; + div.setAttribute('data-page-number', this.id); + this.div = div; + let ring = document.createElement('div'); + ring.className = 'thumbnailSelectionRing'; + let borderAdjustment = 2 * THUMBNAIL_CANVAS_BORDER_WIDTH; + ring.style.width = this.canvasWidth + borderAdjustment + 'px'; + ring.style.height = this.canvasHeight + borderAdjustment + 'px'; + this.ring = ring; + div.appendChild(ring); + anchor.appendChild(div); + container.appendChild(anchor); + } + setPdfPage(pdfPage) { + this.pdfPage = pdfPage; + this.pdfPageRotate = pdfPage.rotate; + let totalRotation = (this.rotation + this.pdfPageRotate) % 360; + this.viewport = pdfPage.getViewport(1, totalRotation); + this.reset(); + } + reset() { + this.cancelRendering(); + this.pageWidth = this.viewport.width; + this.pageHeight = this.viewport.height; + this.pageRatio = this.pageWidth / this.pageHeight; + this.canvasHeight = this.canvasWidth / this.pageRatio | 0; + this.scale = this.canvasWidth / this.pageWidth; + this.div.removeAttribute('data-loaded'); + let ring = this.ring; + let childNodes = ring.childNodes; + for (let i = childNodes.length - 1; i >= 0; i--) { + ring.removeChild(childNodes[i]); } - this._currentScale = newScale; - if (!noScroll) { - let page = this._currentPageNumber, - dest; - if (this._location && !(this.isInPresentationMode || this.isChangingPresentationMode)) { - page = this._location.pageNumber; - dest = [null, { name: 'XYZ' }, this._location.left, this._location.top, null]; - } - this.scrollPageIntoView({ - pageNumber: page, - destArray: dest, - allowNegativeOffset: true - }); + let borderAdjustment = 2 * THUMBNAIL_CANVAS_BORDER_WIDTH; + ring.style.width = this.canvasWidth + borderAdjustment + 'px'; + ring.style.height = this.canvasHeight + borderAdjustment + 'px'; + if (this.canvas) { + this.canvas.width = 0; + this.canvas.height = 0; + delete this.canvas; } - this._setScaleDispatchEvent(newScale, newValue, preset); - if (this.defaultRenderingQueue) { - this.update(); + if (this.image) { + this.image.removeAttribute('src'); + delete this.image; } } - _setScale(value, noScroll = false) { - let scale = parseFloat(value); - if (scale > 0) { - this._setScaleUpdatePages(scale, value, noScroll, false); - } else { - let currentPage = this._pages[this._currentPageNumber - 1]; - if (!currentPage) { - return; - } - let hPadding = this.isInPresentationMode || this.removePageBorders ? 0 : _ui_utils.SCROLLBAR_PADDING; - let vPadding = this.isInPresentationMode || this.removePageBorders ? 0 : _ui_utils.VERTICAL_PADDING; - let pageWidthScale = (this.container.clientWidth - hPadding) / currentPage.width * currentPage.scale; - let pageHeightScale = (this.container.clientHeight - vPadding) / currentPage.height * currentPage.scale; - switch (value) { - case 'page-actual': - scale = 1; - break; - case 'page-width': - scale = pageWidthScale; - break; - case 'page-height': - scale = pageHeightScale; - break; - case 'page-fit': - scale = Math.min(pageWidthScale, pageHeightScale); - break; - case 'auto': - let horizontalScale = (0, _ui_utils.isPortraitOrientation)(currentPage) ? pageWidthScale : Math.min(pageHeightScale, pageWidthScale); - scale = Math.min(_ui_utils.MAX_AUTO_SCALE, horizontalScale); - break; - default: - console.error(`${this._name}._setScale: "${value}" is an unknown zoom value.`); - return; - } - this._setScaleUpdatePages(scale, value, noScroll, true); + update(rotation) { + if (typeof rotation !== 'undefined') { + this.rotation = rotation; } + let totalRotation = (this.rotation + this.pdfPageRotate) % 360; + this.viewport = this.viewport.clone({ + scale: 1, + rotation: totalRotation + }); + this.reset(); } - _resetCurrentPageView() { - if (this.isInPresentationMode) { - this._setScale(this._currentScaleValue, true); + cancelRendering() { + if (this.renderTask) { + this.renderTask.cancel(); + this.renderTask = null; } - let pageView = this._pages[this._currentPageNumber - 1]; - this._scrollIntoView({ pageDiv: pageView.div }); + this.renderingState = _pdf_rendering_queue.RenderingStates.INITIAL; + this.resume = null; } - scrollPageIntoView(params) { - if (!this.pdfDocument) { - return; + _getPageDrawContext(noCtxScale = false) { + let canvas = document.createElement('canvas'); + this.canvas = canvas; + canvas.mozOpaque = true; + let ctx = canvas.getContext('2d', { alpha: false }); + let outputScale = (0, _ui_utils.getOutputScale)(ctx); + canvas.width = this.canvasWidth * outputScale.sx | 0; + canvas.height = this.canvasHeight * outputScale.sy | 0; + canvas.style.width = this.canvasWidth + 'px'; + canvas.style.height = this.canvasHeight + 'px'; + if (!noCtxScale && outputScale.scaled) { + ctx.scale(outputScale.sx, outputScale.sy); } - let pageNumber = params.pageNumber || 0; - let dest = params.destArray || null; - let allowNegativeOffset = params.allowNegativeOffset || false; - if (this.isInPresentationMode || !dest) { - this._setCurrentPageNumber(pageNumber, true); + return ctx; + } + _convertCanvasToImage() { + if (!this.canvas) { return; } - let pageView = this._pages[pageNumber - 1]; - if (!pageView) { - console.error(`${this._name}.scrollPageIntoView: Invalid "pageNumber" parameter.`); + if (this.renderingState !== _pdf_rendering_queue.RenderingStates.FINISHED) { return; } - let x = 0, - y = 0; - let width = 0, - height = 0, - widthScale, - heightScale; - let changeOrientation = pageView.rotation % 180 === 0 ? false : true; - let pageWidth = (changeOrientation ? pageView.height : pageView.width) / pageView.scale / _ui_utils.CSS_UNITS; - let pageHeight = (changeOrientation ? pageView.width : pageView.height) / pageView.scale / _ui_utils.CSS_UNITS; - let scale = 0; - switch (dest[1].name) { - case 'XYZ': - x = dest[2]; - y = dest[3]; - scale = dest[4]; - x = x !== null ? x : 0; - y = y !== null ? y : pageHeight; - break; - case 'Fit': - case 'FitB': - scale = 'page-fit'; - break; - case 'FitH': - case 'FitBH': - y = dest[2]; - scale = 'page-width'; - if (y === null && this._location) { - x = this._location.left; - y = this._location.top; - } - break; - case 'FitV': - case 'FitBV': - x = dest[2]; - width = pageWidth; - height = pageHeight; - scale = 'page-height'; - break; - case 'FitR': - x = dest[2]; - y = dest[3]; - width = dest[4] - x; - height = dest[5] - y; - let hPadding = this.removePageBorders ? 0 : _ui_utils.SCROLLBAR_PADDING; - let vPadding = this.removePageBorders ? 0 : _ui_utils.VERTICAL_PADDING; - widthScale = (this.container.clientWidth - hPadding) / width / _ui_utils.CSS_UNITS; - heightScale = (this.container.clientHeight - vPadding) / height / _ui_utils.CSS_UNITS; - scale = Math.min(Math.abs(widthScale), Math.abs(heightScale)); - break; - default: - console.error(`${this._name}.scrollPageIntoView: "${dest[1].name}" ` + 'is not a valid destination type.'); - return; - } - if (scale && scale !== this._currentScale) { - this.currentScaleValue = scale; - } else if (this._currentScale === _ui_utils.UNKNOWN_SCALE) { - this.currentScaleValue = _ui_utils.DEFAULT_SCALE_VALUE; - } - if (scale === 'page-fit' && !dest[4]) { - this._scrollIntoView({ - pageDiv: pageView.div, - pageNumber + let id = this.renderingId; + let className = 'thumbnailImage'; + if (this.disableCanvasToImageConversion) { + this.canvas.id = id; + this.canvas.className = className; + this.l10n.get('thumb_page_canvas', { page: this.pageId }, 'Thumbnail of Page {{page}}').then(msg => { + this.canvas.setAttribute('aria-label', msg); }); + this.div.setAttribute('data-loaded', true); + this.ring.appendChild(this.canvas); return; } - let boundingRect = [pageView.viewport.convertToViewportPoint(x, y), pageView.viewport.convertToViewportPoint(x + width, y + height)]; - let left = Math.min(boundingRect[0][0], boundingRect[1][0]); - let top = Math.min(boundingRect[0][1], boundingRect[1][1]); - if (!allowNegativeOffset) { - left = Math.max(left, 0); - top = Math.max(top, 0); - } - this._scrollIntoView({ - pageDiv: pageView.div, - pageSpot: { - left, - top - }, - pageNumber + let image = document.createElement('img'); + image.id = id; + image.className = className; + this.l10n.get('thumb_page_canvas', { page: this.pageId }, 'Thumbnail of Page {{page}}').then(msg => { + image.setAttribute('aria-label', msg); }); + image.style.width = this.canvasWidth + 'px'; + image.style.height = this.canvasHeight + 'px'; + image.src = this.canvas.toDataURL(); + this.image = image; + this.div.setAttribute('data-loaded', true); + this.ring.appendChild(image); + this.canvas.width = 0; + this.canvas.height = 0; + delete this.canvas; } - _resizeBuffer(numVisiblePages) { - let suggestedCacheSize = Math.max(DEFAULT_CACHE_SIZE, 2 * numVisiblePages + 1); - this._buffer.resize(suggestedCacheSize); - } - _updateLocation(firstPage) { - let currentScale = this._currentScale; - let currentScaleValue = this._currentScaleValue; - let normalizedScaleValue = parseFloat(currentScaleValue) === currentScale ? Math.round(currentScale * 10000) / 100 : currentScaleValue; - let pageNumber = firstPage.id; - let pdfOpenParams = '#page=' + pageNumber; - pdfOpenParams += '&zoom=' + normalizedScaleValue; - let currentPageView = this._pages[pageNumber - 1]; - let container = this.container; - let topLeft = currentPageView.getPagePoint(container.scrollLeft - firstPage.x, container.scrollTop - firstPage.y); - let intLeft = Math.round(topLeft[0]); - let intTop = Math.round(topLeft[1]); - pdfOpenParams += ',' + intLeft + ',' + intTop; - this._location = { - pageNumber, - scale: normalizedScaleValue, - top: intTop, - left: intLeft, - rotation: this._pagesRotation, - pdfOpenParams + draw() { + if (this.renderingState !== _pdf_rendering_queue.RenderingStates.INITIAL) { + console.error('Must be in new state before drawing'); + return Promise.resolve(undefined); + } + this.renderingState = _pdf_rendering_queue.RenderingStates.RUNNING; + let renderCapability = (0, _pdfjsLib.createPromiseCapability)(); + let finishRenderTask = error => { + if (renderTask === this.renderTask) { + this.renderTask = null; + } + if (error instanceof _pdfjsLib.RenderingCancelledException) { + renderCapability.resolve(undefined); + return; + } + this.renderingState = _pdf_rendering_queue.RenderingStates.FINISHED; + this._convertCanvasToImage(); + if (!error) { + renderCapability.resolve(undefined); + } else { + renderCapability.reject(error); + } + }; + let ctx = this._getPageDrawContext(); + let drawViewport = this.viewport.clone({ scale: this.scale }); + let renderContinueCallback = cont => { + if (!this.renderingQueue.isHighestPriority(this)) { + this.renderingState = _pdf_rendering_queue.RenderingStates.PAUSED; + this.resume = () => { + this.renderingState = _pdf_rendering_queue.RenderingStates.RUNNING; + cont(); + }; + return; + } + cont(); }; + let renderContext = { + canvasContext: ctx, + viewport: drawViewport + }; + let renderTask = this.renderTask = this.pdfPage.render(renderContext); + renderTask.onContinue = renderContinueCallback; + renderTask.promise.then(function () { + finishRenderTask(null); + }, function (error) { + finishRenderTask(error); + }); + return renderCapability.promise; } - update() { - throw new Error('Not implemented: update'); + setImage(pageView) { + if (this.renderingState !== _pdf_rendering_queue.RenderingStates.INITIAL) { + return; + } + let img = pageView.canvas; + if (!img) { + return; + } + if (!this.pdfPage) { + this.setPdfPage(pageView.pdfPage); + } + this.renderingState = _pdf_rendering_queue.RenderingStates.FINISHED; + let ctx = this._getPageDrawContext(true); + let canvas = ctx.canvas; + if (img.width <= 2 * canvas.width) { + ctx.drawImage(img, 0, 0, img.width, img.height, 0, 0, canvas.width, canvas.height); + this._convertCanvasToImage(); + return; + } + let reducedWidth = canvas.width << MAX_NUM_SCALING_STEPS; + let reducedHeight = canvas.height << MAX_NUM_SCALING_STEPS; + let reducedImage = TempImageFactory.getCanvas(reducedWidth, reducedHeight); + let reducedImageCtx = reducedImage.getContext('2d'); + while (reducedWidth > img.width || reducedHeight > img.height) { + reducedWidth >>= 1; + reducedHeight >>= 1; + } + reducedImageCtx.drawImage(img, 0, 0, img.width, img.height, 0, 0, reducedWidth, reducedHeight); + while (reducedWidth > 2 * canvas.width) { + reducedImageCtx.drawImage(reducedImage, 0, 0, reducedWidth, reducedHeight, 0, 0, reducedWidth >> 1, reducedHeight >> 1); + reducedWidth >>= 1; + reducedHeight >>= 1; + } + ctx.drawImage(reducedImage, 0, 0, reducedWidth, reducedHeight, 0, 0, canvas.width, canvas.height); + this._convertCanvasToImage(); } - containsElement(element) { - return this.container.contains(element); + get pageId() { + return this.pageLabel !== null ? this.pageLabel : this.id; } - focus() { - this.container.focus(); + setPageLabel(label) { + this.pageLabel = typeof label === 'string' ? label : null; + this.l10n.get('thumb_page_title', { page: this.pageId }, 'Page {{page}}').then(msg => { + this.anchor.title = msg; + }); + if (this.renderingState !== _pdf_rendering_queue.RenderingStates.FINISHED) { + return; + } + this.l10n.get('thumb_page_canvas', { page: this.pageId }, 'Thumbnail of Page {{page}}').then(ariaLabel => { + if (this.image) { + this.image.setAttribute('aria-label', ariaLabel); + } else if (this.disableCanvasToImageConversion && this.canvas) { + this.canvas.setAttribute('aria-label', ariaLabel); + } + }); } - get isInPresentationMode() { - return this.presentationModeState === _ui_utils.PresentationModeState.FULLSCREEN; + static cleanup() { + TempImageFactory.destroyCanvas(); } - get isChangingPresentationMode() { - return this.presentationModeState === _ui_utils.PresentationModeState.CHANGING; +} +exports.PDFThumbnailView = PDFThumbnailView; + +/***/ }), +/* 25 */ +/***/ (function(module, exports, __webpack_require__) { + +"use strict"; + + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.PDFViewer = undefined; + +var _base_viewer = __webpack_require__(10); + +var _ui_utils = __webpack_require__(0); + +var _pdfjsLib = __webpack_require__(1); + +class PDFViewer extends _base_viewer.BaseViewer { + get _setDocumentViewerElement() { + return (0, _pdfjsLib.shadow)(this, '_setDocumentViewerElement', this.viewer); } - get isHorizontalScrollbarEnabled() { - return this.isInPresentationMode ? false : this.container.scrollWidth > this.container.clientWidth; + _scrollIntoView({ pageDiv, pageSpot = null }) { + if (!pageSpot) { + const left = pageDiv.offsetLeft + pageDiv.clientLeft; + const right = left + pageDiv.clientWidth; + const { scrollLeft, clientWidth } = this.container; + if (this.scrollMode === _base_viewer.ScrollMode.HORIZONTAL || left < scrollLeft || right > scrollLeft + clientWidth) { + pageSpot = { + left: 0, + top: 0 + }; + } + } + (0, _ui_utils.scrollIntoView)(pageDiv, pageSpot); } _getVisiblePages() { - throw new Error('Not implemented: _getVisiblePages'); - } - cleanup() { - for (let i = 0, ii = this._pages.length; i < ii; i++) { - if (this._pages[i] && this._pages[i].renderingState !== _pdf_rendering_queue.RenderingStates.FINISHED) { - this._pages[i].reset(); - } + if (!this.isInPresentationMode) { + return (0, _ui_utils.getVisibleElements)(this.container, this._pages, true, this.scrollMode === _base_viewer.ScrollMode.HORIZONTAL); } + let currentPage = this._pages[this._currentPageNumber - 1]; + let visible = [{ + id: currentPage.id, + view: currentPage + }]; + return { + first: currentPage, + last: currentPage, + views: visible + }; } - _cancelRendering() { - for (let i = 0, ii = this._pages.length; i < ii; i++) { - if (this._pages[i]) { - this._pages[i].cancelRendering(); + update() { + let visible = this._getVisiblePages(); + let visiblePages = visible.views, + numVisiblePages = visiblePages.length; + if (numVisiblePages === 0) { + return; + } + this._resizeBuffer(numVisiblePages, visiblePages); + this.renderingQueue.renderHighestPriority(visible); + let currentId = this._currentPageNumber; + let stillFullyVisible = false; + for (let i = 0; i < numVisiblePages; ++i) { + let page = visiblePages[i]; + if (page.percent < 100) { + break; + } + if (page.id === currentId) { + stillFullyVisible = true; + break; } } - } - _ensurePdfPageLoaded(pageView) { - if (pageView.pdfPage) { - return Promise.resolve(pageView.pdfPage); + if (!stillFullyVisible) { + currentId = visiblePages[0].id; } - let pageNumber = pageView.id; - if (this._pagesRequests[pageNumber]) { - return this._pagesRequests[pageNumber]; + if (!this.isInPresentationMode) { + this._setCurrentPageNumber(currentId); } - let promise = this.pdfDocument.getPage(pageNumber).then(pdfPage => { - if (!pageView.pdfPage) { - pageView.setPdfPage(pdfPage); - } - this._pagesRequests[pageNumber] = null; - return pdfPage; - }).catch(reason => { - console.error('Unable to get page for page view', reason); - this._pagesRequests[pageNumber] = null; + this._updateLocation(visible.first); + this.eventBus.dispatch('updateviewarea', { + source: this, + location: this._location }); - this._pagesRequests[pageNumber] = promise; - return promise; } - forceRendering(currentlyVisiblePages) { - let visiblePages = currentlyVisiblePages || this._getVisiblePages(); - let pageView = this.renderingQueue.getHighestPriority(visiblePages, this._pages, this.scroll.down); - if (pageView) { - this._ensurePdfPageLoaded(pageView).then(() => { - this.renderingQueue.renderView(pageView); - }); - return true; + _regroupSpreads() { + const container = this._setDocumentViewerElement, + pages = this._pages; + while (container.firstChild) { + container.firstChild.remove(); } - return false; - } - getPageTextContent(pageIndex) { - return this.pdfDocument.getPage(pageIndex + 1).then(function (page) { - return page.getTextContent({ normalizeWhitespace: true }); - }); - } - createTextLayerBuilder(textLayerDiv, pageIndex, viewport, enhanceTextSelection = false) { - return new _text_layer_builder.TextLayerBuilder({ - textLayerDiv, - eventBus: this.eventBus, - pageIndex, - viewport, - findController: this.isInPresentationMode ? null : this.findController, - enhanceTextSelection: this.isInPresentationMode ? false : enhanceTextSelection - }); - } - createAnnotationLayerBuilder(pageDiv, pdfPage, imageResourcesPath = '', renderInteractiveForms = false, l10n = _ui_utils.NullL10n) { - return new _annotation_layer_builder.AnnotationLayerBuilder({ - pageDiv, - pdfPage, - imageResourcesPath, - renderInteractiveForms, - linkService: this.linkService, - downloadManager: this.downloadManager, - l10n - }); - } - setFindController(findController) { - this.findController = findController; - } - get hasEqualPageSizes() { - let firstPageView = this._pages[0]; - for (let i = 1, ii = this._pages.length; i < ii; ++i) { - let pageView = this._pages[i]; - if (pageView.width !== firstPageView.width || pageView.height !== firstPageView.height) { - return false; + if (this.spreadMode === _base_viewer.SpreadMode.NONE) { + for (let i = 0, iMax = pages.length; i < iMax; ++i) { + container.appendChild(pages[i].div); } - } - return true; - } - getPagesOverview() { - let pagesOverview = this._pages.map(function (pageView) { - let viewport = pageView.pdfPage.getViewport(1); - return { - width: viewport.width, - height: viewport.height, - rotation: viewport.rotation - }; - }); - if (!this.enablePrintAutoRotate) { - return pagesOverview; - } - let isFirstPagePortrait = (0, _ui_utils.isPortraitOrientation)(pagesOverview[0]); - return pagesOverview.map(function (size) { - if (isFirstPagePortrait === (0, _ui_utils.isPortraitOrientation)(size)) { - return size; + } else { + const parity = this.spreadMode - 1; + let spread = null; + for (let i = 0, iMax = pages.length; i < iMax; ++i) { + if (spread === null) { + spread = document.createElement('div'); + spread.className = 'spread'; + container.appendChild(spread); + } else if (i % 2 === parity) { + spread = spread.cloneNode(false); + container.appendChild(spread); + } + spread.appendChild(pages[i].div); } - return { - width: size.height, - height: size.width, - rotation: (size.rotation + 90) % 360 - }; - }); + } + this.scrollPageIntoView({ pageNumber: this._currentPageNumber }); + this.update(); } } -exports.BaseViewer = BaseViewer; +exports.PDFViewer = PDFViewer; /***/ }), /* 26 */ @@ -7790,6 +8033,8 @@ Object.defineProperty(exports, "__esModule", { }); exports.SecondaryToolbar = undefined; +var _base_viewer = __webpack_require__(10); + var _pdf_cursor_tools = __webpack_require__(6); var _ui_utils = __webpack_require__(0); @@ -7845,6 +8090,36 @@ class SecondaryToolbar { eventName: 'switchcursortool', eventDetails: { tool: _pdf_cursor_tools.CursorTool.HAND }, close: true + }, { + element: options.scrollVerticalButton, + eventName: 'switchscrollmode', + eventDetails: { mode: _base_viewer.ScrollMode.VERTICAL }, + close: true + }, { + element: options.scrollHorizontalButton, + eventName: 'switchscrollmode', + eventDetails: { mode: _base_viewer.ScrollMode.HORIZONTAL }, + close: true + }, { + element: options.scrollWrappedButton, + eventName: 'switchscrollmode', + eventDetails: { mode: _base_viewer.ScrollMode.WRAPPED }, + close: true + }, { + element: options.spreadNoneButton, + eventName: 'switchspreadmode', + eventDetails: { mode: _base_viewer.SpreadMode.NONE }, + close: true + }, { + element: options.spreadOddButton, + eventName: 'switchspreadmode', + eventDetails: { mode: _base_viewer.SpreadMode.ODD }, + close: true + }, { + element: options.spreadEvenButton, + eventName: 'switchspreadmode', + eventDetails: { mode: _base_viewer.SpreadMode.EVEN }, + close: true }, { element: options.documentPropertiesButton, eventName: 'documentproperties', @@ -7864,6 +8139,8 @@ class SecondaryToolbar { this.reset(); this._bindClickListeners(); this._bindCursorToolsListener(options); + this._bindScrollModeListener(options); + this._bindSpreadModeListener(options); this.eventBus.on('resize', this._setMaxHeight.bind(this)); } get isOpen() { @@ -7920,6 +8197,20 @@ class SecondaryToolbar { } }); } + _bindScrollModeListener(buttons) { + this.eventBus.on('scrollmodechanged', function (evt) { + buttons.scrollVerticalButton.classList.toggle('toggled', evt.mode === _base_viewer.ScrollMode.VERTICAL); + buttons.scrollHorizontalButton.classList.toggle('toggled', evt.mode === _base_viewer.ScrollMode.HORIZONTAL); + buttons.scrollWrappedButton.classList.toggle('toggled', evt.mode === _base_viewer.ScrollMode.WRAPPED); + }); + } + _bindSpreadModeListener(buttons) { + this.eventBus.on('spreadmodechanged', function (evt) { + buttons.spreadNoneButton.classList.toggle('toggled', evt.mode === _base_viewer.SpreadMode.NONE); + buttons.spreadOddButton.classList.toggle('toggled', evt.mode === _base_viewer.SpreadMode.ODD); + buttons.spreadEvenButton.classList.toggle('toggled', evt.mode === _base_viewer.SpreadMode.EVEN); + }); + } open() { if (this.opened) { return; @@ -8606,7 +8897,9 @@ function getDefaultPreferences() { "renderInteractiveForms": false, "enablePrintAutoRotate": false, "disablePageMode": false, - "disablePageLabels": false + "disablePageLabels": false, + "scrollModeOnLoad": 0, + "spreadModeOnLoad": 0 }); } return defaultPreferences; diff --git a/browser/locales/en-US/pdfviewer/viewer.properties b/browser/locales/en-US/pdfviewer/viewer.properties index 3f4723eb2237d..af1765fc1348e 100644 --- a/browser/locales/en-US/pdfviewer/viewer.properties +++ b/browser/locales/en-US/pdfviewer/viewer.properties @@ -65,6 +65,20 @@ cursor_text_select_tool_label=Text Selection Tool cursor_hand_tool.title=Enable Hand Tool cursor_hand_tool_label=Hand Tool +scroll_vertical.title=Use Vertical Scrolling +scroll_vertical_label=Vertical Scrolling +scroll_horizontal.title=Use Horizontal Scrolling +scroll_horizontal_label=Horizontal Scrolling +scroll_wrapped.title=Use Wrapped Scrolling +scroll_wrapped_label=Wrapped Scrolling + +spread_none.title=Do not join page spreads +spread_none_label=No Spreads +spread_odd.title=Join page spreads starting with odd-numbered pages +spread_odd_label=Odd Spreads +spread_even.title=Join page spreads starting with even-numbered pages +spread_even_label=Even Spreads + # Document properties dialog box document_properties.title=Document Properties… document_properties_label=Document Properties… diff --git a/gfx/thebes/gfxWindowsPlatform.cpp b/gfx/thebes/gfxWindowsPlatform.cpp index f930c60b5ace8..48fc71a05cb6a 100644 --- a/gfx/thebes/gfxWindowsPlatform.cpp +++ b/gfx/thebes/gfxWindowsPlatform.cpp @@ -345,15 +345,6 @@ gfxWindowsPlatform::InitAcceleration() { gfxPlatform::InitAcceleration(); - // Set up the D3D11 feature levels we can ask for. - if (IsWin8OrLater()) { - mFeatureLevels.AppendElement(D3D_FEATURE_LEVEL_11_1); - } - mFeatureLevels.AppendElement(D3D_FEATURE_LEVEL_11_0); - mFeatureLevels.AppendElement(D3D_FEATURE_LEVEL_10_1); - mFeatureLevels.AppendElement(D3D_FEATURE_LEVEL_10_0); - mFeatureLevels.AppendElement(D3D_FEATURE_LEVEL_9_3); - DeviceManagerDx::Init(); InitializeConfig(); diff --git a/gfx/thebes/gfxWindowsPlatform.h b/gfx/thebes/gfxWindowsPlatform.h index e55e3e6867467..a6d7b441c3671 100644 --- a/gfx/thebes/gfxWindowsPlatform.h +++ b/gfx/thebes/gfxWindowsPlatform.h @@ -265,8 +265,6 @@ class gfxWindowsPlatform : public gfxPlatform DWRITE_MEASURING_MODE mMeasuringMode; RefPtr mD3D11ReadbackManager; - - nsTArray mFeatureLevels; }; #endif /* GFX_WINDOWS_PLATFORM_H */ diff --git a/js/src/frontend/BytecodeEmitter.cpp b/js/src/frontend/BytecodeEmitter.cpp index 5b493e4f62012..30cca385cdd0e 100644 --- a/js/src/frontend/BytecodeEmitter.cpp +++ b/js/src/frontend/BytecodeEmitter.cpp @@ -1962,9 +1962,6 @@ class MOZ_STACK_CLASS IfThenElseEmitter JumpList jumpAroundThen_; JumpList jumpsAroundElse_; - // The source note index for SRC_IF, SRC_IF_ELSE, or SRC_COND. - unsigned noteIndex_; - // The stack depth before emitting the then block. // Used for restoring stack depth before emitting the else block. // Also used for assertion to make sure then and else blocks pushed the @@ -2014,7 +2011,6 @@ class MOZ_STACK_CLASS IfThenElseEmitter public: explicit IfThenElseEmitter(BytecodeEmitter* bce) : bce_(bce), - noteIndex_(-1), thenDepth_(0), #ifdef DEBUG pushed_(0), @@ -2037,7 +2033,7 @@ class MOZ_STACK_CLASS IfThenElseEmitter // Emit an annotated branch-if-false around the then part. SrcNoteType type = nextState == If ? SRC_IF : nextState == IfElse ? SRC_IF_ELSE : SRC_COND; - if (!bce_->newSrcNote(type, ¬eIndex_)) + if (!bce_->newSrcNote(type)) return false; if (!bce_->emitJump(JSOP_IFEQ, &jumpAroundThen_)) return false; @@ -2093,17 +2089,6 @@ class MOZ_STACK_CLASS IfThenElseEmitter if (!bce_->emitJumpTargetAndPatch(jumpAroundThen_)) return false; - // Annotate SRC_IF_ELSE or SRC_COND with the offset from branch to - // jump, for IonMonkey's benefit. We can't just "back up" from the pc - // of the else clause, because we don't know whether an extended - // jump was required to leap from the end of the then clause over - // the else clause. - if (!bce_->setSrcNoteOffset(noteIndex_, 0, - jumpsAroundElse_.offset - jumpAroundThen_.offset)) - { - return false; - } - // Restore stack depth of the then part. bce_->stackDepth = thenDepth_; state_ = Else; diff --git a/js/src/frontend/SourceNotes.h b/js/src/frontend/SourceNotes.h index 6ae184ae4bed8..d09db79985210 100644 --- a/js/src/frontend/SourceNotes.h +++ b/js/src/frontend/SourceNotes.h @@ -37,8 +37,8 @@ namespace js { #define FOR_EACH_SRC_NOTE_TYPE(M) \ M(SRC_NULL, "null", 0) /* Terminates a note vector. */ \ M(SRC_IF, "if", 0) /* JSOP_IFEQ bytecode is from an if-then. */ \ - M(SRC_IF_ELSE, "if-else", 1) /* JSOP_IFEQ bytecode is from an if-then-else. */ \ - M(SRC_COND, "cond", 1) /* JSOP_IFEQ is from conditional ?: operator. */ \ + M(SRC_IF_ELSE, "if-else", 0) /* JSOP_IFEQ bytecode is from an if-then-else. */ \ + M(SRC_COND, "cond", 0) /* JSOP_IFEQ is from conditional ?: operator. */ \ M(SRC_FOR, "for", 3) /* JSOP_NOP or JSOP_POP in for(;;) loop head. */ \ M(SRC_WHILE, "while", 1) /* JSOP_GOTO to for or while loop condition from before \ loop, else JSOP_NOP at top of do-while loop. */ \ diff --git a/js/src/jit-test/tests/cacheir/bug1462280.js b/js/src/jit-test/tests/cacheir/bug1462280.js new file mode 100644 index 0000000000000..d4581ad6ac9ce --- /dev/null +++ b/js/src/jit-test/tests/cacheir/bug1462280.js @@ -0,0 +1,3 @@ +for (var i = 0; i < 2; i++) { + evaluate("var obj = {[Symbol.iterator]: Symbol.iterator};"); +} diff --git a/js/src/jit-test/tests/generators/bug1462353.js b/js/src/jit-test/tests/generators/bug1462353.js new file mode 100644 index 0000000000000..9140a38339f3a --- /dev/null +++ b/js/src/jit-test/tests/generators/bug1462353.js @@ -0,0 +1,11 @@ +class Base {} +class Derived extends Base { + constructor() { + var fun = async() => { + for (var i = 0; i < 20; i++) {} // Trigger OSR. + super(); + }; + fun(); + } +} +d = new Derived(); diff --git a/js/src/jit/BaselineCompiler.cpp b/js/src/jit/BaselineCompiler.cpp index 7c2cbf77e1044..aca940e578a85 100644 --- a/js/src/jit/BaselineCompiler.cpp +++ b/js/src/jit/BaselineCompiler.cpp @@ -4698,19 +4698,6 @@ BaselineCompiler::emit_JSOP_RESUME() return false; #endif - Register constructing = regs.takeAny(); - ValueOperand newTarget = regs.takeAnyValue(); - masm.loadValue(Address(genObj, GeneratorObject::offsetOfNewTargetSlot()), newTarget); - masm.move32(Imm32(0), constructing); - { - Label notConstructing; - masm.branchTestObject(Assembler::NotEqual, newTarget, ¬Constructing); - masm.pushValue(newTarget); - masm.move32(Imm32(CalleeToken_FunctionConstructing), constructing); - masm.bind(¬Constructing); - } - regs.add(newTarget); - // Push |undefined| for all formals. Register scratch2 = regs.takeAny(); Label loop, loopDone; @@ -4735,14 +4722,10 @@ BaselineCompiler::emit_JSOP_RESUME() masm.makeFrameDescriptor(scratch2, JitFrame_BaselineJS, JitFrameLayout::Size()); masm.Push(Imm32(0)); // actual argc - - // Duplicate PushCalleeToken with a variable instead. - masm.orPtr(constructing, callee); - masm.Push(callee); + masm.PushCalleeToken(callee, /* constructing = */ false); masm.Push(scratch2); // frame descriptor regs.add(callee); - regs.add(constructing); // Load the return value. ValueOperand retVal = regs.takeAnyValue(); diff --git a/js/src/jit/CacheIRCompiler.cpp b/js/src/jit/CacheIRCompiler.cpp index d9c29db26b373..bf6330b3f1b16 100644 --- a/js/src/jit/CacheIRCompiler.cpp +++ b/js/src/jit/CacheIRCompiler.cpp @@ -703,7 +703,6 @@ CacheRegisterAllocator::assertValidState() const const auto& loc2 = operandLocations_[j]; if (loc2.isUninitialized()) continue; - MOZ_ASSERT(loc1 != loc2); MOZ_ASSERT(!loc1.aliasesReg(loc2)); } } diff --git a/js/src/jit/IonControlFlow.cpp b/js/src/jit/IonControlFlow.cpp index 6fbd354dac25c..f68e45ca1bdee 100644 --- a/js/src/jit/IonControlFlow.cpp +++ b/js/src/jit/IonControlFlow.cpp @@ -1762,22 +1762,22 @@ ControlFlowGenerator::processIfStart(JSOp op) // The bytecode for if/ternary gets emitted either like this: // - // IFEQ X ; src note (IF_ELSE, COND) points to the GOTO + // IFEQ X ; src note (IF_ELSE, COND) // ... // GOTO Z - // X: ... ; else/else if + // X: JUMPTARGET ; else/else if // ... - // Z: ; join + // Z: JUMPTARGET ; join // // Or like this: // - // IFEQ X ; src note (IF) has no offset + // IFEQ X ; src note (IF) // ... - // Z: ... ; join + // X: JUMPTARGET ; join // // We want to parse the bytecode as if we were parsing the AST, so for the - // IF_ELSE/COND cases, we use the source note and follow the GOTO. For the - // IF case, the IFEQ offset is the join point. + // IF_ELSE/COND cases, we use the IFEQ/GOTO bytecode offsets to follow the + // branch. For the IF case, the IFEQ offset is the join point. switch (SN_TYPE(sn)) { case SRC_IF: if (!cfgStack_.append(CFGState::If(falseStart, test))) @@ -1789,9 +1789,9 @@ ControlFlowGenerator::processIfStart(JSOp op) { // Infer the join point from the JSOP_GOTO[X] sitting here, then // assert as we much we can that this is the right GOTO. - jsbytecode* trueEnd = pc + GetSrcNoteOffset(sn, 0); + MOZ_ASSERT(JSOp(*falseStart) == JSOP_JUMPTARGET); + jsbytecode* trueEnd = falseStart - JSOP_GOTO_LENGTH; MOZ_ASSERT(trueEnd > pc); - MOZ_ASSERT(trueEnd < falseStart); MOZ_ASSERT(JSOp(*trueEnd) == JSOP_GOTO); MOZ_ASSERT(!GetSrcNote(gsn, script, trueEnd)); diff --git a/js/src/shell/js.cpp b/js/src/shell/js.cpp index f5296ff45a4c2..fc6f6be7819af 100644 --- a/js/src/shell/js.cpp +++ b/js/src/shell/js.cpp @@ -2695,6 +2695,8 @@ SrcNotes(JSContext* cx, HandleScript script, Sprinter* sp) switch (type) { case SRC_NULL: case SRC_IF: + case SRC_IF_ELSE: + case SRC_COND: case SRC_CONTINUE: case SRC_BREAK: case SRC_BREAK2LABEL: @@ -2729,18 +2731,12 @@ SrcNotes(JSContext* cx, HandleScript script, Sprinter* sp) } break; - case SRC_IF_ELSE: - if (!sp->jsprintf(" else %u", unsigned(GetSrcNoteOffset(sn, 0)))) - return false; - break; - case SRC_FOR_IN: case SRC_FOR_OF: if (!sp->jsprintf(" closingjump %u", unsigned(GetSrcNoteOffset(sn, 0)))) return false; break; - case SRC_COND: case SRC_WHILE: case SRC_NEXTCASE: if (!sp->jsprintf(" offset %u", unsigned(GetSrcNoteOffset(sn, 0)))) diff --git a/js/src/vm/GeneratorObject.cpp b/js/src/vm/GeneratorObject.cpp index df14f163142c6..6f41259004fb6 100644 --- a/js/src/vm/GeneratorObject.cpp +++ b/js/src/vm/GeneratorObject.cpp @@ -21,6 +21,7 @@ GeneratorObject::create(JSContext* cx, AbstractFramePtr frame) { MOZ_ASSERT(frame.script()->isGenerator() || frame.script()->isAsync()); MOZ_ASSERT(frame.script()->nfixed() == 0); + MOZ_ASSERT(!frame.isConstructing()); Rooted global(cx, cx->global()); @@ -41,7 +42,6 @@ GeneratorObject::create(JSContext* cx, AbstractFramePtr frame) return nullptr; genObj->setCallee(*frame.callee()); - genObj->setNewTarget(frame.newTarget()); genObj->setEnvironmentChain(*frame.environmentChain()); if (frame.script()->needsArgsObj()) genObj->setArgsObj(frame.argsObj()); @@ -137,9 +137,8 @@ GeneratorObject::resume(JSContext* cx, InterpreterActivation& activation, MOZ_ASSERT(genObj->isSuspended()); RootedFunction callee(cx, &genObj->callee()); - RootedValue newTarget(cx, genObj->newTarget()); RootedObject envChain(cx, &genObj->environmentChain()); - if (!activation.resumeGeneratorFrame(callee, newTarget, envChain)) + if (!activation.resumeGeneratorFrame(callee, envChain)) return false; activation.regs().fp()->setResumedGenerator(); diff --git a/js/src/vm/GeneratorObject.h b/js/src/vm/GeneratorObject.h index e10c1ee7b3433..41f092c87cb14 100644 --- a/js/src/vm/GeneratorObject.h +++ b/js/src/vm/GeneratorObject.h @@ -29,7 +29,6 @@ class GeneratorObject : public NativeObject ARGS_OBJ_SLOT, EXPRESSION_STACK_SLOT, YIELD_AND_AWAIT_INDEX_SLOT, - NEWTARGET_SLOT, RESERVED_SLOTS }; @@ -114,17 +113,6 @@ class GeneratorObject : public NativeObject setFixedSlot(EXPRESSION_STACK_SLOT, NullValue()); } - bool isConstructing() const { - return getFixedSlot(NEWTARGET_SLOT).isObject(); - } - const Value& newTarget() const { - return getFixedSlot(NEWTARGET_SLOT); - } - void setNewTarget(const Value& newTarget) { - setFixedSlot(NEWTARGET_SLOT, newTarget); - } - - // The yield index slot is abused for a few purposes. It's undefined if // it hasn't been set yet (before the initial yield), and null if the // generator is closed. If the generator is running, the yield index is @@ -180,7 +168,6 @@ class GeneratorObject : public NativeObject setFixedSlot(ARGS_OBJ_SLOT, NullValue()); setFixedSlot(EXPRESSION_STACK_SLOT, NullValue()); setFixedSlot(YIELD_AND_AWAIT_INDEX_SLOT, NullValue()); - setFixedSlot(NEWTARGET_SLOT, NullValue()); } bool isAfterYield(); @@ -205,9 +192,6 @@ class GeneratorObject : public NativeObject static size_t offsetOfExpressionStackSlot() { return getFixedSlotOffset(EXPRESSION_STACK_SLOT); } - static size_t offsetOfNewTargetSlot() { - return getFixedSlotOffset(NEWTARGET_SLOT); - } }; bool GeneratorThrowOrReturn(JSContext* cx, AbstractFramePtr frame, Handle obj, diff --git a/js/src/vm/Stack-inl.h b/js/src/vm/Stack-inl.h index bf2056e458c21..5647c477761a9 100644 --- a/js/src/vm/Stack-inl.h +++ b/js/src/vm/Stack-inl.h @@ -318,8 +318,7 @@ InterpreterStack::pushInlineFrame(JSContext* cx, InterpreterRegs& regs, const Ca MOZ_ALWAYS_INLINE bool InterpreterStack::resumeGeneratorCallFrame(JSContext* cx, InterpreterRegs& regs, - HandleFunction callee, HandleValue newTarget, - HandleObject envChain) + HandleFunction callee, HandleObject envChain) { MOZ_ASSERT(callee->isGenerator() || callee->isAsync()); RootedScript script(cx, JSFunction::getOrCreateScript(cx, callee)); @@ -332,11 +331,12 @@ InterpreterStack::resumeGeneratorCallFrame(JSContext* cx, InterpreterRegs& regs, LifoAlloc::Mark mark = allocator_.mark(); - MaybeConstruct constructing = MaybeConstruct(newTarget.isObject()); + // (Async) generators and async functions are not constructors. + MOZ_ASSERT(!callee->isConstructor()); // Include callee, |this|, and maybe |new.target| unsigned nformal = callee->nargs(); - unsigned nvals = 2 + constructing + nformal + script->nslots(); + unsigned nvals = 2 + nformal + script->nslots(); uint8_t* buffer = allocateFrame(cx, sizeof(InterpreterFrame) + nvals * sizeof(Value)); if (!buffer) @@ -346,12 +346,10 @@ InterpreterStack::resumeGeneratorCallFrame(JSContext* cx, InterpreterRegs& regs, argv[-2] = ObjectValue(*callee); argv[-1] = UndefinedValue(); SetValueRangeToUndefined(argv, nformal); - if (constructing) - argv[nformal] = newTarget; - InterpreterFrame* fp = reinterpret_cast(argv + nformal + constructing); + InterpreterFrame* fp = reinterpret_cast(argv + nformal); fp->mark_ = mark; - fp->initCallFrame(prev, prevpc, prevsp, *callee, script, argv, 0, constructing); + fp->initCallFrame(prev, prevpc, prevsp, *callee, script, argv, 0, NO_CONSTRUCT); fp->resumeGeneratorFrame(envChain); regs.prepareToRun(*fp, script); @@ -647,6 +645,18 @@ AbstractFramePtr::unsetIsDebuggee() asRematerializedFrame()->unsetIsDebuggee(); } +inline bool +AbstractFramePtr::isConstructing() const +{ + if (isInterpreterFrame()) + return asInterpreterFrame()->isConstructing(); + if (isBaselineFrame()) + return asBaselineFrame()->isConstructing(); + if (isRematerializedFrame()) + return asRematerializedFrame()->isConstructing(); + MOZ_CRASH("Unexpected frame"); +} + inline bool AbstractFramePtr::hasArgs() const { @@ -963,11 +973,10 @@ InterpreterActivation::popInlineFrame(InterpreterFrame* frame) } inline bool -InterpreterActivation::resumeGeneratorFrame(HandleFunction callee, HandleValue newTarget, - HandleObject envChain) +InterpreterActivation::resumeGeneratorFrame(HandleFunction callee, HandleObject envChain) { InterpreterStack& stack = cx_->interpreterStack(); - if (!stack.resumeGeneratorCallFrame(cx_, regs_, callee, newTarget, envChain)) + if (!stack.resumeGeneratorCallFrame(cx_, regs_, callee, envChain)) return false; MOZ_ASSERT(regs_.fp()->script()->compartment() == compartment_); diff --git a/js/src/vm/Stack.h b/js/src/vm/Stack.h index a4c3955da1f3d..e391da8ec6fd8 100644 --- a/js/src/vm/Stack.h +++ b/js/src/vm/Stack.h @@ -231,6 +231,7 @@ class AbstractFramePtr inline Value calleev() const; inline Value& thisArgument() const; + inline bool isConstructing() const; inline Value newTarget() const; inline bool debuggerNeedsCheckPrimitiveReturn() const; @@ -906,8 +907,7 @@ class InterpreterStack void popInlineFrame(InterpreterRegs& regs); bool resumeGeneratorCallFrame(JSContext* cx, InterpreterRegs& regs, - HandleFunction callee, HandleValue newTarget, - HandleObject envChain); + HandleFunction callee, HandleObject envChain); inline void purge(JSRuntime* rt); @@ -1552,8 +1552,7 @@ class InterpreterActivation : public Activation MaybeConstruct constructing); inline void popInlineFrame(InterpreterFrame* frame); - inline bool resumeGeneratorFrame(HandleFunction callee, HandleValue newTarget, - HandleObject envChain); + inline bool resumeGeneratorFrame(HandleFunction callee, HandleObject envChain); InterpreterFrame* current() const { return regs_.fp(); diff --git a/testing/web-platform/meta/MANIFEST.json b/testing/web-platform/meta/MANIFEST.json index 22f67327abddb..5752fa32b9df7 100644 --- a/testing/web-platform/meta/MANIFEST.json +++ b/testing/web-platform/meta/MANIFEST.json @@ -106807,6 +106807,30 @@ {} ] ], + "css/css-contain/contain-layout-006.html": [ + [ + "/css/css-contain/contain-layout-006.html", + [ + [ + "/css/reference/ref-filled-green-100px-square.xht", + "==" + ] + ], + {} + ] + ], + "css/css-contain/contain-layout-007.html": [ + [ + "/css/css-contain/contain-layout-007.html", + [ + [ + "/css/reference/ref-filled-green-100px-square.xht", + "==" + ] + ], + {} + ] + ], "css/css-contain/contain-layout-breaks-001.html": [ [ "/css/css-contain/contain-layout-breaks-001.html", @@ -106927,6 +106951,30 @@ {} ] ], + "css/css-contain/contain-paint-009.html": [ + [ + "/css/css-contain/contain-paint-009.html", + [ + [ + "/css/reference/ref-filled-green-100px-square.xht", + "==" + ] + ], + {} + ] + ], + "css/css-contain/contain-paint-010.html": [ + [ + "/css/css-contain/contain-paint-010.html", + [ + [ + "/css/reference/ref-filled-green-100px-square.xht", + "==" + ] + ], + {} + ] + ], "css/css-contain/contain-size-001.html": [ [ "/css/css-contain/contain-size-001.html", @@ -128479,6 +128527,30 @@ {} ] ], + "css/css-sizing/intrinsic-percent-non-replaced-004.html": [ + [ + "/css/css-sizing/intrinsic-percent-non-replaced-004.html", + [ + [ + "/css/css-sizing/intrinsic-percent-non-replaced-004-ref.html", + "==" + ] + ], + {} + ] + ], + "css/css-sizing/intrinsic-percent-non-replaced-005.html": [ + [ + "/css/css-sizing/intrinsic-percent-non-replaced-005.html", + [ + [ + "/css/css-sizing/intrinsic-percent-non-replaced-005-ref.html", + "==" + ] + ], + {} + ] + ], "css/css-style-attr/style-attr-braces-001.xht": [ [ "/css/css-style-attr/style-attr-braces-001.xht", @@ -188184,6 +188256,11 @@ {} ] ], + "2dcontext/OWNERS": [ + [ + {} + ] + ], "2dcontext/best-practices/.gitkeep": [ [ {} @@ -189254,6 +189331,11 @@ {} ] ], + "BackgroundSync/OWNERS": [ + [ + {} + ] + ], "FileAPI/BlobURL/support/file_test2.txt": [ [ {} @@ -192709,11 +192791,21 @@ {} ] ], + "apng/OWNERS": [ + [ + {} + ] + ], "apng/animated-png-timeout-ref.html": [ [ {} ] ], + "audio-output/OWNERS": [ + [ + {} + ] + ], "background-fetch/OWNERS": [ [ {} @@ -193214,6 +193306,11 @@ {} ] ], + "common/subset-tests.js": [ + [ + {} + ] + ], "common/test-setting-immutable-prototype.js": [ [ {} @@ -217054,6 +217151,11 @@ {} ] ], + "credential-management/OWNERS": [ + [ + {} + ] + ], "credential-management/support/echoing-nester.html": [ [ {} @@ -240719,6 +240821,11 @@ {} ] ], + "css/css-content/OWNERS": [ + [ + {} + ] + ], "css/css-content/attr-case-insensitive-ref.html": [ [ {} @@ -240999,6 +241106,11 @@ {} ] ], + "css/css-fill-stroke/OWNERS": [ + [ + {} + ] + ], "css/css-fill-stroke/reference/paint-order-001-ref.tentative.html": [ [ {} @@ -242354,6 +242466,11 @@ {} ] ], + "css/css-font-loading/OWNERS": [ + [ + {} + ] + ], "css/css-fonts/OWNERS": [ [ {} @@ -253059,6 +253176,11 @@ {} ] ], + "css/css-properties-values-api/OWNERS": [ + [ + {} + ] + ], "css/css-pseudo/OWNERS": [ [ {} @@ -254244,11 +254366,26 @@ {} ] ], + "css/css-scroll-anchoring/OWNERS": [ + [ + {} + ] + ], "css/css-scroll-anchoring/README.md": [ [ {} ] ], + "css/css-scroll-snap/OWNERS": [ + [ + {} + ] + ], + "css/css-shadow-parts/OWNERS": [ + [ + {} + ] + ], "css/css-shadow-parts/support/shadow-helper.js": [ [ {} @@ -254764,6 +254901,16 @@ {} ] ], + "css/css-sizing/intrinsic-percent-non-replaced-004-ref.html": [ + [ + {} + ] + ], + "css/css-sizing/intrinsic-percent-non-replaced-005-ref.html": [ + [ + {} + ] + ], "css/css-speech/OWNERS": [ [ {} @@ -272314,6 +272461,11 @@ {} ] ], + "device-memory/OWNERS": [ + [ + {} + ] + ], "docs/.gitignore": [ [ {} @@ -288464,6 +288616,11 @@ {} ] ], + "imagebitmap-renderingcontext/OWNERS": [ + [ + {} + ] + ], "images/OWNERS": [ [ {} @@ -289929,6 +290086,11 @@ {} ] ], + "mediacapture-image/OWNERS": [ + [ + {} + ] + ], "mediacapture-record/OWNERS": [ [ {} @@ -290679,6 +290841,11 @@ {} ] ], + "offscreen-canvas/OWNERS": [ + [ + {} + ] + ], "offscreen-canvas/filter/offscreencanvas.filter.js": [ [ {} @@ -294289,6 +294456,11 @@ {} ] ], + "server-timing/OWNERS": [ + [ + {} + ] + ], "server-timing/resources/blue.png": [ [ {} @@ -298404,6 +298576,11 @@ {} ] ], + "wasm/OWNERS": [ + [ + {} + ] + ], "wasm/compile_worker.js": [ [ {} @@ -299134,6 +299311,11 @@ {} ] ], + "webgl/OWNERS": [ + [ + {} + ] + ], "webgl/common.js": [ [ {} @@ -301944,6 +302126,11 @@ {} ] ], + "workers/modules/resources/static-import-non-existent-script-worker.js": [ + [ + {} + ] + ], "workers/modules/resources/static-import-worker.js": [ [ {} @@ -302199,6 +302386,11 @@ {} ] ], + "worklets/OWNERS": [ + [ + {} + ] + ], "worklets/README.md": [ [ {} @@ -373827,6 +374019,12 @@ {} ] ], + "webrtc/RTCPeerConnection-add-track-no-deadlock.https.html": [ + [ + "/webrtc/RTCPeerConnection-add-track-no-deadlock.https.html", + {} + ] + ], "webrtc/RTCPeerConnection-addIceCandidate.html": [ [ "/webrtc/RTCPeerConnection-addIceCandidate.html", @@ -399676,6 +399874,10 @@ "16f72935aaf97175593bcf27794506f0884f091b", "support" ], + "2dcontext/OWNERS": [ + "07a7da62ef2c26f061cfc076d268f06a0cdcf72b", + "support" + ], "2dcontext/best-practices/.gitkeep": [ "da39a3ee5e6b4b0d3255bfef95601890afd80709", "support" @@ -403752,6 +403954,10 @@ "73f0071c06f429c3d47eac8d0863e11f1d6e8c25", "support" ], + "BackgroundSync/OWNERS": [ + "ed48014d817ef034062db60403704ed2c0cf9aeb", + "support" + ], "BackgroundSync/interfaces.any.js": [ "2a158ca33b93b78a581341d885150d252a0e4555", "testharness" @@ -405689,47 +405895,47 @@ "testharness" ], "WebCryptoAPI/generateKey/successes.js": [ - "db8091eaf59ea342ae7c8f64e6548c976b5f0b36", + "f0f112ddcf43a46cfccc0e7cf29b46208f87bb5f", "support" ], "WebCryptoAPI/generateKey/successes_AES-CBC.https.any.js": [ - "71f7d2beac74da25795366722aea79fb88c197ab", + "49ce28516303c7525f74d29fbbe36b578e9e0d08", "testharness" ], "WebCryptoAPI/generateKey/successes_AES-CTR.https.any.js": [ - "57f1bff81966f8fc20b7870ed1a5ecf939f1c4d1", + "377e8f0ec969f36949c9dc08ae935063d25c08d8", "testharness" ], "WebCryptoAPI/generateKey/successes_AES-GCM.https.any.js": [ - "faa70a7dda91b0602987ec8e7ef0787c4ed163e3", + "a65a71f8f83b017fe9eb8fccbd8da3489ed1f9f0", "testharness" ], "WebCryptoAPI/generateKey/successes_AES-KW.https.any.js": [ - "23b4567c82e12847f41fb6aa8a6a2cb6bd219a94", + "165159903403f67cc27d29f78d46369eb598811c", "testharness" ], "WebCryptoAPI/generateKey/successes_ECDH.https.any.js": [ - "51f5990d71b6d0008163c5550dfe3ca88fe56356", + "525b874eff610c6db8cca7f50ba0c074b8975001", "testharness" ], "WebCryptoAPI/generateKey/successes_ECDSA.https.any.js": [ - "bfce352ef583a31aaae4a5a303a8b98737cfc22f", + "2a63f8d0d12987ca2e4c41e5eb28a53741a091f5", "testharness" ], "WebCryptoAPI/generateKey/successes_HMAC.https.any.js": [ - "64b1846740147585fc4d497ba8d20a4b5bdef315", + "af064fd9cc422c35718d1dcf2f6c861aab7385cc", "testharness" ], "WebCryptoAPI/generateKey/successes_RSA-OAEP.https.any.js": [ - "ccb63d91473cb7ee6554ad80f0ee2be004e75c91", + "f82ce4307fea94a097ccdf470b766f110d876b87", "testharness" ], "WebCryptoAPI/generateKey/successes_RSA-PSS.https.any.js": [ - "9549e735a6d5d2a570f2b6ec4b09c49fd6a88f51", + "8ff33e42d855b7482455ebb3caab5ac311e7cbf5", "testharness" ], "WebCryptoAPI/generateKey/successes_RSASSA-PKCS1-v1_5.https.any.js": [ - "11aff41d669c5a44c5929ac8754d680b675f3c8c", + "fbbbef333461a7845ea1b3cba2169435c7f82761", "testharness" ], "WebCryptoAPI/getRandomValues.any.js": [ @@ -409256,6 +409462,10 @@ "789767132e47fb6cad1ea60584a04b4f2e2c9551", "support" ], + "apng/OWNERS": [ + "5fa81c84bf276ac842e54c02c4889aac62806f86", + "support" + ], "apng/animated-png-timeout-ref.html": [ "dcd3c58b9200109868f2b98bda346bf26f823e07", "support" @@ -409276,6 +409486,10 @@ "8f37d8d2fc1cb9b5ad0d85234f733f534f4f0db8", "testharness" ], + "audio-output/OWNERS": [ + "8d5030068c8ea67ad77f7dabb274470685b734a6", + "support" + ], "audio-output/setSinkId-manual.https.html": [ "6743b9f6843a1c6134ac9cc627375b0368986e55", "manual" @@ -410536,6 +410750,10 @@ "e3593850f8098d3f3ff82c042deab15f51c66a52", "support" ], + "common/subset-tests.js": [ + "ee72de5b5f2302d111a0f131eddf5081ad02b789", + "support" + ], "common/test-setting-immutable-prototype.js": [ "2cafc5c2b867e0fd6f738b1fbeaa503761c400b7", "support" @@ -432492,6 +432710,10 @@ "8307ed240a531033c96da89197dcfb5ea25cde87", "support" ], + "credential-management/OWNERS": [ + "c7e6702e4472c55bb6e9c543bed62de2d2a7331d", + "support" + ], "credential-management/credentialscontainer-create-basics.https.html": [ "4889217f5e821965907d4d60a9ffdd19d4bc79af", "testharness" @@ -496200,6 +496422,14 @@ "60b834ef7b5becf76f5cacd55b2b9c4774562637", "reftest" ], + "css/css-contain/contain-layout-006.html": [ + "89c68e7ce325295d6a36da91b6d4dd39580f7165", + "reftest" + ], + "css/css-contain/contain-layout-007.html": [ + "799965dfb9989fc3a8226e80fa3c67cafb24374b", + "reftest" + ], "css/css-contain/contain-layout-breaks-001.html": [ "09fcfd311126800c7ce63f27c3154ef31fc647bd", "reftest" @@ -496240,6 +496470,14 @@ "5540aaf33b5b841d95f84ead3459f634cf444299", "reftest" ], + "css/css-contain/contain-paint-009.html": [ + "b3a8ee7512f1f893b630453a8443edaed983f4c3", + "reftest" + ], + "css/css-contain/contain-paint-010.html": [ + "e47f99a8fedb60f34ec7877686f478cbc002c6b4", + "reftest" + ], "css/css-contain/contain-size-001.html": [ "089c4fd7352f91a85d5d8f6bf8c5f261c868cd37", "reftest" @@ -496396,6 +496634,10 @@ "6b72ea53450c5a08ef3ddd897608aa9cf7e68e00", "support" ], + "css/css-content/OWNERS": [ + "d3f0adf12724f2b230ffa3b2845e273ba4200076", + "support" + ], "css/css-content/attr-case-insensitive-ref.html": [ "30577fc39afb6ac028e25be11f363e060c0850b2", "support" @@ -498464,6 +498706,10 @@ "cfaff82945bd52baafb8c4c16eb38c9dbee14da6", "testharness" ], + "css/css-fill-stroke/OWNERS": [ + "d9c8054b356c9273a054a83abeb9be0626c23921", + "support" + ], "css/css-fill-stroke/paint-order-001.tentative.html": [ "46e784929d8a661eb432fa04cc79e0612bd5d194", "reftest" @@ -501612,6 +501858,10 @@ "62ff3e2eac64bb2057391e4dcc4664a4839bbbe8", "reftest" ], + "css/css-font-loading/OWNERS": [ + "19b55d317925d28a18230592db5d05426f16537c", + "support" + ], "css/css-font-loading/fontfacesetloadevent-constructor.html": [ "ad355c3d5220c1b938182241a8e8abe030ace699", "testharness" @@ -515112,6 +515362,10 @@ "7f8a5b4d9047c07378473362acb3d001e70d5663", "support" ], + "css/css-properties-values-api/OWNERS": [ + "b098aad4eacf3991e0930a0953067c1b1135c519", + "support" + ], "css/css-properties-values-api/register-property-syntax-parsing.html": [ "b065f4840b3c1deb4a2f8a59428e102f2ae11686", "testharness" @@ -517572,6 +517826,10 @@ "5816d3d7af3c4bef07f4a299ab65c74b7b8d80f9", "testharness" ], + "css/css-scroll-anchoring/OWNERS": [ + "d9c8054b356c9273a054a83abeb9be0626c23921", + "support" + ], "css/css-scroll-anchoring/README.md": [ "31205944cbcf321f7aa77e3bef0f8835cc7b6d13", "support" @@ -517652,6 +517910,10 @@ "de66dba5bce15b7403e9e582d982d4e3e4aed552", "testharness" ], + "css/css-scroll-snap/OWNERS": [ + "d9c8054b356c9273a054a83abeb9be0626c23921", + "support" + ], "css/css-scroll-snap/scroll-snap-type-proximity.html": [ "75bfc0b6c7686afbbf431e653ab674496ad3fe46", "testharness" @@ -517672,6 +517934,10 @@ "dfaf8675bec557c9f2178ad48b29c803f94056b5", "testharness" ], + "css/css-shadow-parts/OWNERS": [ + "d9c8054b356c9273a054a83abeb9be0626c23921", + "support" + ], "css/css-shadow-parts/all-hosts.html": [ "a92019bba916ed3242dcdf66184d73b915f2689d", "testharness" @@ -518757,43 +519023,43 @@ "reftest" ], "css/css-shapes/spec-examples/shape-outside-010.html": [ - "7baf8e86ee451f08ab18e03000d64a529a2824d0", + "929078a33a23f1d10ce9d0f89016725f233e133e", "testharness" ], "css/css-shapes/spec-examples/shape-outside-011.html": [ - "3620cce0bf178d1bc67faa372406c50b3b07c086", + "af178c8f965ce5f48673a4b67aa15f4974a09a2a", "testharness" ], "css/css-shapes/spec-examples/shape-outside-012.html": [ - "1db1130bb5f2f5a8a12bab7ec5a9fa0c40165be4", + "67e23bdb9873267a12790cf4cd60b704f423f8a5", "testharness" ], "css/css-shapes/spec-examples/shape-outside-013.html": [ - "155d33ea047169acdc6b29b4716fa7237b133d51", + "7bd3ac39a58324354fa2c36fa98b151ce1292c85", "testharness" ], "css/css-shapes/spec-examples/shape-outside-014.html": [ - "ab449eda8aa379e0149c759e9dcd9a866c1ed3db", + "e87ca4ce9f46103091139fda326452e4c66b1980", "testharness" ], "css/css-shapes/spec-examples/shape-outside-015.html": [ - "f0ce9eb24d3b6bf8b8aa03f5cd02f82acfcdf8cd", + "d30174b5995f0831f2535a7a817f6ad5af5a6ba8", "testharness" ], "css/css-shapes/spec-examples/shape-outside-016.html": [ - "2ea1538bff7b1825cdd63ea6510435c7aa52aebc", + "585b41b91bd9d452b616f87e81c8a47576299719", "testharness" ], "css/css-shapes/spec-examples/shape-outside-017.html": [ - "366e0ad5c7ae7f2663f9c6bc6c0eba51e299f120", + "9593d57329acf1998d4b5ada5a230f3fed0d3c32", "testharness" ], "css/css-shapes/spec-examples/shape-outside-018.html": [ - "08c9fd21d74ae52b98581c7d013275c30d49e18c", + "c81ef4303d00a4f490f8cada68d8a6449daa56c3", "testharness" ], "css/css-shapes/spec-examples/shape-outside-019.html": [ - "46de7762b9a9c29a0aa798775cea5dfb17bbf5a0", + "3eaf5c74cfbbb676b3f2ccae55a96d3999ac890b", "testharness" ], "css/css-shapes/spec-examples/support/circle-no-shadow.png": [ @@ -518809,7 +519075,7 @@ "support" ], "css/css-shapes/spec-examples/support/spec-example-utils.js": [ - "137b347da1085eb0042f1d2fc017694ff528180b", + "de748e548169b360cf0d31a5499d766dd8bc2a7d", "support" ], "css/css-shapes/support/1x1-green.png": [ @@ -518972,6 +519238,22 @@ "43d44ad3a75e6abb9d66d06c3cdc71dbcb366651", "reftest" ], + "css/css-sizing/intrinsic-percent-non-replaced-004-ref.html": [ + "4b93517397b4332b3062804e2d6047afdd169fae", + "support" + ], + "css/css-sizing/intrinsic-percent-non-replaced-004.html": [ + "42bc0191ff3ba22c5ceb377f1bc68131d652509e", + "reftest" + ], + "css/css-sizing/intrinsic-percent-non-replaced-005-ref.html": [ + "a2cd75ab26376e74e26414013fc34b8e7fdb1a68", + "support" + ], + "css/css-sizing/intrinsic-percent-non-replaced-005.html": [ + "33aa880de7eb7c4128022871dfd5e2895be30dcc", + "reftest" + ], "css/css-speech/Integer.html": [ "8db91e711b22ead393b1d9a18c224a7f838b85b0", "manual" @@ -532029,7 +532311,7 @@ "testharness" ], "css/css-transitions/zero-duration-multiple-transition.html": [ - "7db6bc8641a6a2eb5f1ee1fdbc9b6215a0462bbc", + "bcbcd704e617cf1bb057a67d9ff5635ef6ebda7e", "testharness" ], "css/css-typed-om/CSSMatrixComponent-DOMMatrix-mutable.html": [ @@ -556148,6 +556430,10 @@ "2ec52a6baa7490478ec61e72bf89b2ec09d453b5", "testharness" ], + "device-memory/OWNERS": [ + "c328f48fe12bce670646911964930d221c768f1d", + "support" + ], "device-memory/device-memory.https.any.js": [ "4e746987c6580c6ff388f1512a02cc6fe33393ea", "testharness" @@ -556313,7 +556599,7 @@ "support" ], "docs/_writing-tests/testharness.md": [ - "6d581e1021a2401b34c0c024990b5e85dbef1fa5", + "0a0d88c5ddde91514a51d607405c2b7dedee4776", "support" ], "docs/_writing-tests/visual.md": [ @@ -562333,7 +562619,7 @@ "testharness" ], "fetch/security/dangling-markup-mitigation-data-url.tentative.sub.html": [ - "92c4633c3d684de4b1d959dbff4f2bab1eaf15a0", + "1059b1c0907444bd416889f99d766a566ba9bde3", "testharness" ], "fetch/security/dangling-markup-mitigation.tentative.html": [ @@ -579265,7 +579551,7 @@ "testharness" ], "html/semantics/scripting-1/the-script-element/execution-timing/077.html": [ - "2bfe280f0ae7b745f2217055e66579ab6fb06769", + "077bf7437a9ef4f6d51d0fa26b45ae7c765feb9f", "testharness" ], "html/semantics/scripting-1/the-script-element/execution-timing/078.html": [ @@ -582812,6 +583098,10 @@ "da39a3ee5e6b4b0d3255bfef95601890afd80709", "support" ], + "imagebitmap-renderingcontext/OWNERS": [ + "07a7da62ef2c26f061cfc076d268f06a0cdcf72b", + "support" + ], "imagebitmap-renderingcontext/bitmaprenderer-as-imagesource.html": [ "f80d1496329c64643d2b40e478779929de20c499", "testharness" @@ -584932,6 +585222,10 @@ "ceeb48e7982eb88561f4c1630cb0fcf15d9cf73c", "testharness" ], + "mediacapture-image/OWNERS": [ + "d53c2a28adfbc343850c3362a180bba24ae63609", + "support" + ], "mediacapture-image/idlharness.html": [ "7ccf7fcab0344a2e1893e89d7689e2312287b64d", "testharness" @@ -586948,6 +587242,10 @@ "f31d50ead567908aab1d1dad577eb06c912c97f3", "manual" ], + "offscreen-canvas/OWNERS": [ + "07a7da62ef2c26f061cfc076d268f06a0cdcf72b", + "support" + ], "offscreen-canvas/compositing/2d.composite.canvas.copy.html": [ "983ae27346b47cd73000d9e3cd2264e3233705d1", "testharness" @@ -593309,7 +593607,7 @@ "support" ], "payment-request/PaymentAddress/attributes-and-toJSON-method-manual.https.html": [ - "1a2bf6b62a5021eec649c0919a35574779e30d09", + "46cac5ba402841a8bc311b1a11de4a82589ee567", "manual" ], "payment-request/PaymentItem/type_member.https.html": [ @@ -603180,6 +603478,10 @@ "01ae6e757d428800555012783e290ebba575bcab", "testharness" ], + "server-timing/OWNERS": [ + "99acae581c71af3f6306bff62a1172955e83f756", + "support" + ], "server-timing/cross_origin.html": [ "e20e60bef34167b4608a837d0ddb311effa20773", "testharness" @@ -603909,7 +604211,7 @@ "testharness" ], "server-timing/sw.js": [ - "0c12328f152814e2f0bde7fe026cf12c8ea77ff0", + "47e2601a903e34c2c8afc90e544026e8c6d11d05", "support" ], "server-timing/test_server_timing.html": [ @@ -606409,7 +606711,7 @@ "testharness" ], "shadow-dom/form-control-form-attribute.html": [ - "79b4a278f0e35646cfdffeebf8f0523e2772bc9b", + "7726f8fe9056d3d5c9fb7b963c4bc6e777a8256a", "testharness" ], "shadow-dom/historical.html": [ @@ -612968,6 +613270,10 @@ "caaf2634451eb9228c0b20f0ac817d7a3d3fa685", "testharness" ], + "wasm/OWNERS": [ + "e4284c7c52365b575b20abcf696a5634ef86b769", + "support" + ], "wasm/compile_worker.js": [ "652193b876206d7a0f361f145469a604d03e3784", "support" @@ -614932,6 +615238,10 @@ "c184952fc8a78f5edc7d573a9f8440b5eec334cc", "wdspec" ], + "webgl/OWNERS": [ + "0df8e72f3ab70719aac73d3b06f043fac629939b", + "support" + ], "webgl/bufferSubData.html": [ "526612470551a0eb157b310c587d50080087808d", "testharness" @@ -615484,6 +615794,10 @@ "db758cc2a744c049c291575e408dbb5f280cdf19", "testharness" ], + "webrtc/RTCPeerConnection-add-track-no-deadlock.https.html": [ + "a16eaf6805528c2b73650694f26568f41be5d5ff", + "testharness" + ], "webrtc/RTCPeerConnection-addIceCandidate.html": [ "dd19f1d7a8d12ee85101e53bb30c553e94d67b6a", "testharness" @@ -615625,7 +615939,7 @@ "testharness" ], "webrtc/RTCPeerConnection-setRemoteDescription.html": [ - "59f826d4d23cd52f15f3940cc3abe66933e91037", + "8a3e2f1e157e1ceed18ac66e57040a941b658f24", "testharness" ], "webrtc/RTCPeerConnection-track-stats.https.html": [ @@ -619993,7 +620307,7 @@ "support" ], "webxr/interfaces.https.html": [ - "22e2278ab484ced51fd0a3880d2bfbf610650371", + "b723ad7105c7e5c12ba5fe75ceac3de3d990dfe2", "testharness" ], "webxr/resources/webxr_check.html": [ @@ -620713,7 +621027,7 @@ "testharness" ], "workers/modules/dedicated-worker-import.html": [ - "95973c682b79618cc894417a4f89a758e7e8c7b1", + "b9f5a7a0384ac3f34c48f32a378b758880f59b06", "testharness" ], "workers/modules/dedicated-worker-options-type.html": [ @@ -620725,7 +621039,7 @@ "support" ], "workers/modules/resources/dynamic-import-given-url-worker.js": [ - "372686abd1b2d2d09228a44f6420c646319e0bd1", + "0d2cfe16d71bb17577c6cf6cde5973c18c2c70fe", "support" ], "workers/modules/resources/dynamic-import-worker.js": [ @@ -620760,6 +621074,10 @@ "f69987442b6a223a868e6c1a7ca6d9cee2976068", "support" ], + "workers/modules/resources/static-import-non-existent-script-worker.js": [ + "e8e1f0aedcc780aac742af01387dd151b10104bc", + "support" + ], "workers/modules/resources/static-import-worker.js": [ "6d5fb2c553d2f32cdd16722a85bd65e0a172768c", "support" @@ -621144,6 +621462,10 @@ "c6a02eed61fe26e59252314cbbe090eeed9de9ca", "testharness" ], + "worklets/OWNERS": [ + "e2dd08513daf7b513cf2db811841d50153999954", + "support" + ], "worklets/README.md": [ "33a3530260a18e74dd96470d9890bbdb4ecdb08d", "support" diff --git a/testing/web-platform/meta/cookies/secure/cookie-forcing.html.ini b/testing/web-platform/meta/cookies/secure/cookie-forcing.html.ini index cb0d16620294c..20f4c2a9acdd3 100644 --- a/testing/web-platform/meta/cookies/secure/cookie-forcing.html.ini +++ b/testing/web-platform/meta/cookies/secure/cookie-forcing.html.ini @@ -1,6 +1,4 @@ [cookie-forcing.html] - expected: - if debug and not webrender and not e10s and (os == "linux") and (version == "Ubuntu 16.04") and (processor == "x86") and (bits == 32): TIMEOUT [non-secure origins should be able to force out insecure cookies.] expected: if debug and not webrender and not e10s and (os == "linux") and (version == "Ubuntu 16.04") and (processor == "x86") and (bits == 32): TIMEOUT diff --git a/testing/web-platform/meta/cookies/secure/create-cookie-http.html.ini b/testing/web-platform/meta/cookies/secure/create-cookie-http.html.ini index 36ca39cc3143f..96315a3c958e6 100644 --- a/testing/web-platform/meta/cookies/secure/create-cookie-http.html.ini +++ b/testing/web-platform/meta/cookies/secure/create-cookie-http.html.ini @@ -1,6 +1,4 @@ [create-cookie-http.html] - expected: - if debug and not webrender and not e10s and (os == "linux") and (version == "Ubuntu 16.04") and (processor == "x86") and (bits == 32): ERROR [Untitled] expected: FAIL diff --git a/testing/web-platform/meta/css/css-contain/contain-layout-006.html.ini b/testing/web-platform/meta/css/css-contain/contain-layout-006.html.ini new file mode 100644 index 0000000000000..e6ff7fb8c229a --- /dev/null +++ b/testing/web-platform/meta/css/css-contain/contain-layout-006.html.ini @@ -0,0 +1,2 @@ +[contain-layout-006.html] + expected: FAIL diff --git a/testing/web-platform/meta/css/css-contain/contain-layout-007.html.ini b/testing/web-platform/meta/css/css-contain/contain-layout-007.html.ini new file mode 100644 index 0000000000000..667c8d5a5176e --- /dev/null +++ b/testing/web-platform/meta/css/css-contain/contain-layout-007.html.ini @@ -0,0 +1,2 @@ +[contain-layout-007.html] + expected: FAIL diff --git a/testing/web-platform/meta/custom-elements/CustomElementRegistry.html.ini b/testing/web-platform/meta/custom-elements/CustomElementRegistry.html.ini index 475383d0ea397..13f69e09049fa 100644 --- a/testing/web-platform/meta/custom-elements/CustomElementRegistry.html.ini +++ b/testing/web-platform/meta/custom-elements/CustomElementRegistry.html.ini @@ -11,3 +11,4 @@ [customElements.define must get "observedAttributes" property on the constructor prototype when "attributeChangedCallback" is present] expected: FAIL + diff --git a/testing/web-platform/meta/fetch/security/dangling-markup-mitigation-data-url.tentative.sub.html.ini b/testing/web-platform/meta/fetch/security/dangling-markup-mitigation-data-url.tentative.sub.html.ini index 33c34ddf307ce..ef3fc5a027a61 100644 --- a/testing/web-platform/meta/fetch/security/dangling-markup-mitigation-data-url.tentative.sub.html.ini +++ b/testing/web-platform/meta/fetch/security/dangling-markup-mitigation-data-url.tentative.sub.html.ini @@ -1,5 +1,4 @@ [dangling-markup-mitigation-data-url.tentative.sub.html] - expected: TIMEOUT [] expected: TIMEOUT diff --git a/testing/web-platform/meta/html/browsers/browsing-the-web/history-traversal/persisted-user-state-restoration/resume-timer-on-history-back.html.ini b/testing/web-platform/meta/html/browsers/browsing-the-web/history-traversal/persisted-user-state-restoration/resume-timer-on-history-back.html.ini index f228bbda465c5..3f956b3d3cc04 100644 --- a/testing/web-platform/meta/html/browsers/browsing-the-web/history-traversal/persisted-user-state-restoration/resume-timer-on-history-back.html.ini +++ b/testing/web-platform/meta/html/browsers/browsing-the-web/history-traversal/persisted-user-state-restoration/resume-timer-on-history-back.html.ini @@ -1,4 +1,3 @@ [resume-timer-on-history-back.html] disabled: if os == "win": https://bugzilla.mozilla.org/show_bug.cgi?id=1321179 - diff --git a/testing/web-platform/meta/html/dom/dynamic-markup-insertion/document-write/contentType.window.js.ini b/testing/web-platform/meta/html/dom/dynamic-markup-insertion/document-write/contentType.window.js.ini index 79d32db77daf4..d9664b87fbab1 100644 --- a/testing/web-platform/meta/html/dom/dynamic-markup-insertion/document-write/contentType.window.js.ini +++ b/testing/web-platform/meta/html/dom/dynamic-markup-insertion/document-write/contentType.window.js.ini @@ -3,7 +3,7 @@ if debug and not webrender and e10s and (os == "linux") and (version == "Ubuntu 16.04") and (processor == "x86") and (bits == 32): CRASH if debug and not webrender and not e10s and (os == "linux") and (version == "Ubuntu 16.04") and (processor == "x86") and (bits == 32): CRASH if debug and not webrender and e10s and (os == "linux") and (version == "Ubuntu 16.04") and (processor == "x86_64") and (bits == 64): CRASH - if debug and webrender and e10s and (os == "linux") and (version == "Ubuntu 16.04") and (processor == "x86_64") and (bits == 64): CRASH + if debug and webrender and e10s and (os == "linux") and (version == "Ubuntu 16.04") and (processor == "x86_64") and (bits == 64): TIMEOUT if debug and not webrender and e10s and (os == "win") and (version == "6.1.7601") and (processor == "x86") and (bits == 32): CRASH if debug and not webrender and e10s and (os == "win") and (version == "10.0.15063") and (processor == "x86_64") and (bits == 64): CRASH if debug and not webrender and e10s and (os == "mac") and (version == "OS X 10.10.5") and (processor == "x86_64") and (bits == 64): CRASH diff --git a/testing/web-platform/meta/mozilla-sync b/testing/web-platform/meta/mozilla-sync index e3b94c29bc96b..a22fd720ad855 100644 --- a/testing/web-platform/meta/mozilla-sync +++ b/testing/web-platform/meta/mozilla-sync @@ -1,2 +1,2 @@ -local: 90d9d20d4e4d7a79509c9a13a07e63a463f89527 -upstream: b395fb03bf62cbda20a383842b8da1701080ec43 +local: f456831609d31619a99840f8079c894ff589dc06 +upstream: 43d7898e180de2585d39ab12e3fda81633725e91 diff --git a/testing/web-platform/meta/navigation-timing/nav2_test_redirect_server.html.ini b/testing/web-platform/meta/navigation-timing/nav2_test_redirect_server.html.ini index 97bd265768587..4f732c2d0bbb6 100644 --- a/testing/web-platform/meta/navigation-timing/nav2_test_redirect_server.html.ini +++ b/testing/web-platform/meta/navigation-timing/nav2_test_redirect_server.html.ini @@ -1 +1,2 @@ prefs: [privacy.reduceTimerPrecision:false] +[nav2_test_redirect_server.html] diff --git a/testing/web-platform/meta/webdriver/tests/actions/key.py.ini b/testing/web-platform/meta/webdriver/tests/actions/key.py.ini deleted file mode 100644 index 31c24f64fd45a..0000000000000 --- a/testing/web-platform/meta/webdriver/tests/actions/key.py.ini +++ /dev/null @@ -1,3 +0,0 @@ -[key.py] - expected: - if debug and webrender and e10s and (os == "linux") and (version == "Ubuntu 16.04") and (processor == "x86_64") and (bits == 64): TIMEOUT diff --git a/testing/web-platform/meta/webdriver/tests/close_window/close.py.ini b/testing/web-platform/meta/webdriver/tests/close_window/close.py.ini deleted file mode 100644 index a7c17b97d906b..0000000000000 --- a/testing/web-platform/meta/webdriver/tests/close_window/close.py.ini +++ /dev/null @@ -1,3 +0,0 @@ -[close.py] - expected: - if debug and webrender and e10s and (os == "linux") and (version == "Ubuntu 16.04") and (processor == "x86_64") and (bits == 64): TIMEOUT diff --git a/testing/web-platform/meta/webdriver/tests/delete_session/delete.py.ini b/testing/web-platform/meta/webdriver/tests/delete_session/delete.py.ini deleted file mode 100644 index 1f611a544a5b3..0000000000000 --- a/testing/web-platform/meta/webdriver/tests/delete_session/delete.py.ini +++ /dev/null @@ -1,3 +0,0 @@ -[delete.py] - expected: - if debug and webrender and e10s and (os == "linux") and (version == "Ubuntu 16.04") and (processor == "x86_64") and (bits == 64): TIMEOUT diff --git a/testing/web-platform/meta/webdriver/tests/execute_async_script/collections.py.ini b/testing/web-platform/meta/webdriver/tests/execute_async_script/collections.py.ini index 5396a91858f22..3acccb7fb1564 100644 --- a/testing/web-platform/meta/webdriver/tests/execute_async_script/collections.py.ini +++ b/testing/web-platform/meta/webdriver/tests/execute_async_script/collections.py.ini @@ -2,3 +2,4 @@ [test_arguments] bug: 1453057 expected: FAIL + diff --git a/testing/web-platform/meta/webdriver/tests/get_element_attribute/get.py.ini b/testing/web-platform/meta/webdriver/tests/get_element_attribute/get.py.ini deleted file mode 100644 index 0235e42fe0c5c..0000000000000 --- a/testing/web-platform/meta/webdriver/tests/get_element_attribute/get.py.ini +++ /dev/null @@ -1,3 +0,0 @@ -[get.py] - expected: - if debug and webrender and e10s and (os == "linux") and (version == "Ubuntu 16.04") and (processor == "x86_64") and (bits == 64): TIMEOUT diff --git a/testing/web-platform/meta/webxr/interfaces.https.html.ini b/testing/web-platform/meta/webxr/interfaces.https.html.ini index 37537c97a0baa..3b03ebd1d021f 100644 --- a/testing/web-platform/meta/webxr/interfaces.https.html.ini +++ b/testing/web-platform/meta/webxr/interfaces.https.html.ini @@ -446,6 +446,3 @@ [XRWebGLLayer interface: operation getViewport(XRView)] expected: FAIL - [Test IDL implementation of WebXR API] - expected: FAIL - diff --git a/testing/web-platform/meta/workers/modules/dedicated-worker-import.html.ini b/testing/web-platform/meta/workers/modules/dedicated-worker-import.html.ini index aa3ea9b75a5ca..95b120688aaae 100644 --- a/testing/web-platform/meta/workers/modules/dedicated-worker-import.html.ini +++ b/testing/web-platform/meta/workers/modules/dedicated-worker-import.html.ini @@ -21,3 +21,12 @@ [importScripts() on module worker should throw an exception.] expected: NOTRUN + [Worker construction for non-existent script should throw an exception.] + expected: NOTRUN + + [Static import for non-existent script should throw an exception.] + expected: NOTRUN + + [Dynamic import for non-existent script should throw an exception.] + expected: NOTRUN + diff --git a/testing/web-platform/tests/2dcontext/OWNERS b/testing/web-platform/tests/2dcontext/OWNERS new file mode 100644 index 0000000000000..3bb6edf248aa9 --- /dev/null +++ b/testing/web-platform/tests/2dcontext/OWNERS @@ -0,0 +1,5 @@ +@AmeliaBR +@annevk +@kenrussell +@jdashg +@fserb diff --git a/testing/web-platform/tests/BackgroundSync/OWNERS b/testing/web-platform/tests/BackgroundSync/OWNERS new file mode 100644 index 0000000000000..9cc0eff9fd27f --- /dev/null +++ b/testing/web-platform/tests/BackgroundSync/OWNERS @@ -0,0 +1 @@ +@beverloo diff --git a/testing/web-platform/tests/WebCryptoAPI/generateKey/successes.js b/testing/web-platform/tests/WebCryptoAPI/generateKey/successes.js index f9d11eaa8bccd..b99e44d66d40f 100644 --- a/testing/web-platform/tests/WebCryptoAPI/generateKey/successes.js +++ b/testing/web-platform/tests/WebCryptoAPI/generateKey/successes.js @@ -70,21 +70,6 @@ function run_test(algorithmNames, slowTest) { }, testTag + ": generateKey" + parameterString(algorithm, extractable, usages)); } - // Only test a subset of tests with, e.g., ?1-10 in the URL - var subTestStart = 0; - var subTestEnd = Infinity; - var match; - if (location.search) { - match = /^\?(\d+)-(\d+|last)$/.exec(location.search); - if (match) { - subTestStart = match[1]; - if (match[2] !== "last") { - subTestEnd = match[2]; - } - } - } - var currentSubTest = 0; - // Test all valid sets of parameters for successful // key generation. testVectors.forEach(function(vector) { @@ -92,10 +77,7 @@ function run_test(algorithmNames, slowTest) { allAlgorithmSpecifiersFor(name).forEach(function(algorithm) { allValidUsages(vector.usages, false, vector.mandatoryUsages).forEach(function(usages) { [false, true].forEach(function(extractable) { - currentSubTest++; - if (currentSubTest >= subTestStart && currentSubTest <= subTestEnd) { - testSuccess(algorithm, extractable, usages, vector.resultType, "Success"); - } + subsetTest(testSuccess, algorithm, extractable, usages, vector.resultType, "Success"); }); }); }); diff --git a/testing/web-platform/tests/WebCryptoAPI/generateKey/successes_AES-CBC.https.any.js b/testing/web-platform/tests/WebCryptoAPI/generateKey/successes_AES-CBC.https.any.js index f9c1e7b6e7957..6feb60e5caa79 100644 --- a/testing/web-platform/tests/WebCryptoAPI/generateKey/successes_AES-CBC.https.any.js +++ b/testing/web-platform/tests/WebCryptoAPI/generateKey/successes_AES-CBC.https.any.js @@ -1,4 +1,5 @@ // META: timeout=long // META: script=../util/helpers.js +// META: script=/common/subset-tests.js // META: script=successes.js run_test(["AES-CBC"]); diff --git a/testing/web-platform/tests/WebCryptoAPI/generateKey/successes_AES-CTR.https.any.js b/testing/web-platform/tests/WebCryptoAPI/generateKey/successes_AES-CTR.https.any.js index a513ca767d78b..7b4f2df5fb1b3 100644 --- a/testing/web-platform/tests/WebCryptoAPI/generateKey/successes_AES-CTR.https.any.js +++ b/testing/web-platform/tests/WebCryptoAPI/generateKey/successes_AES-CTR.https.any.js @@ -1,4 +1,5 @@ // META: timeout=long // META: script=../util/helpers.js +// META: script=/common/subset-tests.js // META: script=successes.js run_test(["AES-CTR"]); diff --git a/testing/web-platform/tests/WebCryptoAPI/generateKey/successes_AES-GCM.https.any.js b/testing/web-platform/tests/WebCryptoAPI/generateKey/successes_AES-GCM.https.any.js index d9ee294004375..8e7bc92170c65 100644 --- a/testing/web-platform/tests/WebCryptoAPI/generateKey/successes_AES-GCM.https.any.js +++ b/testing/web-platform/tests/WebCryptoAPI/generateKey/successes_AES-GCM.https.any.js @@ -1,4 +1,5 @@ // META: timeout=long // META: script=../util/helpers.js +// META: script=/common/subset-tests.js // META: script=successes.js run_test(["AES-GCM"]); diff --git a/testing/web-platform/tests/WebCryptoAPI/generateKey/successes_AES-KW.https.any.js b/testing/web-platform/tests/WebCryptoAPI/generateKey/successes_AES-KW.https.any.js index 94b6a035a36a5..5eb023369f402 100644 --- a/testing/web-platform/tests/WebCryptoAPI/generateKey/successes_AES-KW.https.any.js +++ b/testing/web-platform/tests/WebCryptoAPI/generateKey/successes_AES-KW.https.any.js @@ -1,4 +1,5 @@ // META: timeout=long // META: script=../util/helpers.js +// META: script=/common/subset-tests.js // META: script=successes.js run_test(["AES-KW"]); diff --git a/testing/web-platform/tests/WebCryptoAPI/generateKey/successes_ECDH.https.any.js b/testing/web-platform/tests/WebCryptoAPI/generateKey/successes_ECDH.https.any.js index 34ed827183568..87590d23ea434 100644 --- a/testing/web-platform/tests/WebCryptoAPI/generateKey/successes_ECDH.https.any.js +++ b/testing/web-platform/tests/WebCryptoAPI/generateKey/successes_ECDH.https.any.js @@ -1,4 +1,5 @@ // META: timeout=long // META: script=../util/helpers.js +// META: script=/common/subset-tests.js // META: script=successes.js run_test(["ECDH"]); diff --git a/testing/web-platform/tests/WebCryptoAPI/generateKey/successes_ECDSA.https.any.js b/testing/web-platform/tests/WebCryptoAPI/generateKey/successes_ECDSA.https.any.js index 3d36f716b75a4..734d86972fc67 100644 --- a/testing/web-platform/tests/WebCryptoAPI/generateKey/successes_ECDSA.https.any.js +++ b/testing/web-platform/tests/WebCryptoAPI/generateKey/successes_ECDSA.https.any.js @@ -1,4 +1,5 @@ // META: timeout=long // META: script=../util/helpers.js +// META: script=/common/subset-tests.js // META: script=successes.js run_test(["ECDSA"]); diff --git a/testing/web-platform/tests/WebCryptoAPI/generateKey/successes_HMAC.https.any.js b/testing/web-platform/tests/WebCryptoAPI/generateKey/successes_HMAC.https.any.js index cd2c30b6c84c9..bc106f3c117c7 100644 --- a/testing/web-platform/tests/WebCryptoAPI/generateKey/successes_HMAC.https.any.js +++ b/testing/web-platform/tests/WebCryptoAPI/generateKey/successes_HMAC.https.any.js @@ -1,4 +1,5 @@ // META: timeout=long // META: script=../util/helpers.js +// META: script=/common/subset-tests.js // META: script=successes.js run_test(["HMAC"]); diff --git a/testing/web-platform/tests/WebCryptoAPI/generateKey/successes_RSA-OAEP.https.any.js b/testing/web-platform/tests/WebCryptoAPI/generateKey/successes_RSA-OAEP.https.any.js index 34f098966a366..b0412286c58eb 100644 --- a/testing/web-platform/tests/WebCryptoAPI/generateKey/successes_RSA-OAEP.https.any.js +++ b/testing/web-platform/tests/WebCryptoAPI/generateKey/successes_RSA-OAEP.https.any.js @@ -16,5 +16,6 @@ // META: variant=?141-150 // META: variant=?151-last // META: script=../util/helpers.js +// META: script=/common/subset-tests.js // META: script=successes.js run_test(["RSA-OAEP"]); diff --git a/testing/web-platform/tests/WebCryptoAPI/generateKey/successes_RSA-PSS.https.any.js b/testing/web-platform/tests/WebCryptoAPI/generateKey/successes_RSA-PSS.https.any.js index b11d6da7c1b3f..ea91c8f99b045 100644 --- a/testing/web-platform/tests/WebCryptoAPI/generateKey/successes_RSA-PSS.https.any.js +++ b/testing/web-platform/tests/WebCryptoAPI/generateKey/successes_RSA-PSS.https.any.js @@ -4,5 +4,6 @@ // META: variant=?21-30 // META: variant=?31-last // META: script=../util/helpers.js +// META: script=/common/subset-tests.js // META: script=successes.js run_test(["RSA-PSS"]); diff --git a/testing/web-platform/tests/WebCryptoAPI/generateKey/successes_RSASSA-PKCS1-v1_5.https.any.js b/testing/web-platform/tests/WebCryptoAPI/generateKey/successes_RSASSA-PKCS1-v1_5.https.any.js index 78d8aaf07fb95..fc785f9b31c96 100644 --- a/testing/web-platform/tests/WebCryptoAPI/generateKey/successes_RSASSA-PKCS1-v1_5.https.any.js +++ b/testing/web-platform/tests/WebCryptoAPI/generateKey/successes_RSASSA-PKCS1-v1_5.https.any.js @@ -4,5 +4,6 @@ // META: variant=?21-30 // META: variant=?31-last // META: script=../util/helpers.js +// META: script=/common/subset-tests.js // META: script=successes.js run_test(["RSASSA-PKCS1-v1_5"]); diff --git a/testing/web-platform/tests/apng/OWNERS b/testing/web-platform/tests/apng/OWNERS new file mode 100644 index 0000000000000..a2f0669fa514f --- /dev/null +++ b/testing/web-platform/tests/apng/OWNERS @@ -0,0 +1,3 @@ +@stuartparmenter +@svgeesus +@leonscroggins diff --git a/testing/web-platform/tests/audio-output/OWNERS b/testing/web-platform/tests/audio-output/OWNERS new file mode 100644 index 0000000000000..4a5c2a885b430 --- /dev/null +++ b/testing/web-platform/tests/audio-output/OWNERS @@ -0,0 +1 @@ +@guidou diff --git a/testing/web-platform/tests/common/subset-tests.js b/testing/web-platform/tests/common/subset-tests.js new file mode 100644 index 0000000000000..1810320e66085 --- /dev/null +++ b/testing/web-platform/tests/common/subset-tests.js @@ -0,0 +1,33 @@ +// Only test a subset of tests with, e.g., ?1-10 in the URL. +// Can be used together with +// Sample usage: +// for (const test of tests) { +// subsetTest(async_test, test.fn, test.name); +// } +(function() { + var subTestStart = 0; + var subTestEnd = Infinity; + var match; + if (location.search) { + match = /(?:^\?|&)(\d+)-(\d+|last)(?:&|$)/.exec(location.search); + if (match) { + subTestStart = parseInt(match[1], 10); + if (match[2] !== "last") { + subTestEnd = parseInt(match[2], 10); + } + } + } + function shouldRunSubTest(currentSubTest) { + return currentSubTest >= subTestStart && currentSubTest <= subTestEnd; + } + var currentSubTest = 0; + function subsetTest(testFunc, ...args) { + currentSubTest++; + if (shouldRunSubTest(currentSubTest)) { + return testFunc(...args); + } + return null; + } + self.shouldRunSubTest = shouldRunSubTest; + self.subsetTest = subsetTest; +})(); diff --git a/testing/web-platform/tests/credential-management/OWNERS b/testing/web-platform/tests/credential-management/OWNERS new file mode 100644 index 0000000000000..12f907ceb4181 --- /dev/null +++ b/testing/web-platform/tests/credential-management/OWNERS @@ -0,0 +1 @@ +@mikewest diff --git a/testing/web-platform/tests/css/css-contain/contain-layout-006.html b/testing/web-platform/tests/css/css-contain/contain-layout-006.html new file mode 100644 index 0000000000000..57dc518a65b37 --- /dev/null +++ b/testing/web-platform/tests/css/css-contain/contain-layout-006.html @@ -0,0 +1,28 @@ + + +CSS Containment Test: Layout containment absolutely positioned descendants + + + + + +

Test passes if there is a filled green square and no red.

+
+
+
diff --git a/testing/web-platform/tests/css/css-contain/contain-layout-007.html b/testing/web-platform/tests/css/css-contain/contain-layout-007.html new file mode 100644 index 0000000000000..39be5fe7fd06e --- /dev/null +++ b/testing/web-platform/tests/css/css-contain/contain-layout-007.html @@ -0,0 +1,28 @@ + + +CSS Containment Test: Layout containment fixed positioned descendants + + + + + +

Test passes if there is a filled green square and no red.

+
+
+
diff --git a/testing/web-platform/tests/css/css-contain/contain-paint-009.html b/testing/web-platform/tests/css/css-contain/contain-paint-009.html new file mode 100644 index 0000000000000..34ca8d72b5994 --- /dev/null +++ b/testing/web-platform/tests/css/css-contain/contain-paint-009.html @@ -0,0 +1,28 @@ + + +CSS Containment Test: Paint containment absolutely positioned descendants + + + + + +

Test passes if there is a filled green square and no red.

+
+
+
diff --git a/testing/web-platform/tests/css/css-contain/contain-paint-010.html b/testing/web-platform/tests/css/css-contain/contain-paint-010.html new file mode 100644 index 0000000000000..a05ce58f8bc47 --- /dev/null +++ b/testing/web-platform/tests/css/css-contain/contain-paint-010.html @@ -0,0 +1,28 @@ + + +CSS Containment Test: Paint containment fixed positioned descendants + + + + + +

Test passes if there is a filled green square and no red.

+
+
+
diff --git a/testing/web-platform/tests/css/css-content/OWNERS b/testing/web-platform/tests/css/css-content/OWNERS new file mode 100644 index 0000000000000..ae23ef8876e76 --- /dev/null +++ b/testing/web-platform/tests/css/css-content/OWNERS @@ -0,0 +1 @@ +@dauwhe diff --git a/testing/web-platform/tests/css/css-fill-stroke/OWNERS b/testing/web-platform/tests/css/css-fill-stroke/OWNERS new file mode 100644 index 0000000000000..4d8fac449153f --- /dev/null +++ b/testing/web-platform/tests/css/css-fill-stroke/OWNERS @@ -0,0 +1 @@ +@tabatkins diff --git a/testing/web-platform/tests/css/css-font-loading/OWNERS b/testing/web-platform/tests/css/css-font-loading/OWNERS new file mode 100644 index 0000000000000..404d8d1153dbf --- /dev/null +++ b/testing/web-platform/tests/css/css-font-loading/OWNERS @@ -0,0 +1,2 @@ +@tabatkins +@svgeesus diff --git a/testing/web-platform/tests/css/css-properties-values-api/OWNERS b/testing/web-platform/tests/css/css-properties-values-api/OWNERS new file mode 100644 index 0000000000000..00afa92246e83 --- /dev/null +++ b/testing/web-platform/tests/css/css-properties-values-api/OWNERS @@ -0,0 +1,2 @@ +@tabatkins +@astearns diff --git a/testing/web-platform/tests/css/css-scroll-anchoring/OWNERS b/testing/web-platform/tests/css/css-scroll-anchoring/OWNERS new file mode 100644 index 0000000000000..4d8fac449153f --- /dev/null +++ b/testing/web-platform/tests/css/css-scroll-anchoring/OWNERS @@ -0,0 +1 @@ +@tabatkins diff --git a/testing/web-platform/tests/css/css-scroll-snap/OWNERS b/testing/web-platform/tests/css/css-scroll-snap/OWNERS new file mode 100644 index 0000000000000..4d8fac449153f --- /dev/null +++ b/testing/web-platform/tests/css/css-scroll-snap/OWNERS @@ -0,0 +1 @@ +@tabatkins diff --git a/testing/web-platform/tests/css/css-shadow-parts/OWNERS b/testing/web-platform/tests/css/css-shadow-parts/OWNERS new file mode 100644 index 0000000000000..4d8fac449153f --- /dev/null +++ b/testing/web-platform/tests/css/css-shadow-parts/OWNERS @@ -0,0 +1 @@ +@tabatkins diff --git a/testing/web-platform/tests/css/css-sizing/intrinsic-percent-non-replaced-004-ref.html b/testing/web-platform/tests/css/css-sizing/intrinsic-percent-non-replaced-004-ref.html new file mode 100644 index 0000000000000..aa735cffdbbdb --- /dev/null +++ b/testing/web-platform/tests/css/css-sizing/intrinsic-percent-non-replaced-004-ref.html @@ -0,0 +1,56 @@ + +Reference + + + + +
+
+
+
+
+
+
+
+
+
+
+
diff --git a/testing/web-platform/tests/css/css-sizing/intrinsic-percent-non-replaced-004.html b/testing/web-platform/tests/css/css-sizing/intrinsic-percent-non-replaced-004.html new file mode 100644 index 0000000000000..6fc061abff4db --- /dev/null +++ b/testing/web-platform/tests/css/css-sizing/intrinsic-percent-non-replaced-004.html @@ -0,0 +1,60 @@ + +Percentages of width on non-replaced blocks are ignored for intrinsic sizing and resolved afterwards + + + + + + +
+
+
+
+
+
+
+
+
+
+
+
diff --git a/testing/web-platform/tests/css/css-sizing/intrinsic-percent-non-replaced-005-ref.html b/testing/web-platform/tests/css/css-sizing/intrinsic-percent-non-replaced-005-ref.html new file mode 100644 index 0000000000000..38f480c0acdbf --- /dev/null +++ b/testing/web-platform/tests/css/css-sizing/intrinsic-percent-non-replaced-005-ref.html @@ -0,0 +1,56 @@ + +Reference + + + + +
+
+
+
+
+
+
+
+
+
+
+
diff --git a/testing/web-platform/tests/css/css-sizing/intrinsic-percent-non-replaced-005.html b/testing/web-platform/tests/css/css-sizing/intrinsic-percent-non-replaced-005.html new file mode 100644 index 0000000000000..f105d942043c4 --- /dev/null +++ b/testing/web-platform/tests/css/css-sizing/intrinsic-percent-non-replaced-005.html @@ -0,0 +1,60 @@ + +Percentages of width on non-replaced blocks are ignored for intrinsic sizing and resolved afterwards + + + + + + +
+
+
+
+
+
+
+
+
+
+
+
diff --git a/testing/web-platform/tests/device-memory/OWNERS b/testing/web-platform/tests/device-memory/OWNERS new file mode 100644 index 0000000000000..3e7089cf2ccc1 --- /dev/null +++ b/testing/web-platform/tests/device-memory/OWNERS @@ -0,0 +1,2 @@ +@tdresser +@npm1 diff --git a/testing/web-platform/tests/docs/_writing-tests/testharness.md b/testing/web-platform/tests/docs/_writing-tests/testharness.md index e76d8bdad8697..652cf63d7e350 100644 --- a/testing/web-platform/tests/docs/_writing-tests/testharness.md +++ b/testing/web-platform/tests/docs/_writing-tests/testharness.md @@ -19,6 +19,44 @@ documented in two sections: See [server features][] for advanced testing features that are commonly used with testharness.js. See also the [general guidelines][] for all test types. +## Variants + +A test file can have multiple variants by including `meta` elements, +for example: + +``` + + +``` + +The test can then do different things based on the URL. + +There is a utility script in `/common/subset-tests.js` that works +well together with variants, where a test that would otherwise have +too many tests to be useful can be split up in ranges of subtests. +For example: + +``` + +Testing variants + + + + +``` + + ## Auto-generated test boilerplate While most JavaScript tests require a certain amount of HTML @@ -121,7 +159,7 @@ can be used to include both the global and a local `utils.js` in a test. Use `// META: timeout=long` at the beginning of the resource. -### Specifying test variants in auto-generated boilerplate tests +### Specifying test [variants](#variants) in auto-generated boilerplate tests Use `// META: variant=url-suffix` at the beginning of the resource. For example, diff --git a/testing/web-platform/tests/fetch/security/dangling-markup-mitigation-data-url.tentative.sub.html b/testing/web-platform/tests/fetch/security/dangling-markup-mitigation-data-url.tentative.sub.html index 3b13fccdc4b81..f27735daa1dd6 100644 --- a/testing/web-platform/tests/fetch/security/dangling-markup-mitigation-data-url.tentative.sub.html +++ b/testing/web-platform/tests/fetch/security/dangling-markup-mitigation-data-url.tentative.sub.html @@ -16,7 +16,8 @@ var doubleEscapedBrace = "&amp;lt;"; var rawNewline = " "; var escapedNewline = "&#10;"; - var doubleEscapedNewline = "&amp;#10;"; + // doubleEscapedNewline is used inside a data URI, and so must have its '#' escaped. + var doubleEscapedNewline = "&amp;%2310;"; function appendFrameAndGetElement(test, frame) { return new Promise((resolve, reject) => { diff --git a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/077.html b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/077.html index a7a59421250e6..4b98851ecddc6 100644 --- a/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/077.html +++ b/testing/web-platform/tests/html/semantics/scripting-1/the-script-element/execution-timing/077.html @@ -17,12 +17,12 @@ var t = async_test() function test() { - var script = createScript('data:text\/javascript,log("Script #1 ran")'); + var script = createScript('data:text\/javascript,log("Script %231 ran")'); var script2 = createScript('','log("Script #2 ran")'); if(script2) { head.removeChild(script2); } - var script3 = createScript('data:text\/javascript, log("Script #3 ran"); createScript(\'\', \'log("Script #4 ran")\')'); + var script3 = createScript('data:text\/javascript, log("Script %233 ran"); createScript(\'\', \'log("Script #4 ran")\')'); if(script3) { head.removeChild(script3); } diff --git a/testing/web-platform/tests/imagebitmap-renderingcontext/OWNERS b/testing/web-platform/tests/imagebitmap-renderingcontext/OWNERS new file mode 100644 index 0000000000000..3bb6edf248aa9 --- /dev/null +++ b/testing/web-platform/tests/imagebitmap-renderingcontext/OWNERS @@ -0,0 +1,5 @@ +@AmeliaBR +@annevk +@kenrussell +@jdashg +@fserb diff --git a/testing/web-platform/tests/mediacapture-image/OWNERS b/testing/web-platform/tests/mediacapture-image/OWNERS new file mode 100644 index 0000000000000..32380f13e3268 --- /dev/null +++ b/testing/web-platform/tests/mediacapture-image/OWNERS @@ -0,0 +1,2 @@ +@yellowdoge +@reillyeon diff --git a/testing/web-platform/tests/offscreen-canvas/OWNERS b/testing/web-platform/tests/offscreen-canvas/OWNERS new file mode 100644 index 0000000000000..3bb6edf248aa9 --- /dev/null +++ b/testing/web-platform/tests/offscreen-canvas/OWNERS @@ -0,0 +1,5 @@ +@AmeliaBR +@annevk +@kenrussell +@jdashg +@fserb diff --git a/testing/web-platform/tests/payment-request/PaymentAddress/attributes-and-toJSON-method-manual.https.html b/testing/web-platform/tests/payment-request/PaymentAddress/attributes-and-toJSON-method-manual.https.html index 3925cdd81e6ae..f767044d060f4 100644 --- a/testing/web-platform/tests/payment-request/PaymentAddress/attributes-and-toJSON-method-manual.https.html +++ b/testing/web-platform/tests/payment-request/PaymentAddress/attributes-and-toJSON-method-manual.https.html @@ -68,7 +68,7 @@

PaymentAddress interface