Merge pull request #21576 from Snuffleupagus/RefSetCache-getOrPutComputed

Add a `getOrPutComputed` method in the `RefSetCache` class
This commit is contained in:
Jonas Jenwald 2026-07-15 17:45:47 +02:00 committed by GitHub
commit e39b23904c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
11 changed files with 37 additions and 32 deletions

View File

@ -455,12 +455,7 @@ class PDFEditor {
// Re-entry means a (malformed) cycle back to this stream: allocate its // Re-entry means a (malformed) cycle back to this stream: allocate its
// reference now to break the loop, like the generic path's eager alloc. // reference now to break the loop, like the generic path's eager alloc.
if (resourceStreamPath.has(oldRef)) { if (resourceStreamPath.has(oldRef)) {
let ref = oldRefMapping.get(oldRef); return oldRefMapping.getOrPutComputed(oldRef, () => this.newRef);
if (!ref) {
ref = this.newRef;
oldRefMapping.put(oldRef, ref);
}
return ref;
} }
const key = oldRef.toString(); const key = oldRef.toString();

View File

@ -13,6 +13,8 @@
* limitations under the License. * limitations under the License.
*/ */
import { makeSet } from "../shared/util.js";
const ON_CURVE_POINT = 1 << 0; const ON_CURVE_POINT = 1 << 0;
const X_SHORT_VECTOR = 1 << 1; const X_SHORT_VECTOR = 1 << 1;
const Y_SHORT_VECTOR = 1 << 2; const Y_SHORT_VECTOR = 1 << 2;
@ -756,13 +758,7 @@ function pruneCompositeGlyphCycles(glyfTable, locaEntries, numGlyphs) {
stack.push({ node: next, idx: 0 }); stack.push({ node: next, idx: 0 });
continue; continue;
} }
backEdges.getOrInsertComputed(top.node, makeSet).add(compIdx);
let removeSet = backEdges.get(top.node);
if (!removeSet) {
removeSet = new Set();
backEdges.set(top.node, removeSet);
}
removeSet.add(compIdx);
} }
} }

View File

@ -13,7 +13,7 @@
* limitations under the License. * limitations under the License.
*/ */
import { assert, unreachable, warn } from "../shared/util.js"; import { assert, makeSet, unreachable, warn } from "../shared/util.js";
import { RefSet, RefSetCache } from "./primitives.js"; import { RefSet, RefSetCache } from "./primitives.js";
class BaseLocalCache { class BaseLocalCache {
@ -228,11 +228,7 @@ class GlobalImageCache {
} }
shouldCache(ref, pageIndex) { shouldCache(ref, pageIndex) {
let pageIndexSet = this._refCache.get(ref); const pageIndexSet = this._refCache.getOrPutComputed(ref, makeSet);
if (!pageIndexSet) {
pageIndexSet = new Set();
this._refCache.put(ref, pageIndexSet);
}
pageIndexSet.add(pageIndex); pageIndexSet.add(pageIndex);
if (pageIndexSet.size < GlobalImageCache.NUM_PAGES_THRESHOLD) { if (pageIndexSet.size < GlobalImageCache.NUM_PAGES_THRESHOLD) {

View File

@ -398,6 +398,16 @@ class RefSetCache {
this._map.set(ref.toString(), this.get(aliasRef)); this._map.set(ref.toString(), this.get(aliasRef));
} }
getOrPutComputed(ref, callback) {
const map = this._map,
refStr = ref.toString();
if (!map.has(refStr)) {
map.set(refStr, callback(ref));
}
return map.get(refStr);
}
[Symbol.iterator]() { [Symbol.iterator]() {
return this._map.values(); return this._map.values();
} }

View File

@ -93,12 +93,7 @@ class StructTreeRoot {
return; return;
} }
this.structParentIds ||= new RefSetCache(); this.structParentIds ||= new RefSetCache();
let ids = this.structParentIds.get(pageRef); this.structParentIds.getOrPutComputed(pageRef, makeArr).push([id, type]);
if (!ids) {
ids = [];
this.structParentIds.put(pageRef, ids);
}
ids.push([id, type]);
} }
addAnnotationIdToPage(pageRef, id) { addAnnotationIdToPage(pageRef, id) {
@ -537,11 +532,9 @@ class StructTreeRoot {
return; return;
} }
let cachedParentDict = cache.get(parentRef); const cachedParentDict = cache.getOrPutComputed(parentRef, () =>
if (!cachedParentDict) { parentDict.clone()
cachedParentDict = parentDict.clone(); );
cache.put(parentRef, cachedParentDict);
}
const parentKidsRaw = cachedParentDict.getRaw("K"); const parentKidsRaw = cachedParentDict.getRaw("K");
let cachedParentKids = let cachedParentKids =
parentKidsRaw instanceof Ref ? cache.get(parentKidsRaw) : null; parentKidsRaw instanceof Ref ? cache.get(parentKidsRaw) : null;

View File

@ -36,6 +36,7 @@ import {
makeArr, makeArr,
makeMap, makeMap,
makeObj, makeObj,
makeSet,
normalizeUnicode, normalizeUnicode,
OPS, OPS,
PasswordException, PasswordException,
@ -131,6 +132,7 @@ globalThis.pdfjsLib = {
makeArr, makeArr,
makeMap, makeMap,
makeObj, makeObj,
makeSet,
MathClamp, MathClamp,
noContextMenu, noContextMenu,
normalizeUnicode, normalizeUnicode,
@ -195,6 +197,7 @@ export {
makeArr, makeArr,
makeMap, makeMap,
makeObj, makeObj,
makeSet,
MathClamp, MathClamp,
noContextMenu, noContextMenu,
normalizeUnicode, normalizeUnicode,

View File

@ -1135,6 +1135,7 @@ function _isValidExplicitDest(validRef, validName, dest) {
const makeArr = () => []; const makeArr = () => [];
const makeMap = () => new Map(); const makeMap = () => new Map();
const makeObj = () => Object.create(null); const makeObj = () => Object.create(null);
const makeSet = () => new Set();
// See https://developer.mozilla.org/en-US/docs/Web/API/Blob/bytes#browser_compatibility // See https://developer.mozilla.org/en-US/docs/Web/API/Blob/bytes#browser_compatibility
if ( if (
@ -1197,6 +1198,7 @@ export {
makeArr, makeArr,
makeMap, makeMap,
makeObj, makeObj,
makeSet,
MeshFigureType, MeshFigureType,
normalizeUnicode, normalizeUnicode,
objectSize, objectSize,

View File

@ -27,6 +27,7 @@ import {
makeArr, makeArr,
makeMap, makeMap,
makeObj, makeObj,
makeSet,
normalizeUnicode, normalizeUnicode,
OPS, OPS,
PasswordException, PasswordException,
@ -115,6 +116,7 @@ const expectedAPI = Object.freeze({
makeArr, makeArr,
makeMap, makeMap,
makeObj, makeObj,
makeSet,
MathClamp, MathClamp,
noContextMenu, noContextMenu,
normalizeUnicode, normalizeUnicode,

View File

@ -568,6 +568,12 @@ describe("primitives", function () {
cache.put(ref2, obj2); cache.put(ref2, obj2);
expect([...cache.keys()]).toEqual([ref1, ref2]); expect([...cache.keys()]).toEqual([ref1, ref2]);
}); });
it("should handle getOrPutComputed correctly", function () {
expect(cache.getOrPutComputed(ref1, () => obj1)).toEqual(obj1);
// Trying to set it again should be ignored.
expect(cache.getOrPutComputed(ref1, () => obj2)).toEqual(obj1);
});
}); });
describe("isName", function () { describe("isName", function () {

View File

@ -13,7 +13,7 @@
* limitations under the License. * limitations under the License.
*/ */
const { OPS } = globalThis.pdfjsLib || (await import("pdfjs-lib")); const { makeSet, OPS } = globalThis.pdfjsLib || (await import("pdfjs-lib"));
const opMap = Object.create(null); const opMap = Object.create(null);
for (const key in OPS) { for (const key in OPS) {
@ -460,7 +460,7 @@ class Stepper {
for (const [dependentIdx, { dependencies: ownDependencies }] of metadata) { for (const [dependentIdx, { dependencies: ownDependencies }] of metadata) {
for (const dependencyIdx of ownDependencies) { for (const dependencyIdx of ownDependencies) {
dependents dependents
.getOrInsertComputed(dependencyIdx, () => new Set()) .getOrInsertComputed(dependencyIdx, makeSet)
.add(dependentIdx); .add(dependentIdx);
} }
} }

View File

@ -47,6 +47,7 @@ const {
makeArr, makeArr,
makeMap, makeMap,
makeObj, makeObj,
makeSet,
MathClamp, MathClamp,
noContextMenu, noContextMenu,
normalizeUnicode, normalizeUnicode,
@ -111,6 +112,7 @@ export {
makeArr, makeArr,
makeMap, makeMap,
makeObj, makeObj,
makeSet,
MathClamp, MathClamp,
noContextMenu, noContextMenu,
normalizeUnicode, normalizeUnicode,