text: /**
   * @licstart The following is the entire license notice for the
   * Javascript code in this page
   *
   * Copyright 2020 Mozilla Foundation
   *
   * Licensed under the Apache License, Version 2.0 (the "License");
   * you may not use this file except in compliance with the License.
   * You may obtain a copy of the License at
   *
   *     http://www.apache.org/licenses/LICENSE-2.0
   *
   * Unless required by applicable law or agreed to in writing, software
   * distributed under the License is distributed on an "AS IS" BASIS,
   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   * See the License for the specific language governing permissions and
   * limitations under the License.
   *
   * @licend The above is the entire license notice for the
   * Javascript code in this page
   */
  "use strict";
  
  Object.defineProperty(exports, "__esModule", {
    value: true
  });
  exports.isDestHashesEqual = isDestHashesEqual;
  exports.isDestArraysEqual = isDestArraysEqual;
  exports.PDFHistory = void 0;
  
  var _ui_utils_metapdf = require("./ui_utils_metapdf.js");
  
  function _typeof(obj) { "@babel/helpers - typeof"; if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); }
  
  function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); }
  
  function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
  
  function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
  
  function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; }
  
  function _iterableToArrayLimit(arr, i) { if (typeof Symbol === "undefined" || !(Symbol.iterator in Object(arr))) return; var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"] != null) _i["return"](); } finally { if (_d) throw _e; } } return _arr; }
  
  function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
  
  function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
  
  function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
  
  function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }
  
  var HASH_CHANGE_TIMEOUT = 1000;
  var POSITION_UPDATED_THRESHOLD = 50;
  var UPDATE_VIEWAREA_TIMEOUT = 1000;
  
  function getCurrentHash() {
    return document.location.hash;
  }
  
  var PDFHistory = /*#__PURE__*/function () {
    function PDFHistory(_ref) {
      var _this = this;
  
      var linkService = _ref.linkService,
          eventBus = _ref.eventBus;
  
      _classCallCheck(this, PDFHistory);
  
      this.linkService = linkService;
      this.eventBus = eventBus;
      this._initialized = false;
      this._fingerprint = "";
      this.reset();
      this._boundEvents = null;
      this._isViewerInPresentationMode = false;
  
      this.eventBus._on("presentationmodechanged", function (evt) {
        _this._isViewerInPresentationMode = evt.active || evt.switchInProgress;
      });
  
      this.eventBus._on("pagesinit", function () {
        _this._isPagesLoaded = false;
  
        var onPagesLoaded = function onPagesLoaded(evt) {
          _this.eventBus._off("pagesloaded", onPagesLoaded);
  
          _this._isPagesLoaded = !!evt.pagesCount;
        };
  
        _this.eventBus._on("pagesloaded", onPagesLoaded);
      });
    }
  
    _createClass(PDFHistory, [{
      key: "initialize",
      value: function initialize(_ref2) {
        var fingerprint = _ref2.fingerprint,
            _ref2$resetHistory = _ref2.resetHistory,
            resetHistory = _ref2$resetHistory === void 0 ? false : _ref2$resetHistory,
            _ref2$updateUrl = _ref2.updateUrl,
            updateUrl = _ref2$updateUrl === void 0 ? false : _ref2$updateUrl;
  
        if (!fingerprint || typeof fingerprint !== "string") {
          console.error('PDFHistory.initialize: The "fingerprint" must be a non-empty string.');
          return;
        }
  
        if (this._initialized) {
          this.reset();
        }
  
        var reInitialized = this._fingerprint !== "" && this._fingerprint !== fingerprint;
        this._fingerprint = fingerprint;
        this._updateUrl = updateUrl === true;
        this._initialized = true;
  
        this._bindEvents();
  
        var state = window.history.state;
        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, true) || resetHistory) {
          var _this$_parseCurrentHa = this._parseCurrentHash(true),
              hash = _this$_parseCurrentHa.hash,
              page = _this$_parseCurrentHa.page,
              rotation = _this$_parseCurrentHa.rotation;
  
          if (!hash || reInitialized || resetHistory) {
            this._pushOrReplaceState(null, true);
  
            return;
          }
  
          this._pushOrReplaceState({
            hash: hash,
            page: page,
            rotation: rotation
          }, true);
  
          return;
        }
  
        var destination = state.destination;
  
        this._updateInternalState(destination, state.uid, true);
  
        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=".concat(destination.page);
        }
      }
    }, {
      key: "reset",
      value: function reset() {
        if (this._initialized) {
          this._pageHide();
  
          this._initialized = false;
  
          this._unbindEvents();
        }
  
        if (this._updateViewareaTimeout) {
          clearTimeout(this._updateViewareaTimeout);
          this._updateViewareaTimeout = null;
        }
  
        this._initialBookmark = null;
        this._initialRotation = null;
      }
    }, {
      key: "push",
      value: function push(_ref3) {
        var _this2 = this;
  
        var _ref3$namedDest = _ref3.namedDest,
            namedDest = _ref3$namedDest === void 0 ? null : _ref3$namedDest,
            explicitDest = _ref3.explicitDest,
            pageNumber = _ref3.pageNumber;
  
        if (!this._initialized) {
          return;
        }
  
        if (namedDest && typeof namedDest !== "string") {
          console.error("PDFHistory.push: " + "\"".concat(namedDest, "\" is not a valid namedDest parameter."));
          return;
        } else if (!Array.isArray(explicitDest)) {
          console.error("PDFHistory.push: " + "\"".concat(explicitDest, "\" is not a valid explicitDest parameter."));
          return;
        } else if (!(Number.isInteger(pageNumber) && pageNumber > 0 && pageNumber <= this.linkService.pagesCount)) {
          if (pageNumber !== null || this._destination) {
            console.error("PDFHistory.push: " + "\"".concat(pageNumber, "\" is not a valid pageNumber parameter."));
            return;
          }
        }
  
        var hash = namedDest || JSON.stringify(explicitDest);
  
        if (!hash) {
          return;
        }
  
        var 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: hash,
          page: pageNumber,
          rotation: this.linkService.rotation
        }, forceReplace);
  
        if (!this._popStateInProgress) {
          this._popStateInProgress = true;
          Promise.resolve().then(function () {
            _this2._popStateInProgress = false;
          });
        }
      }
    }, {
      key: "pushPage",
      value: function pushPage(pageNumber) {
        var _this$_destination,
            _this3 = this;
  
        if (!this._initialized) {
          return;
        }
  
        if (!(Number.isInteger(pageNumber) && pageNumber > 0 && pageNumber <= this.linkService.pagesCount)) {
          console.error("PDFHistory.pushPage: \"".concat(pageNumber, "\" is not a valid page number."));
          return;
        }
  
        if (((_this$_destination = this._destination) === null || _this$_destination === void 0 ? void 0 : _this$_destination.page) === pageNumber) {
          return;
        }
  
        if (this._popStateInProgress) {
          return;
        }
  
        this._pushOrReplaceState({
          hash: "page=".concat(pageNumber),
          page: pageNumber,
          rotation: this.linkService.rotation
        });
  
        if (!this._popStateInProgress) {
          this._popStateInProgress = true;
          Promise.resolve().then(function () {
            _this3._popStateInProgress = false;
          });
        }
      }
    }, {
      key: "pushCurrentPosition",
      value: function pushCurrentPosition() {
        if (!this._initialized || this._popStateInProgress) {
          return;
        }
  
        this._tryPushCurrentPosition();
      }
    }, {
      key: "back",
      value: function back() {
        if (!this._initialized || this._popStateInProgress) {
          return;
        }
  
        var state = window.history.state;
  
        if (this._isValidState(state) && state.uid > 0) {
          window.history.back();
        }
      }
    }, {
      key: "forward",
      value: function forward() {
        if (!this._initialized || this._popStateInProgress) {
          return;
        }
  
        var state = window.history.state;
  
        if (this._isValidState(state) && state.uid < this._maxUid) {
          window.history.forward();
        }
      }
    }, {
      key: "_pushOrReplaceState",
      value: function _pushOrReplaceState(destination) {
        var forceReplace = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
        var shouldReplace = forceReplace || !this._destination;
        var newState = {
          fingerprint: this._fingerprint,
          uid: shouldReplace ? this._uid : this._uid + 1,
          destination: destination
        };
  
        this._updateInternalState(destination, newState.uid);
  
        var newUrl;
  
        if (this._updateUrl && (destination === null || destination === void 0 ? void 0 : destination.hash)) {
          var baseUrl = document.location.href.split("#")[0];
  
          if (!baseUrl.startsWith("file://")) {
            newUrl = "".concat(baseUrl, "#").concat(destination.hash);
          }
        }
  
        if (shouldReplace) {
          window.history.replaceState(newState, "", newUrl);
        } else {
          window.history.pushState(newState, "", newUrl);
        }
      }
    }, {
      key: "_tryPushCurrentPosition",
      value: function _tryPushCurrentPosition() {
        var temporary = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
  
        if (!this._position) {
          return;
        }
  
        var position = this._position;
  
        if (temporary) {
          position = Object.assign(Object.create(null), 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;
        }
  
        var forceReplace = false;
  
        if (this._destination.page >= position.first && this._destination.page <= position.page) {
          if (this._destination.dest || !this._destination.first) {
            return;
          }
  
          forceReplace = true;
        }
  
        this._pushOrReplaceState(position, forceReplace);
      }
    }, {
      key: "_isValidState",
      value: function _isValidState(state) {
        var checkReload = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
  
        if (!state) {
          return false;
        }
  
        if (state.fingerprint !== this._fingerprint) {
          if (checkReload) {
            if (typeof state.fingerprint !== "string" || state.fingerprint.length !== this._fingerprint.length) {
              return false;
            }
  
            var _performance$getEntri = performance.getEntriesByType("navigation"),
                _performance$getEntri2 = _slicedToArray(_performance$getEntri, 1),
                perfEntry = _performance$getEntri2[0];
  
            if ((perfEntry === null || perfEntry === void 0 ? void 0 : perfEntry.type) !== "reload") {
              return false;
            }
          } else {
            return false;
          }
        }
  
        if (!Number.isInteger(state.uid) || state.uid < 0) {
          return false;
        }
  
        if (state.destination === null || _typeof(state.destination) !== "object") {
          return false;
        }
  
        return true;
      }
    }, {
      key: "_updateInternalState",
      value: function _updateInternalState(destination, uid) {
        var removeTemporary = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
  
        if (this._updateViewareaTimeout) {
          clearTimeout(this._updateViewareaTimeout);
          this._updateViewareaTimeout = null;
        }
  
        if (removeTemporary && (destination === null || destination === void 0 ? void 0 : destination.temporary)) {
          delete destination.temporary;
        }
  
        this._destination = destination;
        this._uid = uid;
        this._maxUid = Math.max(this._maxUid, uid);
        this._numPositionUpdates = 0;
      }
    }, {
      key: "_parseCurrentHash",
      value: function _parseCurrentHash() {
        var checkNameddest = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : false;
        var hash = unescape(getCurrentHash()).substring(1);
        var params = (0, _ui_utils_metapdf.parseQueryString)(hash);
        var nameddest = params.nameddest || "";
        var page = params.page | 0;
  
        if (!(Number.isInteger(page) && page > 0 && page <= this.linkService.pagesCount) || checkNameddest && nameddest.length > 0) {
          page = null;
        }
  
        return {
          hash: hash,
          page: page,
          rotation: this.linkService.rotation
        };
      }
    }, {
      key: "_updateViewarea",
      value: function _updateViewarea(_ref4) {
        var _this4 = this;
  
        var location = _ref4.location;
  
        if (this._updateViewareaTimeout) {
          clearTimeout(this._updateViewareaTimeout);
          this._updateViewareaTimeout = null;
        }
  
        this._position = {
          hash: this._isViewerInPresentationMode ? "page=".concat(location.pageNumber) : location.pdfOpenParams.substring(1),
          page: this.linkService.page,
          first: location.pageNumber,
          rotation: location.rotation
        };
  
        if (this._popStateInProgress) {
          return;
        }
  
        if (POSITION_UPDATED_THRESHOLD > 0 && this._isPagesLoaded && this._destination && !this._destination.page) {
          this._numPositionUpdates++;
        }
  
        if (UPDATE_VIEWAREA_TIMEOUT > 0) {
          this._updateViewareaTimeout = setTimeout(function () {
            if (!_this4._popStateInProgress) {
              _this4._tryPushCurrentPosition(true);
            }
  
            _this4._updateViewareaTimeout = null;
          }, UPDATE_VIEWAREA_TIMEOUT);
        }
      }
    }, {
      key: "_popState",
      value: function _popState(_ref5) {
        var _this5 = this;
  
        var state = _ref5.state;
        var newHash = getCurrentHash(),
            hashChanged = this._currentHash !== newHash;
        this._currentHash = newHash;
  
        if (!state) {
          this._uid++;
  
          var _this$_parseCurrentHa2 = this._parseCurrentHash(),
              hash = _this$_parseCurrentHa2.hash,
              page = _this$_parseCurrentHa2.page,
              rotation = _this$_parseCurrentHa2.rotation;
  
          this._pushOrReplaceState({
            hash: hash,
            page: page,
            rotation: rotation
          }, true);
  
          return;
        }
  
        if (!this._isValidState(state)) {
          return;
        }
  
        this._popStateInProgress = true;
  
        if (hashChanged) {
          this._blockHashChange++;
          (0, _ui_utils_metapdf.waitOnEventOrTimeout)({
            target: window,
            name: "hashchange",
            delay: HASH_CHANGE_TIMEOUT
          }).then(function () {
            _this5._blockHashChange--;
          });
        }
  
        var destination = state.destination;
  
        this._updateInternalState(destination, state.uid, true);
  
        if ((0, _ui_utils_metapdf.isValidRotation)(destination.rotation)) {
          this.linkService.rotation = destination.rotation;
        }
  
        if (destination.dest) {
          this.linkService.goToDestination(destination.dest);
        } else if (destination.hash) {
          this.linkService.setHash(destination.hash);
        } else if (destination.page) {
          this.linkService.page = destination.page;
        }
  
        Promise.resolve().then(function () {
          _this5._popStateInProgress = false;
        });
      }
    }, {
      key: "_pageHide",
      value: function _pageHide() {
        if (!this._destination || this._destination.temporary) {
          this._tryPushCurrentPosition();
        }
      }
    }, {
      key: "_bindEvents",
      value: function _bindEvents() {
        if (this._boundEvents) {
          return;
        }
  
        this._boundEvents = {
          updateViewarea: this._updateViewarea.bind(this),
          popState: this._popState.bind(this),
          pageHide: this._pageHide.bind(this)
        };
  
        this.eventBus._on("updateviewarea", this._boundEvents.updateViewarea);
  
        window.addEventListener("popstate", this._boundEvents.popState);
        window.addEventListener("pagehide", this._boundEvents.pageHide);
      }
    }, {
      key: "_unbindEvents",
      value: function _unbindEvents() {
        if (!this._boundEvents) {
          return;
        }
  
        this.eventBus._off("updateviewarea", this._boundEvents.updateViewarea);
  
        window.removeEventListener("popstate", this._boundEvents.popState);
        window.removeEventListener("pagehide", this._boundEvents.pageHide);
        this._boundEvents = null;
      }
    }, {
      key: "popStateInProgress",
      get: function get() {
        return this._initialized && (this._popStateInProgress || this._blockHashChange > 0);
      }
    }, {
      key: "initialBookmark",
      get: function get() {
        return this._initialized ? this._initialBookmark : null;
      }
    }, {
      key: "initialRotation",
      get: function get() {
        return this._initialized ? this._initialRotation : null;
      }
    }]);
  
    return PDFHistory;
  }();
  
  exports.PDFHistory = PDFHistory;
  
  function isDestHashesEqual(destHash, pushHash) {
    if (typeof destHash !== "string" || typeof pushHash !== "string") {
      return false;
    }
  
    if (destHash === pushHash) {
      return true;
    }
  
    var _parseQueryString = (0, _ui_utils_metapdf.parseQueryString)(destHash),
        nameddest = _parseQueryString.nameddest;
  
    if (nameddest === pushHash) {
      return true;
    }
  
    return false;
  }
  
  function isDestArraysEqual(firstDest, secondDest) {
    function isEntryEqual(first, second) {
      if (_typeof(first) !== _typeof(second)) {
        return false;
      }
  
      if (Array.isArray(first) || Array.isArray(second)) {
        return false;
      }
  
      if (first !== null && _typeof(first) === "object" && second !== null) {
        if (Object.keys(first).length !== Object.keys(second).length) {
          return false;
        }
  
        for (var key in first) {
          if (!isEntryEqual(first[key], second[key])) {
            return false;
          }
        }
  
        return true;
      }
  
      return first === second || Number.isNaN(first) && Number.isNaN(second);
    }
  
    if (!(Array.isArray(firstDest) && Array.isArray(secondDest))) {
      return false;
    }
  
    if (firstDest.length !== secondDest.length) {
      return false;
    }
  
    for (var i = 0, ii = firstDest.length; i < ii; i++) {
      if (!isEntryEqual(firstDest[i], secondDest[i])) {
        return false;
      }
    }
  
    return true;
  }