: str_replace(): Passing null to parameter #2 ($replace) of type array|string is deprecated in
if (!PDFWorkerUtil.isWorkerDisabled) {
warn("Setting up fake worker.");
PDFWorkerUtil.isWorkerDisabled = true;
PDFWorker._setupFakeWorkerGlobal.then(WorkerMessageHandler => {
this._readyCapability.reject(new Error("Worker was destroyed"));
const port = new LoopbackPort();
const id = `fake${PDFWorkerUtil.fakeWorkerId++}`;
const workerHandler = new MessageHandler(id + "_worker", id, port);
WorkerMessageHandler.setup(workerHandler, port);
const messageHandler = new MessageHandler(id, id + "_worker", port);
this._messageHandler = messageHandler;
this._readyCapability.resolve();
messageHandler.send("configure", {
verbosity: this.verbosity
this._readyCapability.reject(new Error(`Setting up fake worker failed: "${reason.message}".`));
this._webWorker.terminate();
PDFWorker.#workerPorts?.delete(this._port);
if (this._messageHandler) {
this._messageHandler.destroy();
this._messageHandler = null;
static fromPort(params) {
throw new Error("PDFWorker.fromPort - invalid method signature.");
const cachedPort = this.#workerPorts?.get(params.port);
if (cachedPort._pendingDestroy) {
throw new Error("PDFWorker.fromPort - the worker is being destroyed.\n" + "Please remember to await `PDFDocumentLoadingTask.destroy()`-calls.");
return new PDFWorker(params);
if (GlobalWorkerOptions.workerSrc) {
return GlobalWorkerOptions.workerSrc;
throw new Error('No "GlobalWorkerOptions.workerSrc" specified.');
static get #mainThreadWorkerMessageHandler() {
return globalThis.pdfjsWorker?.WorkerMessageHandler || null;
static get _setupFakeWorkerGlobal() {
const loader = async () => {
if (this.#mainThreadWorkerMessageHandler) {
return this.#mainThreadWorkerMessageHandler;
const worker = await import( /*webpackIgnore: true*/this.workerSrc);
return worker.WorkerMessageHandler;
return shadow(this, "_setupFakeWorkerGlobal", loader());
#methodPromises = new Map();
#pagePromises = new Map();
#pageRefCache = new Map();
#passwordCapability = null;
constructor(messageHandler, loadingTask, networkStream, params, factory) {
this.messageHandler = messageHandler;
this.loadingTask = loadingTask;
this.commonObjs = new PDFObjects();
this.fontLoader = new FontLoader({
ownerDocument: params.ownerDocument,
styleElement: params.styleElement
this.loadingParams = params.loadingParams;
this.canvasFactory = factory.canvasFactory;
this.filterFactory = factory.filterFactory;
this.cMapReaderFactory = factory.cMapReaderFactory;
this.standardFontDataFactory = factory.standardFontDataFactory;
this.destroyCapability = null;
this._networkStream = networkStream;
this._lastProgress = null;
this.downloadInfoCapability = Promise.withResolvers();
this.setupMessageHandler();
#cacheSimpleMethod(name, data = null) {
const cachedPromise = this.#methodPromises.get(name);
const promise = this.messageHandler.sendWithPromise(name, data);
this.#methodPromises.set(name, promise);
get annotationStorage() {
return shadow(this, "annotationStorage", new AnnotationStorage());
getRenderingIntent(intent, annotationMode = AnnotationMode.ENABLE, printAnnotationStorage = null, isOpList = false) {
let renderingIntent = RenderingIntentFlag.DISPLAY;
let annotationStorageSerializable = SerializableEmpty;
renderingIntent = RenderingIntentFlag.ANY;
renderingIntent = RenderingIntentFlag.PRINT;
warn(`getRenderingIntent - invalid intent: ${intent}`);
switch (annotationMode) {
case AnnotationMode.DISABLE:
renderingIntent += RenderingIntentFlag.ANNOTATIONS_DISABLE;
case AnnotationMode.ENABLE:
case AnnotationMode.ENABLE_FORMS:
renderingIntent += RenderingIntentFlag.ANNOTATIONS_FORMS;
case AnnotationMode.ENABLE_STORAGE:
renderingIntent += RenderingIntentFlag.ANNOTATIONS_STORAGE;
const annotationStorage = renderingIntent & RenderingIntentFlag.PRINT && printAnnotationStorage instanceof PrintAnnotationStorage ? printAnnotationStorage : this.annotationStorage;
annotationStorageSerializable = annotationStorage.serializable;
warn(`getRenderingIntent - invalid annotationMode: ${annotationMode}`);
renderingIntent += RenderingIntentFlag.OPLIST;
cacheKey: `${renderingIntent}_${annotationStorageSerializable.hash}`,
annotationStorageSerializable
if (this.destroyCapability) {
return this.destroyCapability.promise;
this.destroyCapability = Promise.withResolvers();
this.#passwordCapability?.reject(new Error("Worker was destroyed during onPassword callback"));
for (const page of this.#pageCache.values()) {
waitOn.push(page._destroy());
this.#pagePromises.clear();
this.#pageRefCache.clear();
if (this.hasOwnProperty("annotationStorage")) {
this.annotationStorage.resetModified();
const terminated = this.messageHandler.sendWithPromise("Terminate", null);
Promise.all(waitOn).then(() => {
this.#methodPromises.clear();
this.filterFactory.destroy();
this._networkStream?.cancelAllRequests(new AbortException("Worker was terminated."));
if (this.messageHandler) {
this.messageHandler.destroy();
this.messageHandler = null;
this.destroyCapability.resolve();
}, this.destroyCapability.reject);
return this.destroyCapability.promise;
messageHandler.on("GetReader", (data, sink) => {
assert(this._networkStream, "GetReader - no `IPDFStream` instance available.");
this._fullReader = this._networkStream.getFullReader();
this._fullReader.onProgress = evt => {
this._fullReader.read().then(function ({
assert(value instanceof ArrayBuffer, "GetReader - expected an ArrayBuffer.");
sink.enqueue(new Uint8Array(value), 1, [value]);
sink.onCancel = reason => {
this._fullReader.cancel(reason);
sink.ready.catch(readyReason => {
messageHandler.on("ReaderHeadersReady", data => {
const headersCapability = Promise.withResolvers();
const fullReader = this._fullReader;
fullReader.headersReady.then(() => {
if (!fullReader.isStreamingSupported || !fullReader.isRangeSupported) {
if (this._lastProgress) {
loadingTask.onProgress?.(this._lastProgress);
fullReader.onProgress = evt => {
loadingTask.onProgress?.({
headersCapability.resolve({
isStreamingSupported: fullReader.isStreamingSupported,
isRangeSupported: fullReader.isRangeSupported,
contentLength: fullReader.contentLength
}, headersCapability.reject);
return headersCapability.promise;
messageHandler.on("GetRangeReader", (data, sink) => {
assert(this._networkStream, "GetRangeReader - no `IPDFStream` instance available.");
const rangeReader = this._networkStream.getRangeReader(data.begin, data.end);
rangeReader.read().then(function ({
assert(value instanceof ArrayBuffer, "GetRangeReader - expected an ArrayBuffer.");
sink.enqueue(new Uint8Array(value), 1, [value]);
sink.onCancel = reason => {
rangeReader.cancel(reason);
sink.ready.catch(readyReason => {
messageHandler.on("GetDoc", ({
this._numPages = pdfInfo.numPages;
this._htmlForXfa = pdfInfo.htmlForXfa;
delete pdfInfo.htmlForXfa;
loadingTask._capability.resolve(new PDFDocumentProxy(pdfInfo, this));
messageHandler.on("DocException", function (ex) {
case "PasswordException":
reason = new PasswordException(ex.message, ex.code);
case "InvalidPDFException":
reason = new InvalidPDFException(ex.message);
case "MissingPDFException":
reason = new MissingPDFException(ex.message);
case "UnexpectedResponseException":
reason = new UnexpectedResponseException(ex.message, ex.status);
case "UnknownErrorException":
reason = new UnknownErrorException(ex.message, ex.details);
unreachable("DocException - expected a valid Error.");
loadingTask._capability.reject(reason);
messageHandler.on("PasswordRequest", exception => {
this.#passwordCapability = Promise.withResolvers();
if (loadingTask.onPassword) {
const updatePassword = password => {
if (password instanceof Error) {
this.#passwordCapability.reject(password);
this.#passwordCapability.resolve({
loadingTask.onPassword(updatePassword, exception.code);
this.#passwordCapability.reject(ex);
this.#passwordCapability.reject(new PasswordException(exception.message, exception.code));
return this.#passwordCapability.promise;
messageHandler.on("DataLoaded", data => {
loadingTask.onProgress?.({
this.downloadInfoCapability.resolve(data);
messageHandler.on("StartRenderPage", data => {
const page = this.#pageCache.get(data.pageIndex);
page._startRenderPage(data.transparency, data.cacheKey);
messageHandler.on("commonobj", ([id, type, exportedData]) => {
if (this.commonObjs.has(id)) {
if ("error" in exportedData) {
const exportedError = exportedData.error;
warn(`Error during font loading: ${exportedError}`);
this.commonObjs.resolve(id, exportedError);
const inspectFont = pdfBug && globalThis.FontInspector?.enabled ? (font, url) => globalThis.FontInspector.fontAdded(font, url) : null;
const font = new FontFaceObject(exportedData, {
this.fontLoader.bind(font).catch(() => messageHandler.sendWithPromise("FontFallback", {
if (!fontExtraProperties && font.data) {
this.commonObjs.resolve(id, font);
assert(imageRef, "The imageRef must be defined.");
for (const pageProxy of this.#pageCache.values()) {
for (const [, data] of pageProxy.objs) {
if (data?.ref !== imageRef) {
this.commonObjs.resolve(id, structuredClone(data));
this.commonObjs.resolve(id, exportedData);
throw new Error(`Got unknown common object type ${type}`);
messageHandler.on("obj", ([id, pageIndex, type, imageData]) => {
const pageProxy = this.#pageCache.get(pageIndex);
if (pageProxy.objs.has(id)) {
if (pageProxy._intentStates.size === 0) {
imageData?.bitmap?.close();
pageProxy.objs.resolve(id, imageData);
if (imageData?.dataLen > MAX_IMAGE_SIZE_TO_CACHE) {
pageProxy._maybeCleanupAfterRender = true;
pageProxy.objs.resolve(id, imageData);
throw new Error(`Got unknown object type ${type}`);
messageHandler.on("DocProgress", data => {
loadingTask.onProgress?.({
messageHandler.on("FetchBuiltInCMap", data => {
return Promise.reject(new Error("Worker was destroyed."));
if (!this.cMapReaderFactory) {
return Promise.reject(new Error("CMapReaderFactory not initialized, see the `useWorkerFetch` parameter."));
return this.cMapReaderFactory.fetch(data);
messageHandler.on("FetchStandardFontData", data => {
return Promise.reject(new Error("Worker was destroyed."));
if (!this.standardFontDataFactory) {
return Promise.reject(new Error("StandardFontDataFactory not initialized, see the `useWorkerFetch` parameter."));
return this.standardFontDataFactory.fetch(data);
return this.messageHandler.sendWithPromise("GetData", null);
if (this.annotationStorage.size <= 0) {
warn("saveDocument called while `annotationStorage` is empty, " + "please use the getData-method instead.");
} = this.annotationStorage.serializable;
return this.messageHandler.sendWithPromise("SaveDocument", {
isPureXfa: !!this._htmlForXfa,
numPages: this._numPages,
filename: this._fullReader?.filename ?? null
}, transfer).finally(() => {
this.annotationStorage.resetModified();
if (!Number.isInteger(pageNumber) || pageNumber <= 0 || pageNumber > this._numPages) {
return Promise.reject(new Error("Invalid page request."));
const pageIndex = pageNumber - 1,
cachedPromise = this.#pagePromises.get(pageIndex);
const promise = this.messageHandler.sendWithPromise("GetPage", {