Replace semi-private fields/methods with actual private ones in src/core/catalog.js

Additionally, move a couple of "public" fields out of the class constructor and initialize them directly instead.
This commit is contained in:
Jonas Jenwald 2025-05-21 11:34:32 +02:00
parent fc68a9f3ee
commit 0d2ab3c709

View File

@ -85,38 +85,49 @@ function fetchRemoteDest(action) {
} }
class Catalog { class Catalog {
#actualNumPages = null;
#catDict = null;
builtInCMapCache = new Map();
fontCache = new RefSetCache();
globalColorSpaceCache = new GlobalColorSpaceCache();
globalImageCache = new GlobalImageCache();
nonBlendModesSet = new RefSet();
pageDictCache = new RefSetCache();
pageIndexCache = new RefSetCache();
pageKidsCountCache = new RefSetCache();
standardFontDataCache = new Map();
systemFontCache = new Map();
constructor(pdfManager, xref) { constructor(pdfManager, xref) {
this.pdfManager = pdfManager; this.pdfManager = pdfManager;
this.xref = xref; this.xref = xref;
this._catDict = xref.getCatalogObj(); this.#catDict = xref.getCatalogObj();
if (!(this._catDict instanceof Dict)) { if (!(this.#catDict instanceof Dict)) {
throw new FormatError("Catalog object is not a dictionary."); throw new FormatError("Catalog object is not a dictionary.");
} }
// Given that `XRef.parse` will both fetch *and* validate the /Pages-entry, // Given that `XRef.parse` will both fetch *and* validate the /Pages-entry,
// the following call must always succeed here: // the following call must always succeed here:
this.toplevelPagesDict; // eslint-disable-line no-unused-expressions this.toplevelPagesDict; // eslint-disable-line no-unused-expressions
this._actualNumPages = null;
this.fontCache = new RefSetCache();
this.builtInCMapCache = new Map();
this.standardFontDataCache = new Map();
this.globalColorSpaceCache = new GlobalColorSpaceCache();
this.globalImageCache = new GlobalImageCache();
this.pageKidsCountCache = new RefSetCache();
this.pageIndexCache = new RefSetCache();
this.pageDictCache = new RefSetCache();
this.nonBlendModesSet = new RefSet();
this.systemFontCache = new Map();
} }
cloneDict() { cloneDict() {
return this._catDict.clone(); return this.#catDict.clone();
} }
get version() { get version() {
const version = this._catDict.get("Version"); const version = this.#catDict.get("Version");
if (version instanceof Name) { if (version instanceof Name) {
if (PDF_VERSION_REGEXP.test(version.name)) { if (PDF_VERSION_REGEXP.test(version.name)) {
return shadow(this, "version", version.name); return shadow(this, "version", version.name);
@ -127,7 +138,7 @@ class Catalog {
} }
get lang() { get lang() {
const lang = this._catDict.get("Lang"); const lang = this.#catDict.get("Lang");
return shadow( return shadow(
this, this,
"lang", "lang",
@ -140,7 +151,7 @@ class Catalog {
* `false` for XFA Foreground documents. * `false` for XFA Foreground documents.
*/ */
get needsRendering() { get needsRendering() {
const needsRendering = this._catDict.get("NeedsRendering"); const needsRendering = this.#catDict.get("NeedsRendering");
return shadow( return shadow(
this, this,
"needsRendering", "needsRendering",
@ -151,7 +162,7 @@ class Catalog {
get collection() { get collection() {
let collection = null; let collection = null;
try { try {
const obj = this._catDict.get("Collection"); const obj = this.#catDict.get("Collection");
if (obj instanceof Dict && obj.size > 0) { if (obj instanceof Dict && obj.size > 0) {
collection = obj; collection = obj;
} }
@ -167,7 +178,7 @@ class Catalog {
get acroForm() { get acroForm() {
let acroForm = null; let acroForm = null;
try { try {
const obj = this._catDict.get("AcroForm"); const obj = this.#catDict.get("AcroForm");
if (obj instanceof Dict && obj.size > 0) { if (obj instanceof Dict && obj.size > 0) {
acroForm = obj; acroForm = obj;
} }
@ -181,12 +192,12 @@ class Catalog {
} }
get acroFormRef() { get acroFormRef() {
const value = this._catDict.getRaw("AcroForm"); const value = this.#catDict.getRaw("AcroForm");
return shadow(this, "acroFormRef", value instanceof Ref ? value : null); return shadow(this, "acroFormRef", value instanceof Ref ? value : null);
} }
get metadata() { get metadata() {
const streamRef = this._catDict.getRaw("Metadata"); const streamRef = this.#catDict.getRaw("Metadata");
if (!(streamRef instanceof Ref)) { if (!(streamRef instanceof Ref)) {
return shadow(this, "metadata", null); return shadow(this, "metadata", null);
} }
@ -225,7 +236,7 @@ class Catalog {
get markInfo() { get markInfo() {
let markInfo = null; let markInfo = null;
try { try {
markInfo = this._readMarkInfo(); markInfo = this.#readMarkInfo();
} catch (ex) { } catch (ex) {
if (ex instanceof MissingDataException) { if (ex instanceof MissingDataException) {
throw ex; throw ex;
@ -235,11 +246,8 @@ class Catalog {
return shadow(this, "markInfo", markInfo); return shadow(this, "markInfo", markInfo);
} }
/** #readMarkInfo() {
* @private const obj = this.#catDict.get("MarkInfo");
*/
_readMarkInfo() {
const obj = this._catDict.get("MarkInfo");
if (!(obj instanceof Dict)) { if (!(obj instanceof Dict)) {
return null; return null;
} }
@ -273,7 +281,7 @@ class Catalog {
} }
#readStructTreeRoot() { #readStructTreeRoot() {
const rawObj = this._catDict.getRaw("StructTreeRoot"); const rawObj = this.#catDict.getRaw("StructTreeRoot");
const obj = this.xref.fetchIfRef(rawObj); const obj = this.xref.fetchIfRef(rawObj);
if (!(obj instanceof Dict)) { if (!(obj instanceof Dict)) {
return null; return null;
@ -285,7 +293,7 @@ class Catalog {
} }
get toplevelPagesDict() { get toplevelPagesDict() {
const pagesObj = this._catDict.get("Pages"); const pagesObj = this.#catDict.get("Pages");
if (!(pagesObj instanceof Dict)) { if (!(pagesObj instanceof Dict)) {
throw new FormatError("Invalid top-level pages dictionary."); throw new FormatError("Invalid top-level pages dictionary.");
} }
@ -295,7 +303,7 @@ class Catalog {
get documentOutline() { get documentOutline() {
let obj = null; let obj = null;
try { try {
obj = this._readDocumentOutline(); obj = this.#readDocumentOutline();
} catch (ex) { } catch (ex) {
if (ex instanceof MissingDataException) { if (ex instanceof MissingDataException) {
throw ex; throw ex;
@ -305,11 +313,8 @@ class Catalog {
return shadow(this, "documentOutline", obj); return shadow(this, "documentOutline", obj);
} }
/** #readDocumentOutline() {
* @private let obj = this.#catDict.get("Outlines");
*/
_readDocumentOutline() {
let obj = this._catDict.get("Outlines");
if (!(obj instanceof Dict)) { if (!(obj instanceof Dict)) {
return null; return null;
} }
@ -391,7 +396,7 @@ class Catalog {
get permissions() { get permissions() {
let permissions = null; let permissions = null;
try { try {
permissions = this._readPermissions(); permissions = this.#readPermissions();
} catch (ex) { } catch (ex) {
if (ex instanceof MissingDataException) { if (ex instanceof MissingDataException) {
throw ex; throw ex;
@ -401,10 +406,7 @@ class Catalog {
return shadow(this, "permissions", permissions); return shadow(this, "permissions", permissions);
} }
/** #readPermissions() {
* @private
*/
_readPermissions() {
const encrypt = this.xref.trailer.get("Encrypt"); const encrypt = this.xref.trailer.get("Encrypt");
if (!(encrypt instanceof Dict)) { if (!(encrypt instanceof Dict)) {
return null; return null;
@ -433,7 +435,7 @@ class Catalog {
get optionalContentConfig() { get optionalContentConfig() {
let config = null; let config = null;
try { try {
const properties = this._catDict.get("OCProperties"); const properties = this.#catDict.get("OCProperties");
if (!properties) { if (!properties) {
return shadow(this, "optionalContentConfig", null); return shadow(this, "optionalContentConfig", null);
} }
@ -645,11 +647,11 @@ class Catalog {
} }
setActualNumPages(num = null) { setActualNumPages(num = null) {
this._actualNumPages = num; this.#actualNumPages = num;
} }
get hasActualNumPages() { get hasActualNumPages() {
return this._actualNumPages !== null; return this.#actualNumPages !== null;
} }
get _pagesCount() { get _pagesCount() {
@ -663,7 +665,7 @@ class Catalog {
} }
get numPages() { get numPages() {
return this.hasActualNumPages ? this._actualNumPages : this._pagesCount; return this.hasActualNumPages ? this.#actualNumPages : this._pagesCount;
} }
get destinations() { get destinations() {
@ -721,14 +723,14 @@ class Catalog {
} }
#readDests() { #readDests() {
const obj = this._catDict.get("Names"); const obj = this.#catDict.get("Names");
const rawDests = []; const rawDests = [];
if (obj?.has("Dests")) { if (obj?.has("Dests")) {
rawDests.push(new NameTree(obj.getRaw("Dests"), this.xref)); rawDests.push(new NameTree(obj.getRaw("Dests"), this.xref));
} }
if (this._catDict.has("Dests")) { if (this.#catDict.has("Dests")) {
// Simple destination dictionary. // Simple destination dictionary.
rawDests.push(this._catDict.get("Dests")); rawDests.push(this.#catDict.get("Dests"));
} }
return rawDests; return rawDests;
} }
@ -736,7 +738,7 @@ class Catalog {
get pageLabels() { get pageLabels() {
let obj = null; let obj = null;
try { try {
obj = this._readPageLabels(); obj = this.#readPageLabels();
} catch (ex) { } catch (ex) {
if (ex instanceof MissingDataException) { if (ex instanceof MissingDataException) {
throw ex; throw ex;
@ -746,11 +748,8 @@ class Catalog {
return shadow(this, "pageLabels", obj); return shadow(this, "pageLabels", obj);
} }
/** #readPageLabels() {
* @private const obj = this.#catDict.getRaw("PageLabels");
*/
_readPageLabels() {
const obj = this._catDict.getRaw("PageLabels");
if (!obj) { if (!obj) {
return null; return null;
} }
@ -847,7 +846,7 @@ class Catalog {
} }
get pageLayout() { get pageLayout() {
const obj = this._catDict.get("PageLayout"); const obj = this.#catDict.get("PageLayout");
// Purposely use a non-standard default value, rather than 'SinglePage', to // Purposely use a non-standard default value, rather than 'SinglePage', to
// allow differentiating between `undefined` and /SinglePage since that does // allow differentiating between `undefined` and /SinglePage since that does
// affect the Scroll mode (continuous/non-continuous) used in Adobe Reader. // affect the Scroll mode (continuous/non-continuous) used in Adobe Reader.
@ -868,7 +867,7 @@ class Catalog {
} }
get pageMode() { get pageMode() {
const obj = this._catDict.get("PageMode"); const obj = this.#catDict.get("PageMode");
let pageMode = "UseNone"; // Default value. let pageMode = "UseNone"; // Default value.
if (obj instanceof Name) { if (obj instanceof Name) {
@ -886,7 +885,7 @@ class Catalog {
} }
get viewerPreferences() { get viewerPreferences() {
const obj = this._catDict.get("ViewerPreferences"); const obj = this.#catDict.get("ViewerPreferences");
if (!(obj instanceof Dict)) { if (!(obj instanceof Dict)) {
return shadow(this, "viewerPreferences", null); return shadow(this, "viewerPreferences", null);
} }
@ -1012,7 +1011,7 @@ class Catalog {
} }
get openAction() { get openAction() {
const obj = this._catDict.get("OpenAction"); const obj = this.#catDict.get("OpenAction");
const openAction = Object.create(null); const openAction = Object.create(null);
if (obj instanceof Dict) { if (obj instanceof Dict) {
@ -1040,7 +1039,7 @@ class Catalog {
} }
get attachments() { get attachments() {
const obj = this._catDict.get("Names"); const obj = this.#catDict.get("Names");
let attachments = null; let attachments = null;
if (obj instanceof Dict && obj.has("EmbeddedFiles")) { if (obj instanceof Dict && obj.has("EmbeddedFiles")) {
@ -1056,7 +1055,7 @@ class Catalog {
} }
get xfaImages() { get xfaImages() {
const obj = this._catDict.get("Names"); const obj = this.#catDict.get("Names");
let xfaImages = null; let xfaImages = null;
if (obj instanceof Dict && obj.has("XFAImages")) { if (obj instanceof Dict && obj.has("XFAImages")) {
@ -1074,8 +1073,8 @@ class Catalog {
return shadow(this, "xfaImages", xfaImages); return shadow(this, "xfaImages", xfaImages);
} }
_collectJavaScript() { #collectJavaScript() {
const obj = this._catDict.get("Names"); const obj = this.#catDict.get("Names");
let javaScript = null; let javaScript = null;
function appendIfJavaScriptDict(name, jsDict) { function appendIfJavaScriptDict(name, jsDict) {
@ -1112,7 +1111,7 @@ class Catalog {
} }
} }
// Append OpenAction "JavaScript" actions, if any, to the JavaScript map. // Append OpenAction "JavaScript" actions, if any, to the JavaScript map.
const openAction = this._catDict.get("OpenAction"); const openAction = this.#catDict.get("OpenAction");
if (openAction) { if (openAction) {
appendIfJavaScriptDict("OpenAction", openAction); appendIfJavaScriptDict("OpenAction", openAction);
} }
@ -1121,10 +1120,10 @@ class Catalog {
} }
get jsActions() { get jsActions() {
const javaScript = this._collectJavaScript(); const javaScript = this.#collectJavaScript();
let actions = collectActions( let actions = collectActions(
this.xref, this.xref,
this._catDict, this.#catDict,
DocumentActionEventType DocumentActionEventType
); );
@ -1164,7 +1163,7 @@ class Catalog {
const nodesToVisit = [this.toplevelPagesDict]; const nodesToVisit = [this.toplevelPagesDict];
const visitedNodes = new RefSet(); const visitedNodes = new RefSet();
const pagesRef = this._catDict.getRaw("Pages"); const pagesRef = this.#catDict.getRaw("Pages");
if (pagesRef instanceof Ref) { if (pagesRef instanceof Ref) {
visitedNodes.put(pagesRef); visitedNodes.put(pagesRef);
} }
@ -1301,7 +1300,7 @@ class Catalog {
const queue = [{ currentNode: this.toplevelPagesDict, posInKids: 0 }]; const queue = [{ currentNode: this.toplevelPagesDict, posInKids: 0 }];
const visitedNodes = new RefSet(); const visitedNodes = new RefSet();
const pagesRef = this._catDict.getRaw("Pages"); const pagesRef = this.#catDict.getRaw("Pages");
if (pagesRef instanceof Ref) { if (pagesRef instanceof Ref) {
visitedNodes.put(pagesRef); visitedNodes.put(pagesRef);
} }
@ -1505,7 +1504,7 @@ class Catalog {
} }
get baseUrl() { get baseUrl() {
const uri = this._catDict.get("URI"); const uri = this.#catDict.get("URI");
if (uri instanceof Dict) { if (uri instanceof Dict) {
const base = uri.get("Base"); const base = uri.get("Base");
if (typeof base === "string") { if (typeof base === "string") {