Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
da1f42c
Skip the "should reorder thumbnails after dropping two adjacent pages…
timvandermeij Mar 15, 2026
1db3774
Make sure the menuitems are readable when hovering them (bug 2023138)
calixteman Mar 20, 2026
c17801b
Avoid getting null value in RefSet when cloning
calixteman Mar 20, 2026
04272de
Add the possibility to save added annotations when reorganizing a pdf…
calixteman Mar 17, 2026
4aee2e8
Correctly focus the pasted page (bug 2022516)
calixteman Mar 20, 2026
008181a
Add the basic telemetry for Organize feature (bug 2022481)
calixteman Mar 20, 2026
5299eb2
Remove explicit `name`/`filename` validation in the `BaseCMapReaderFa…
Snuffleupagus Mar 20, 2026
1182284
Trigger the current find after a page has been moved (bug 2023150)
calixteman Mar 20, 2026
0617e3e
Merge pull request #20923 from calixteman/bug2023138
calixteman Mar 20, 2026
504505b
Merge pull request #20924 from calixteman/fix_null_ref
calixteman Mar 20, 2026
16aee06
Merge pull request #20925 from calixteman/reorganize_save_annotations
calixteman Mar 20, 2026
652822b
[Firefox] Ensure that worker-thread fetching is used for built-in CMa…
Snuffleupagus Mar 20, 2026
2c58120
Merge pull request #20929 from calixteman/bug2022481
calixteman Mar 20, 2026
dabb2b9
Merge pull request #20927 from Snuffleupagus/Firefox-enforce-worker-b…
calixteman Mar 20, 2026
5bdeb79
Merge pull request #20926 from calixteman/bug2022516
calixteman Mar 20, 2026
e1f02be
Pass the global signal the text layer builder in order to remove all …
calixteman Mar 20, 2026
5a240f7
Merge pull request #20932 from calixteman/bug2023150
calixteman Mar 20, 2026
977e4f2
Merge pull request #20928 from calixteman/pass_global_signal_text_layer
calixteman Mar 20, 2026
0dd1556
Merge pull request #20880 from timvandermeij/disable-reorder-test
timvandermeij Mar 20, 2026
ab228da
Merge pull request #20931 from Snuffleupagus/rm-factory-name-validation
timvandermeij Mar 20, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/core/annotation.js
Original file line number Diff line number Diff line change
Expand Up @@ -354,12 +354,12 @@ class AnnotationFactory {

static async saveNewAnnotations(
evaluator,
xref,
task,
annotations,
imagePromises,
changes
) {
const xref = evaluator.xref;
let baseFontRef;
const promises = [];
const { isOffscreenCanvasSupported } = evaluator.options;
Expand Down
5 changes: 5 additions & 0 deletions src/core/document.js
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,10 @@ class Page {
});
}

createAnnotationEvaluator(handler) {
return this.#createPartialEvaluator(handler);
}

#getInheritableProperty(key, getArray = false) {
const value = getInheritableProperty({
dict: this.pageDict,
Expand Down Expand Up @@ -386,6 +390,7 @@ class Page {
);
const newData = await AnnotationFactory.saveNewAnnotations(
partialEvaluator,
this.xref,
task,
annotations,
imagePromises,
Expand Down
80 changes: 71 additions & 9 deletions src/core/editor/pdf_editor.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,21 @@
/** @typedef {import("../document.js").PDFDocument} PDFDocument */
/** @typedef {import("../document.js").Page} Page */
/** @typedef {import("../xref.js").XRef} XRef */
/** @typedef {import("../worker.js").WorkerTask} WorkerTask */
// eslint-disable-next-line max-len
/** @typedef {import("../../shared/message_handler.js").MessageHandler} MessageHandler */

import {
deepCompare,
getInheritableProperty,
getNewAnnotationsMap,
stringToAsciiOrUTF16BE,
} from "../core_utils.js";
import { Dict, isName, Name, Ref, RefSet, RefSetCache } from "../primitives.js";
import { getModificationDate, stringToPDFString } from "../../shared/util.js";
import { incrementalUpdate, writeValue } from "../writer.js";
import { NameTree, NumberTree } from "../name_number_tree.js";
import { AnnotationFactory } from "../annotation.js";
import { BaseStream } from "../base_stream.js";
import { StringStream } from "../stream.js";

Expand Down Expand Up @@ -75,8 +80,9 @@ class DocumentData {
}

class XRefWrapper {
constructor(entries) {
constructor(entries, getNewRef) {
this.entries = entries;
this._getNewRef = getNewRef;
}

fetch(ref) {
Expand All @@ -94,11 +100,17 @@ class XRefWrapper {
fetchAsync(ref) {
return Promise.resolve(this.fetch(ref));
}

getNewTemporaryRef() {
return this._getNewRef();
}
}

class PDFEditor {
hasSingleFile = false;

#newAnnotationsParams = null;

currentDocument = null;

oldPages = [];
Expand All @@ -107,7 +119,7 @@ class PDFEditor {

xref = [null];

xrefWrapper = new XRefWrapper(this.xref);
xrefWrapper = new XRefWrapper(this.xref, () => this.newRef);

newRefCount = 1;

Expand Down Expand Up @@ -249,7 +261,8 @@ class PDFEditor {
obj = obj.slice();
}
for (let i = 0, ii = obj.length; i < ii; i++) {
const postponedActions = postponedRefCopies.get(obj[i]);
const postponedActions =
obj[i] instanceof Ref && postponedRefCopies.get(obj[i]);
if (postponedActions) {
// The object is a reference that needs to be copied later.
postponedActions.push(ref => (obj[i] = ref));
Expand Down Expand Up @@ -277,7 +290,8 @@ class PDFEditor {
}
if (dict) {
for (const [key, rawObj] of dict.getRawEntries()) {
const postponedActions = postponedRefCopies.get(rawObj);
const postponedActions =
rawObj instanceof Ref && postponedRefCopies.get(rawObj);
if (postponedActions) {
// The object is a reference that needs to be copied later.
postponedActions.push(ref => dict.set(key, ref));
Expand Down Expand Up @@ -535,13 +549,33 @@ class PDFEditor {
/**
* Extract pages from the given documents.
* @param {Array<PageInfo>} pageInfos
* @param {Object} annotationStorage - The annotation storage containing the
* annotations to be merged into the new document.
* @param {MessageHandler} handler - The message handler to use for processing
* the annotations.
* @param {WorkerTask} task - The worker task to use for reporting progress
* and cancellation.
* @return {Promise<void>}
*/
async extractPages(pageInfos) {
async extractPages(pageInfos, annotationStorage, handler, task) {
const promises = [];
let newIndex = 0;
this.hasSingleFile = pageInfos.length === 1;
const allDocumentData = [];

if (annotationStorage) {
this.#newAnnotationsParams = {
handler,
task,
newAnnotationsByPage: getNewAnnotationsMap(annotationStorage),
imagesPromises: AnnotationFactory.generateImages(
annotationStorage.values(),
this.xrefWrapper,
true
),
};
}

for (const {
document,
includePages,
Expand Down Expand Up @@ -1083,7 +1117,7 @@ class PDFEditor {

// Fix the ID tree.
for (const [id, nodeRef] of idTree || []) {
const newNodeRef = oldRefMapping.get(nodeRef);
const newNodeRef = nodeRef instanceof Ref && oldRefMapping.get(nodeRef);
const newId = dedupIDs.get(id) || id;
if (newNodeRef) {
newIdTree.set(newId, newNodeRef);
Expand Down Expand Up @@ -1137,7 +1171,7 @@ class PDFEditor {
const newDestinations = (documentData.destinations = new Map());
for (const [key, dest] of Object.entries(destinations)) {
const pageRef = dest[0];
const pageData = pagesMap.get(pageRef);
const pageData = pageRef instanceof Ref && pagesMap.get(pageRef);
if (!pageData) {
continue;
}
Expand Down Expand Up @@ -1537,7 +1571,7 @@ class PDFEditor {
}
const { oldRefMapping } = documentData;
for (const coRef of co) {
const newCoRef = oldRefMapping.get(coRef);
const newCoRef = coRef instanceof Ref && oldRefMapping.get(coRef);
if (newCoRef) {
calculationOrder.push(newCoRef);
}
Expand Down Expand Up @@ -1930,16 +1964,44 @@ class PDFEditor {
await this.#collectDependencies(resources, true, xref)
);

let newAnnots = null;

if (annotations) {
const newAnnotations = await this.#collectDependencies(
annotations,
true,
xref
);
this.#fixNamedDestinations(newAnnotations, dedupNamedDestinations);
pageDict.setIfArray("Annots", newAnnotations);
if (Array.isArray(newAnnotations) && newAnnotations.length > 0) {
newAnnots = newAnnotations;
}
}

const newAnnotations =
this.#newAnnotationsParams?.newAnnotationsByPage.get(pageIndex);
if (newAnnotations) {
const { handler, task, imagesPromises } = this.#newAnnotationsParams;
const changes = new RefSetCache();
const newData = await AnnotationFactory.saveNewAnnotations(
page.createAnnotationEvaluator(handler),
this.xrefWrapper,
task,
newAnnotations,
imagesPromises,
changes
);
for (const [ref, { data }] of changes.items()) {
this.xref[ref.num] = data;
}
newAnnots ||= [];
for (const { ref } of newData.annotations) {
newAnnots.push(ref);
}
}

pageDict.setIfArray("Annots", newAnnots);

if (this.useObjectStreams) {
const newLastRef = this.newRefCount;
const pageObjectRefs = [];
Expand Down
6 changes: 6 additions & 0 deletions src/core/evaluator.js
Original file line number Diff line number Diff line change
Expand Up @@ -408,6 +408,9 @@ class PartialEvaluator {
isCompressed: true,
};
} else {
if (typeof PDFJSDev !== "undefined" && PDFJSDev.test("MOZCENTRAL")) {
throw new Error("Only worker-thread fetching supported.");
}
// Get the data on the main-thread instead.
data = await this.handler.sendWithPromise("FetchBinaryData", {
type: "cMapReaderFactory",
Expand Down Expand Up @@ -446,6 +449,9 @@ class PartialEvaluator {
`${this.options.standardFontDataUrl}${filename}`
);
} else {
if (typeof PDFJSDev !== "undefined" && PDFJSDev.test("MOZCENTRAL")) {
throw new Error("Only worker-thread fetching supported.");
}
// Get the data on the main-thread instead.
data = await this.handler.sendWithPromise("FetchBinaryData", {
type: "standardFontDataFactory",
Expand Down
3 changes: 3 additions & 0 deletions src/core/jbig2_ccittFax_wasm.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,9 @@ class JBig2CCITTFaxWasmImage {
if (this.#useWorkerFetch) {
this.#buffer = await fetchBinaryData(`${this.#wasmUrl}${filename}`);
} else {
if (typeof PDFJSDev !== "undefined" && PDFJSDev.test("MOZCENTRAL")) {
throw new Error("Only worker-thread fetching supported.");
}
this.#buffer = await this.#handler.sendWithPromise(
"FetchBinaryData",
{ type: "wasmFactory", filename }
Expand Down
3 changes: 3 additions & 0 deletions src/core/jpx.js
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,9 @@ class JpxImage {
if (this.#useWorkerFetch) {
this.#buffer = await fetchBinaryData(`${this.#wasmUrl}${filename}`);
} else {
if (typeof PDFJSDev !== "undefined" && PDFJSDev.test("MOZCENTRAL")) {
throw new Error("Only worker-thread fetching supported.");
}
this.#buffer = await this.#handler.sendWithPromise(
"FetchBinaryData",
{ type: "wasmFactory", filename }
Expand Down
Loading
Loading