diff --git a/eslint.config.mjs b/eslint.config.mjs index ffb146870..7dd65dd6e 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -303,6 +303,11 @@ export default [ selector: "NewExpression[callee.name='Name']", message: "Use `Name.get()` rather than `new Name()`.", }, + { + selector: "NewExpression[callee.name='ObjectLoader']", + message: + "Use `ObjectLoader.load()` rather than `new ObjectLoader()`.", + }, { selector: "NewExpression[callee.name='Ref']", message: "Use `Ref.get()` rather than `new Ref()`.", diff --git a/src/core/annotation.js b/src/core/annotation.js index 3bdf9b788..b6106fbee 100644 --- a/src/core/annotation.js +++ b/src/core/annotation.js @@ -1158,15 +1158,12 @@ class Annotation { } } - loadResources(keys, appearance) { - return appearance.dict.getAsync("Resources").then(resources => { - if (!resources) { - return undefined; - } - - const objectLoader = new ObjectLoader(resources, keys, resources.xref); - return objectLoader.load().then(() => resources); - }); + async loadResources(keys, appearance) { + const resources = await appearance.dict.getAsync("Resources"); + if (resources) { + await ObjectLoader.load(resources, keys, resources.xref); + } + return resources; } async getOperatorList(evaluator, task, intent, annotationStorage) { diff --git a/src/core/document.js b/src/core/document.js index b51ddad40..0eb0f96d7 100644 --- a/src/core/document.js +++ b/src/core/document.js @@ -417,8 +417,7 @@ class Page { // TODO: add async `_getInheritableProperty` and remove this. await (this.resourcesPromise ??= this.pdfManager.ensure(this, "resources")); - const objectLoader = new ObjectLoader(this.resources, keys, this.xref); - await objectLoader.load(); + await ObjectLoader.load(this.resources, keys, this.xref); } async #getMergedResources(streamDict, keys) { @@ -430,8 +429,7 @@ class Page { if (!(localResources instanceof Dict && localResources.size)) { return this.resources; } - const objectLoader = new ObjectLoader(localResources, keys, this.xref); - await objectLoader.load(); + await ObjectLoader.load(localResources, keys, this.xref); return Dict.merge({ xref: this.xref, @@ -1254,8 +1252,7 @@ class PDFDocument { if (!(resources instanceof Dict)) { return; } - const objectLoader = new ObjectLoader(resources, ["Font"], this.xref); - await objectLoader.load(); + await ObjectLoader.load(resources, ["Font"], this.xref); const fontRes = resources.get("Font"); if (!(fontRes instanceof Dict)) { diff --git a/src/core/object_loader.js b/src/core/object_loader.js index 28763b25a..f36959239 100644 --- a/src/core/object_loader.js +++ b/src/core/object_loader.js @@ -54,7 +54,7 @@ function addChildren(node, nodesToVisit) { * entire PDF document object graph to be traversed. */ class ObjectLoader { - refSet = null; + refSet = new RefSet(); constructor(dict, keys, xref) { this.dict = dict; @@ -63,13 +63,7 @@ class ObjectLoader { } async load() { - // Don't walk the graph if all the data is already loaded. - if (this.xref.stream.isDataLoaded) { - return; - } - const { keys, dict } = this; - this.refSet = new RefSet(); // Setup the initial nodes to visit. const nodesToVisit = []; for (const key of keys) { @@ -144,6 +138,16 @@ class ObjectLoader { await this.#walk(nodesToRevisit); } } + + static async load(obj, keys, xref) { + // Don't walk the graph if all the data is already loaded. + if (xref.stream.isDataLoaded) { + return; + } + // eslint-disable-next-line no-restricted-syntax + const objLoader = new ObjectLoader(obj, keys, xref); + await objLoader.load(); + } } export { ObjectLoader };