1
0
Fork 0
mirror of https://github.com/mozilla/pdf.js.git synced 2025-04-19 06:38:07 +02:00

[api-minor] Move the page reference/number caching into the API

Rather than having to handle this *manually* throughout the viewer, this functionality can instead be moved into the API which simplifies the code slightly.
This commit is contained in:
Jonas Jenwald 2024-04-24 21:55:50 +02:00
parent fa69d9a3bc
commit f6cd03955b
6 changed files with 42 additions and 74 deletions

View file

@ -419,6 +419,7 @@ class WorkerMessageHandler {
return { return {
rotate, rotate,
ref, ref,
refStr: ref?.toString() ?? null,
userUnit, userUnit,
view, view,
}; };

View file

@ -560,6 +560,16 @@ function getDataProp(val) {
); );
} }
function isRefProxy(ref) {
return (
typeof ref === "object" &&
Number.isInteger(ref?.num) &&
ref.num >= 0 &&
Number.isInteger(ref?.gen) &&
ref.gen >= 0
);
}
/** /**
* @typedef {Object} OnProgressParameters * @typedef {Object} OnProgressParameters
* @property {number} loaded - Currently loaded number of bytes. * @property {number} loaded - Currently loaded number of bytes.
@ -1066,6 +1076,14 @@ class PDFDocumentProxy {
return this.loadingTask.destroy(); return this.loadingTask.destroy();
} }
/**
* @param {RefProxy} ref - The page reference.
* @returns {number | null} The page number, if it's cached.
*/
cachedPageNumber(ref) {
return this._transport.cachedPageNumber(ref);
}
/** /**
* @type {DocumentInitParameters} A subset of the current * @type {DocumentInitParameters} A subset of the current
* {DocumentInitParameters}, which are needed in the viewer. * {DocumentInitParameters}, which are needed in the viewer.
@ -2340,6 +2358,8 @@ class WorkerTransport {
#pagePromises = new Map(); #pagePromises = new Map();
#pageRefCache = new Map();
#passwordCapability = null; #passwordCapability = null;
constructor(messageHandler, loadingTask, networkStream, params, factory) { constructor(messageHandler, loadingTask, networkStream, params, factory) {
@ -2483,6 +2503,7 @@ class WorkerTransport {
} }
this.#pageCache.clear(); this.#pageCache.clear();
this.#pagePromises.clear(); this.#pagePromises.clear();
this.#pageRefCache.clear();
// Allow `AnnotationStorage`-related clean-up when destroying the document. // Allow `AnnotationStorage`-related clean-up when destroying the document.
if (this.hasOwnProperty("annotationStorage")) { if (this.hasOwnProperty("annotationStorage")) {
this.annotationStorage.resetModified(); this.annotationStorage.resetModified();
@ -2915,6 +2936,10 @@ class WorkerTransport {
if (this.destroyed) { if (this.destroyed) {
throw new Error("Transport destroyed"); throw new Error("Transport destroyed");
} }
if (pageInfo.refStr) {
this.#pageRefCache.set(pageInfo.refStr, pageNumber);
}
const page = new PDFPageProxy( const page = new PDFPageProxy(
pageIndex, pageIndex,
pageInfo, pageInfo,
@ -2929,13 +2954,7 @@ class WorkerTransport {
} }
getPageIndex(ref) { getPageIndex(ref) {
if ( if (!isRefProxy(ref)) {
typeof ref !== "object" ||
!Number.isInteger(ref?.num) ||
ref.num < 0 ||
!Number.isInteger(ref?.gen) ||
ref.gen < 0
) {
return Promise.reject(new Error("Invalid pageIndex request.")); return Promise.reject(new Error("Invalid pageIndex request."));
} }
return this.messageHandler.sendWithPromise("GetPageIndex", { return this.messageHandler.sendWithPromise("GetPageIndex", {
@ -3076,6 +3095,14 @@ class WorkerTransport {
cleanupTextLayer(); cleanupTextLayer();
} }
cachedPageNumber(ref) {
if (!isRefProxy(ref)) {
return null;
}
const refStr = ref.gen === 0 ? `${ref.num}R` : `${ref.num}R${ref.gen}`;
return this.#pageRefCache.get(refStr) ?? null;
}
get loadingParams() { get loadingParams() {
const { disableAutoFetch, enableXfa } = this._params; const { disableAutoFetch, enableXfa } = this._params;
return shadow(this, "loadingParams", { return shadow(this, "loadingParams", {

View file

@ -106,12 +106,6 @@ class IPDFLinkService {
* @param {Object} action * @param {Object} action
*/ */
executeSetOCGState(action) {} executeSetOCGState(action) {}
/**
* @param {number} pageNum - page number.
* @param {Object} pageRef - reference to the page.
*/
cachePageRef(pageNum, pageRef) {}
} }
/** /**

View file

@ -49,8 +49,6 @@ const LinkTarget = {
class PDFLinkService { class PDFLinkService {
externalLinkEnabled = true; externalLinkEnabled = true;
#pagesRefCache = new Map();
/** /**
* @param {PDFLinkServiceOptions} options * @param {PDFLinkServiceOptions} options
*/ */
@ -74,7 +72,6 @@ class PDFLinkService {
setDocument(pdfDocument, baseUrl = null) { setDocument(pdfDocument, baseUrl = null) {
this.baseUrl = baseUrl; this.baseUrl = baseUrl;
this.pdfDocument = pdfDocument; this.pdfDocument = pdfDocument;
this.#pagesRefCache.clear();
} }
setViewer(pdfViewer) { setViewer(pdfViewer) {
@ -157,15 +154,14 @@ class PDFLinkService {
// Dest array looks like that: <page-ref> </XYZ|/FitXXX> <args..> // Dest array looks like that: <page-ref> </XYZ|/FitXXX> <args..>
const [destRef] = explicitDest; const [destRef] = explicitDest;
if (typeof destRef === "object" && destRef !== null) { if (destRef && typeof destRef === "object") {
pageNumber = this._cachedPageNumber(destRef); pageNumber = this.pdfDocument.cachedPageNumber(destRef);
if (!pageNumber) { if (!pageNumber) {
// Fetch the page reference if it's not yet available. This could // Fetch the page reference if it's not yet available. This could
// only occur during loading, before all pages have been resolved. // only occur during loading, before all pages have been resolved.
try { try {
pageNumber = (await this.pdfDocument.getPageIndex(destRef)) + 1; pageNumber = (await this.pdfDocument.getPageIndex(destRef)) + 1;
this.cachePageRef(pageNumber, destRef);
} catch { } catch {
console.error( console.error(
`goToDestination: "${destRef}" is not a valid page reference, for dest="${dest}".` `goToDestination: "${destRef}" is not a valid page reference, for dest="${dest}".`
@ -496,31 +492,6 @@ class PDFLinkService {
); );
} }
/**
* @param {number} pageNum - page number.
* @param {Object} pageRef - reference to the page.
*/
cachePageRef(pageNum, pageRef) {
if (!pageRef) {
return;
}
const refStr =
pageRef.gen === 0 ? `${pageRef.num}R` : `${pageRef.num}R${pageRef.gen}`;
this.#pagesRefCache.set(refStr, pageNum);
}
/**
* @ignore
*/
_cachedPageNumber(pageRef) {
if (!pageRef) {
return null;
}
const refStr =
pageRef.gen === 0 ? `${pageRef.num}R` : `${pageRef.num}R${pageRef.gen}`;
return this.#pagesRefCache.get(refStr) || null;
}
static #isValidExplicitDest(dest) { static #isValidExplicitDest(dest) {
if (!Array.isArray(dest) || dest.length < 2) { if (!Array.isArray(dest) || dest.length < 2) {
return false; return false;
@ -580,12 +551,6 @@ class PDFLinkService {
*/ */
class SimpleLinkService extends PDFLinkService { class SimpleLinkService extends PDFLinkService {
setDocument(pdfDocument, baseUrl = null) {} setDocument(pdfDocument, baseUrl = null) {}
/**
* @param {number} pageNum - page number.
* @param {Object} pageRef - reference to the page.
*/
cachePageRef(pageNum, pageRef) {}
} }
export { LinkTarget, PDFLinkService, SimpleLinkService }; export { LinkTarget, PDFLinkService, SimpleLinkService };

View file

@ -325,21 +325,10 @@ class PDFOutlineViewer extends BaseTreeViewer {
if (Array.isArray(explicitDest)) { if (Array.isArray(explicitDest)) {
const [destRef] = explicitDest; const [destRef] = explicitDest;
if (typeof destRef === "object" && destRef !== null) { if (destRef && typeof destRef === "object") {
pageNumber = this.linkService._cachedPageNumber(destRef); // The page reference must be available, since the current method
// won't be invoked until all pages have been loaded.
if (!pageNumber) { pageNumber = pdfDocument.cachedPageNumber(destRef);
try {
pageNumber = (await pdfDocument.getPageIndex(destRef)) + 1;
if (pdfDocument !== this._pdfDocument) {
return null; // The document was closed while the data resolved.
}
this.linkService.cachePageRef(pageNumber, destRef);
} catch {
// Invalid page reference, ignore it and continue parsing.
}
}
} else if (Number.isInteger(destRef)) { } else if (Number.isInteger(destRef)) {
pageNumber = destRef + 1; pageNumber = destRef + 1;
} }

View file

@ -935,11 +935,7 @@ class PDFViewer {
// Set the first `pdfPage` immediately, since it's already loaded, // Set the first `pdfPage` immediately, since it's already loaded,
// rather than having to repeat the `PDFDocumentProxy.getPage` call in // rather than having to repeat the `PDFDocumentProxy.getPage` call in
// the `this.#ensurePdfPageLoaded` method before rendering can start. // the `this.#ensurePdfPageLoaded` method before rendering can start.
const firstPageView = this._pages[0]; this._pages[0]?.setPdfPage(firstPdfPage);
if (firstPageView) {
firstPageView.setPdfPage(firstPdfPage);
this.linkService.cachePageRef(1, firstPdfPage.ref);
}
if (this._scrollMode === ScrollMode.PAGE) { if (this._scrollMode === ScrollMode.PAGE) {
// Ensure that the current page becomes visible on document load. // Ensure that the current page becomes visible on document load.
@ -994,7 +990,6 @@ class PDFViewer {
if (!pageView.pdfPage) { if (!pageView.pdfPage) {
pageView.setPdfPage(pdfPage); pageView.setPdfPage(pdfPage);
} }
this.linkService.cachePageRef(pageNum, pdfPage.ref);
if (--getPagesLeft === 0) { if (--getPagesLeft === 0) {
this._pagesCapability.resolve(); this._pagesCapability.resolve();
} }
@ -1718,9 +1713,6 @@ class PDFViewer {
if (!pageView.pdfPage) { if (!pageView.pdfPage) {
pageView.setPdfPage(pdfPage); pageView.setPdfPage(pdfPage);
} }
if (!this.linkService._cachedPageNumber?.(pdfPage.ref)) {
this.linkService.cachePageRef(pageView.id, pdfPage.ref);
}
return pdfPage; return pdfPage;
} catch (reason) { } catch (reason) {
console.error("Unable to get page for page view", reason); console.error("Unable to get page for page view", reason);