: str_replace(): Passing null to parameter #2 ($replace) of type array|string is deprecated in
IsCollectionPresent: !!this.catalog.collection,
IsSignaturesPresent: this.formInfo.hasSignatures
infoDict = this.xref.trailer.get("Info");
if (err instanceof MissingDataException) {
info("The document information dictionary is invalid.");
if (!(infoDict instanceof Dict)) {
return shadow(this, "documentInfo", docInfo);
for (const key of infoDict.getKeys()) {
const value = infoDict.get(key);
if (typeof value === "string") {
docInfo[key] = stringToPDFString(value);
if (value instanceof Name) {
customValue = stringToPDFString(value);
if (value instanceof Name) {
if (customValue === undefined) {
warn(`Bad value, for custom key "${key}", in Info: ${value}.`);
docInfo.Custom = Object.create(null);
docInfo.Custom[key] = customValue;
warn(`Bad value, for key "${key}", in Info: ${value}.`);
return shadow(this, "documentInfo", docInfo);
function validate(data) {
return typeof data === "string" && data.length > 0 && data !== EMPTY_FINGERPRINT;
function hexString(hash) {
for (const num of hash) {
const hex = num.toString(16);
buf.push(hex.padStart(2, "0"));
const idArray = this.xref.trailer.get("ID");
let hashOriginal, hashModified;
if (Array.isArray(idArray) && validate(idArray[0])) {
hashOriginal = stringToBytes(idArray[0]);
if (idArray[1] !== idArray[0] && validate(idArray[1])) {
hashModified = stringToBytes(idArray[1]);
hashOriginal = calculateMD5(this.stream.getByteRange(0, FINGERPRINT_FIRST_BYTES), 0, FINGERPRINT_FIRST_BYTES);
return shadow(this, "fingerprints", [hexString(hashOriginal), hashModified ? hexString(hashModified) : null]);
async _getLinearizationPage(pageIndex) {
const ref = Ref.get(linearization.objectNumberFirst, 0);
const obj = await xref.fetchAsync(ref);
if (obj instanceof Dict) {
let type = obj.getRaw("Type");
if (type instanceof Ref) {
type = await xref.fetchAsync(type);
if (isName(type, "Page") || !obj.has("Type") && !obj.has("Kids") && obj.has("Contents")) {
if (!catalog.pageKidsCountCache.has(ref)) {
catalog.pageKidsCountCache.put(ref, 1);
if (!catalog.pageIndexCache.has(ref)) {
catalog.pageIndexCache.put(ref, 0);
throw new FormatError("The Linearization dictionary doesn't point to a valid Page dictionary.");
warn(`_getLinearizationPage: "${reason.message}".`);
return catalog.getPageDict(pageIndex);
const cachedPromise = this._pagePromises.get(pageIndex);
promise = Promise.resolve([Dict.empty, null]);
} else if (linearization?.pageFirst === pageIndex) {
promise = this._getLinearizationPage(pageIndex);
promise = catalog.getPageDict(pageIndex);
promise = promise.then(([pageDict, ref]) => {
pdfManager: this.pdfManager,
globalIdFactory: this._globalIdFactory,
fontCache: catalog.fontCache,
builtInCMapCache: catalog.builtInCMapCache,
standardFontDataCache: catalog.standardFontDataCache,
globalImageCache: catalog.globalImageCache,
systemFontCache: catalog.systemFontCache,
nonBlendModesSet: catalog.nonBlendModesSet,
this._pagePromises.set(pageIndex, promise);
async checkFirstPage(recoveryMode = false) {
if (reason instanceof XRefEntryException) {
this._pagePromises.delete(0);
throw new XRefParseException();
async checkLastPage(recoveryMode = false) {
catalog.setActualNumPages();
await Promise.all([pdfManager.ensureDoc("xfaFactory"), pdfManager.ensureDoc("linearization"), pdfManager.ensureCatalog("numPages")]);
} else if (this.linearization) {
numPages = this.linearization.numPages;
numPages = catalog.numPages;
if (!Number.isInteger(numPages)) {
throw new FormatError("Page count is not an integer.");
} else if (numPages <= 1) {
await this.getPage(numPages - 1);
this._pagePromises.delete(numPages - 1);
if (reason instanceof XRefEntryException && !recoveryMode) {
throw new XRefParseException();
warn(`checkLastPage - invalid /Pages tree /Count: ${numPages}.`);
pagesTree = await catalog.getAllPageDicts(recoveryMode);
if (reasonAll instanceof XRefEntryException && !recoveryMode) {
throw new XRefParseException();
catalog.setActualNumPages(1);
for (const [pageIndex, [pageDict, ref]] of pagesTree) {
if (pageDict instanceof Error) {
promise = Promise.reject(pageDict);
promise = Promise.resolve(new Page({
globalIdFactory: this._globalIdFactory,
fontCache: catalog.fontCache,
builtInCMapCache: catalog.builtInCMapCache,
standardFontDataCache: catalog.standardFontDataCache,
globalImageCache: catalog.globalImageCache,
systemFontCache: catalog.systemFontCache,
nonBlendModesSet: catalog.nonBlendModesSet,
this._pagePromises.set(pageIndex, promise);
catalog.setActualNumPages(pagesTree.size);
fontFallback(id, handler) {
return this.catalog.fontFallback(id, handler);
async cleanup(manuallyTriggered = false) {
return this.catalog ? this.catalog.cleanup(manuallyTriggered) : clearGlobalCaches();
async #collectFieldObjects(name, fieldRef, promises, annotationGlobals, visitedRefs) {
if (!(fieldRef instanceof Ref) || visitedRefs.has(fieldRef)) {
visitedRefs.put(fieldRef);
const field = await xref.fetchAsync(fieldRef);
if (!(field instanceof Dict)) {
const partName = stringToPDFString(await field.getAsync("T"));
name = name === "" ? partName : `${name}.${partName}`;
obj = obj.getRaw("Parent");
if (obj instanceof Ref) {
if (visitedRefs.has(obj)) {
obj = await xref.fetchAsync(obj);
if (!(obj instanceof Dict)) {
const partName = stringToPDFString(await obj.getAsync("T"));
name = name === "" ? partName : `${name}.${partName}`;
if (!promises.has(name)) {
promises.get(name).push(AnnotationFactory.create(xref, fieldRef, annotationGlobals, null, true, null).then(annotation => annotation?.getFieldObject()).catch(function (reason) {
warn(`#collectFieldObjects: "${reason}".`);
if (!field.has("Kids")) {
const kids = await field.getAsync("Kids");
if (Array.isArray(kids)) {
for (const kid of kids) {
await this.#collectFieldObjects(name, kid, promises, annotationGlobals, visitedRefs);
if (!this.formInfo.hasFields) {
return shadow(this, "fieldObjects", Promise.resolve(null));
const promise = Promise.all([this.pdfManager.ensureDoc("annotationGlobals"), this.pdfManager.ensureCatalog("acroForm")]).then(async ([annotationGlobals, acroForm]) => {
if (!annotationGlobals) {
const visitedRefs = new RefSet();
const allFields = Object.create(null);
const fieldPromises = new Map();
for (const fieldRef of await acroForm.getAsync("Fields")) {
await this.#collectFieldObjects("", fieldRef, fieldPromises, annotationGlobals, visitedRefs);
for (const [name, promises] of fieldPromises) {
allPromises.push(Promise.all(promises).then(fields => {
fields = fields.filter(field => !!field);
allFields[name] = fields;
await Promise.all(allPromises);
return shadow(this, "fieldObjects", promise);
const promise = this.pdfManager.ensureDoc("_parseHasJSActions");
return shadow(this, "hasJSActions", promise);
async _parseHasJSActions() {
const [catalogJsActions, fieldObjects] = await Promise.all([this.pdfManager.ensureCatalog("jsActions"), this.pdfManager.ensureDoc("fieldObjects")]);
return Object.values(fieldObjects).some(fieldObject => fieldObject.some(object => object.actions !== null));
get calculationOrderIds() {
const acroForm = this.catalog.acroForm;
if (!acroForm?.has("CO")) {
return shadow(this, "calculationOrderIds", null);
const calculationOrder = acroForm.get("CO");
if (!Array.isArray(calculationOrder) || calculationOrder.length === 0) {
return shadow(this, "calculationOrderIds", null);
for (const id of calculationOrder) {
return shadow(this, "calculationOrderIds", null);
return shadow(this, "calculationOrderIds", ids);
get annotationGlobals() {
return shadow(this, "annotationGlobals", AnnotationFactory.createGlobals(this.pdfManager));
;// CONCATENATED MODULE: ./src/core/pdf_manager.js
function parseDocBaseUrl(url) {
const absoluteUrl = createValidAbsoluteUrl(url);
warn(`Invalid absolute docBaseUrl: "${url}".`);
if (this.constructor === BasePdfManager) {
unreachable("Cannot initialize BasePdfManager.");
this._docBaseUrl = parseDocBaseUrl(args.docBaseUrl);
this._docId = args.docId;
this._password = args.password;
this.enableXfa = args.enableXfa;
args.evaluatorOptions.isOffscreenCanvasSupported &&= FeatureTest.isOffscreenCanvasSupported;
this.evaluatorOptions = Object.freeze(args.evaluatorOptions);
return this.pdfDocument.catalog;
return this.ensure(this.pdfDocument, prop, args);
return this.ensure(this.pdfDocument.xref, prop, args);
ensureCatalog(prop, args) {
return this.ensure(this.pdfDocument.catalog, prop, args);
return this.pdfDocument.getPage(pageIndex);
fontFallback(id, handler) {
return this.pdfDocument.fontFallback(id, handler);
loadXfaFonts(handler, task) {
return this.pdfDocument.loadXfaFonts(handler, task);
return this.pdfDocument.loadXfaImages();
serializeXfaData(annotationStorage) {
return this.pdfDocument.serializeXfaData(annotationStorage);
cleanup(manuallyTriggered = false) {
return this.pdfDocument.cleanup(manuallyTriggered);
async ensure(obj, prop, args) {
unreachable("Abstract method `ensure` called");
requestRange(begin, end) {
unreachable("Abstract method `requestRange` called");
requestLoadedStream(noFetch = false) {
unreachable("Abstract method `requestLoadedStream` called");
sendProgressiveData(chunk) {
unreachable("Abstract method `sendProgressiveData` called");
updatePassword(password) {
this._password = password;
unreachable("Abstract method `terminate` called");
class LocalPdfManager extends BasePdfManager {
const stream = new Stream(args.source);
this.pdfDocument = new PDFDocument(this, stream);
this._loadedStreamPromise = Promise.resolve(stream);
async ensure(obj, prop, args) {
if (typeof value === "function") {
return value.apply(obj, args);
requestRange(begin, end) {
return Promise.resolve();
requestLoadedStream(noFetch = false) {
return this._loadedStreamPromise;
class NetworkPdfManager extends BasePdfManager {
this.streamManager = new ChunkedStreamManager(args.source, {
msgHandler: args.handler,
disableAutoFetch: args.disableAutoFetch,
rangeChunkSize: args.rangeChunkSize
this.pdfDocument = new PDFDocument(this, this.streamManager.getStream());
async ensure(obj, prop, args) {
if (typeof value === "function") {
return value.apply(obj, args);
if (!(ex instanceof MissingDataException)) {
await this.requestRange(ex.begin, ex.end);
return this.ensure(obj, prop, args);
requestRange(begin, end) {
return this.streamManager.requestRange(begin, end);