mirror of
https://github.com/mozilla/pdf.js.git
synced 2026-08-03 12:57:20 +02:00
Merge pull request #20726 from Snuffleupagus/getOrInsertComputed-fewer-functions
Reduce allocations and function creation when using `getOrInsert` and `getOrInsertComputed`
This commit is contained in:
commit
4ecbd0cbe2
@ -18,6 +18,7 @@ import {
|
|||||||
assert,
|
assert,
|
||||||
BaseException,
|
BaseException,
|
||||||
hexNumbers,
|
hexNumbers,
|
||||||
|
makeArr,
|
||||||
objectSize,
|
objectSize,
|
||||||
stringToPDFString,
|
stringToPDFString,
|
||||||
Util,
|
Util,
|
||||||
@ -669,7 +670,9 @@ function getNewAnnotationsMap(annotationStorage) {
|
|||||||
if (!key.startsWith(AnnotationEditorPrefix)) {
|
if (!key.startsWith(AnnotationEditorPrefix)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
newAnnotationsByPage.getOrInsert(value.pageIndex, []).push(value);
|
newAnnotationsByPage
|
||||||
|
.getOrInsertComputed(value.pageIndex, makeArr)
|
||||||
|
.push(value);
|
||||||
}
|
}
|
||||||
return newAnnotationsByPage.size > 0 ? newAnnotationsByPage : null;
|
return newAnnotationsByPage.size > 0 ? newAnnotationsByPage : null;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -20,6 +20,7 @@ import {
|
|||||||
info,
|
info,
|
||||||
InvalidPDFException,
|
InvalidPDFException,
|
||||||
isArrayEqual,
|
isArrayEqual,
|
||||||
|
makeArr,
|
||||||
objectSize,
|
objectSize,
|
||||||
PageActionEventType,
|
PageActionEventType,
|
||||||
RenderingIntentFlag,
|
RenderingIntentFlag,
|
||||||
@ -1894,7 +1895,7 @@ class PDFDocument {
|
|||||||
orphanFields.put(fieldRef, parentRef);
|
orphanFields.put(fieldRef, parentRef);
|
||||||
}
|
}
|
||||||
|
|
||||||
promises.getOrInsert(name, []).push(
|
promises.getOrInsertComputed(name, makeArr).push(
|
||||||
AnnotationFactory.create(
|
AnnotationFactory.create(
|
||||||
xref,
|
xref,
|
||||||
fieldRef,
|
fieldRef,
|
||||||
|
|||||||
@ -15,6 +15,7 @@
|
|||||||
|
|
||||||
import {
|
import {
|
||||||
AnnotationPrefix,
|
AnnotationPrefix,
|
||||||
|
makeArr,
|
||||||
stringToPDFString,
|
stringToPDFString,
|
||||||
stringToUTF8String,
|
stringToUTF8String,
|
||||||
warn,
|
warn,
|
||||||
@ -450,7 +451,7 @@ class StructTreeRoot {
|
|||||||
for (const element of elements) {
|
for (const element of elements) {
|
||||||
if (element.structTreeParentId) {
|
if (element.structTreeParentId) {
|
||||||
const id = parseInt(element.structTreeParentId.split("_mc")[1], 10);
|
const id = parseInt(element.structTreeParentId.split("_mc")[1], 10);
|
||||||
idToElements.getOrInsert(id, []).push(element);
|
idToElements.getOrInsertComputed(id, makeArr).push(element);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -24,10 +24,10 @@ import {
|
|||||||
$resolvePrototypes,
|
$resolvePrototypes,
|
||||||
$root,
|
$root,
|
||||||
} from "./symbol_utils.js";
|
} from "./symbol_utils.js";
|
||||||
|
import { makeArr, warn } from "../../shared/util.js";
|
||||||
import { NamespaceSetUp } from "./setup.js";
|
import { NamespaceSetUp } from "./setup.js";
|
||||||
import { Template } from "./template.js";
|
import { Template } from "./template.js";
|
||||||
import { UnknownNamespace } from "./unknown.js";
|
import { UnknownNamespace } from "./unknown.js";
|
||||||
import { warn } from "../../shared/util.js";
|
|
||||||
import { XFAObject } from "./xfa_object.js";
|
import { XFAObject } from "./xfa_object.js";
|
||||||
|
|
||||||
class Root extends XFAObject {
|
class Root extends XFAObject {
|
||||||
@ -166,12 +166,9 @@ class Builder {
|
|||||||
_addNamespacePrefix(prefixes) {
|
_addNamespacePrefix(prefixes) {
|
||||||
for (const { prefix, value } of prefixes) {
|
for (const { prefix, value } of prefixes) {
|
||||||
const namespace = this._searchNamespace(value);
|
const namespace = this._searchNamespace(value);
|
||||||
let prefixStack = this._namespacePrefixes.get(prefix);
|
this._namespacePrefixes
|
||||||
if (!prefixStack) {
|
.getOrInsertComputed(prefix, makeArr)
|
||||||
prefixStack = [];
|
.push(namespace);
|
||||||
this._namespacePrefixes.set(prefix, prefixStack);
|
|
||||||
}
|
|
||||||
prefixStack.push(namespace);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -13,9 +13,9 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import { makeObj, warn } from "../../shared/util.js";
|
||||||
import { $globalData } from "./symbol_utils.js";
|
import { $globalData } from "./symbol_utils.js";
|
||||||
import { stripQuotes } from "./utils.js";
|
import { stripQuotes } from "./utils.js";
|
||||||
import { warn } from "../../shared/util.js";
|
|
||||||
|
|
||||||
class FontFinder {
|
class FontFinder {
|
||||||
constructor(pdfFonts) {
|
constructor(pdfFonts) {
|
||||||
@ -48,14 +48,9 @@ class FontFinder {
|
|||||||
addPdfFont(pdfFont) {
|
addPdfFont(pdfFont) {
|
||||||
const cssFontInfo = pdfFont.cssFontInfo;
|
const cssFontInfo = pdfFont.cssFontInfo;
|
||||||
const name = cssFontInfo.fontFamily;
|
const name = cssFontInfo.fontFamily;
|
||||||
let font = this.fonts.get(name);
|
const font = this.fonts.getOrInsertComputed(name, makeObj);
|
||||||
if (!font) {
|
this.defaultFont ??= font;
|
||||||
font = Object.create(null);
|
|
||||||
this.fonts.set(name, font);
|
|
||||||
if (!this.defaultFont) {
|
|
||||||
this.defaultFont = font;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
let property = "";
|
let property = "";
|
||||||
const fontWeight = parseFloat(cssFontInfo.fontWeight);
|
const fontWeight = parseFloat(cssFontInfo.fontWeight);
|
||||||
if (parseFloat(cssFontInfo.italicAngle) !== 0) {
|
if (parseFloat(cssFontInfo.italicAngle) !== 0) {
|
||||||
|
|||||||
@ -19,7 +19,7 @@ import {
|
|||||||
$getChildrenByName,
|
$getChildrenByName,
|
||||||
$getParent,
|
$getParent,
|
||||||
} from "./symbol_utils.js";
|
} from "./symbol_utils.js";
|
||||||
import { warn } from "../../shared/util.js";
|
import { makeMap, warn } from "../../shared/util.js";
|
||||||
|
|
||||||
const namePattern = /^[^.[]+/;
|
const namePattern = /^[^.[]+/;
|
||||||
const indexPattern = /^[^\]]+/;
|
const indexPattern = /^[^\]]+/;
|
||||||
@ -193,11 +193,7 @@ function searchNode(
|
|||||||
let children, cached;
|
let children, cached;
|
||||||
|
|
||||||
if (useCache) {
|
if (useCache) {
|
||||||
cached = somCache.get(node);
|
cached = somCache.getOrInsertComputed(node, makeMap);
|
||||||
if (!cached) {
|
|
||||||
cached = new Map();
|
|
||||||
somCache.set(node, cached);
|
|
||||||
}
|
|
||||||
children = cached.get(cacheName);
|
children = cached.get(cacheName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -36,6 +36,7 @@ import {
|
|||||||
AnnotationType,
|
AnnotationType,
|
||||||
FeatureTest,
|
FeatureTest,
|
||||||
LINE_FACTOR,
|
LINE_FACTOR,
|
||||||
|
makeArr,
|
||||||
shadow,
|
shadow,
|
||||||
unreachable,
|
unreachable,
|
||||||
Util,
|
Util,
|
||||||
@ -3877,7 +3878,9 @@ class AnnotationLayer {
|
|||||||
this.#elements.push(element);
|
this.#elements.push(element);
|
||||||
|
|
||||||
if (data.popupRef) {
|
if (data.popupRef) {
|
||||||
popupToElements.getOrInsert(data.popupRef, []).push(element);
|
popupToElements
|
||||||
|
.getOrInsertComputed(data.popupRef, makeArr)
|
||||||
|
.push(element);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -13,7 +13,7 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { shadow, unreachable } from "../shared/util.js";
|
import { makeMap, shadow, unreachable } from "../shared/util.js";
|
||||||
import { AnnotationEditor } from "./editor/editor.js";
|
import { AnnotationEditor } from "./editor/editor.js";
|
||||||
import { MurmurHash3_64 } from "../shared/murmurhash3.js";
|
import { MurmurHash3_64 } from "../shared/murmurhash3.js";
|
||||||
|
|
||||||
@ -260,7 +260,7 @@ class AnnotationStorage {
|
|||||||
if (key === "type") {
|
if (key === "type") {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
const counters = map.getOrInsertComputed(key, () => new Map());
|
const counters = map.getOrInsertComputed(key, makeMap);
|
||||||
counters.set(val, (counters.get(val) ?? 0) + 1);
|
counters.set(val, (counters.get(val) ?? 0) + 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -25,6 +25,7 @@ import {
|
|||||||
getVerbosityLevel,
|
getVerbosityLevel,
|
||||||
info,
|
info,
|
||||||
isNodeJS,
|
isNodeJS,
|
||||||
|
makeObj,
|
||||||
MathClamp,
|
MathClamp,
|
||||||
RenderingIntentFlag,
|
RenderingIntentFlag,
|
||||||
setVerbosityLevel,
|
setVerbosityLevel,
|
||||||
@ -1502,8 +1503,9 @@ class PDFPageProxy {
|
|||||||
optionalContentConfigPromise ||=
|
optionalContentConfigPromise ||=
|
||||||
this._transport.getOptionalContentConfig(renderingIntent);
|
this._transport.getOptionalContentConfig(renderingIntent);
|
||||||
|
|
||||||
const intentState = this._intentStates.getOrInsertComputed(cacheKey, () =>
|
const intentState = this._intentStates.getOrInsertComputed(
|
||||||
Object.create(null)
|
cacheKey,
|
||||||
|
makeObj
|
||||||
);
|
);
|
||||||
// Ensure that a pending `streamReader` cancel timeout is always aborted.
|
// Ensure that a pending `streamReader` cancel timeout is always aborted.
|
||||||
if (intentState.streamReaderCancelTimeout) {
|
if (intentState.streamReaderCancelTimeout) {
|
||||||
@ -1675,7 +1677,7 @@ class PDFPageProxy {
|
|||||||
);
|
);
|
||||||
const intentState = this._intentStates.getOrInsertComputed(
|
const intentState = this._intentStates.getOrInsertComputed(
|
||||||
intentArgs.cacheKey,
|
intentArgs.cacheKey,
|
||||||
() => Object.create(null)
|
makeObj
|
||||||
);
|
);
|
||||||
let opListTask;
|
let opListTask;
|
||||||
|
|
||||||
|
|||||||
@ -22,6 +22,7 @@ import {
|
|||||||
FONT_IDENTITY_MATRIX,
|
FONT_IDENTITY_MATRIX,
|
||||||
ImageKind,
|
ImageKind,
|
||||||
info,
|
info,
|
||||||
|
makeMap,
|
||||||
OPS,
|
OPS,
|
||||||
shadow,
|
shadow,
|
||||||
TextRenderingMode,
|
TextRenderingMode,
|
||||||
@ -989,10 +990,7 @@ class CanvasGraphics {
|
|||||||
: [currentTransform.slice(0, 4), fillColor]
|
: [currentTransform.slice(0, 4), fillColor]
|
||||||
);
|
);
|
||||||
|
|
||||||
cache = this._cachedBitmapsMap.getOrInsertComputed(
|
cache = this._cachedBitmapsMap.getOrInsertComputed(mainKey, makeMap);
|
||||||
mainKey,
|
|
||||||
() => new Map()
|
|
||||||
);
|
|
||||||
const cachedImage = cache.get(cacheKey);
|
const cachedImage = cache.get(cacheKey);
|
||||||
if (cachedImage && !isPatternFill) {
|
if (cachedImage && !isPatternFill) {
|
||||||
const offsetX = Math.round(
|
const offsetX = Math.round(
|
||||||
|
|||||||
@ -15,6 +15,11 @@
|
|||||||
|
|
||||||
const INITIAL_DATA = Symbol("INITIAL_DATA");
|
const INITIAL_DATA = Symbol("INITIAL_DATA");
|
||||||
|
|
||||||
|
const dataObj = () => ({
|
||||||
|
...Promise.withResolvers(),
|
||||||
|
data: INITIAL_DATA,
|
||||||
|
});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A PDF document and page is built of many objects. E.g. there are objects for
|
* A PDF document and page is built of many objects. E.g. there are objects for
|
||||||
* fonts, images, rendering code, etc. These objects may get processed inside of
|
* fonts, images, rendering code, etc. These objects may get processed inside of
|
||||||
@ -30,10 +35,7 @@ class PDFObjects {
|
|||||||
* @returns {Object}
|
* @returns {Object}
|
||||||
*/
|
*/
|
||||||
#ensureObj(objId) {
|
#ensureObj(objId) {
|
||||||
return this.#objs.getOrInsertComputed(objId, () => ({
|
return this.#objs.getOrInsertComputed(objId, dataObj);
|
||||||
...Promise.withResolvers(),
|
|
||||||
data: INITIAL_DATA,
|
|
||||||
}));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -33,6 +33,9 @@ import {
|
|||||||
getUuid,
|
getUuid,
|
||||||
ImageKind,
|
ImageKind,
|
||||||
InvalidPDFException,
|
InvalidPDFException,
|
||||||
|
makeArr,
|
||||||
|
makeMap,
|
||||||
|
makeObj,
|
||||||
MathClamp,
|
MathClamp,
|
||||||
normalizeUnicode,
|
normalizeUnicode,
|
||||||
OPS,
|
OPS,
|
||||||
@ -123,6 +126,9 @@ globalThis.pdfjsLib = {
|
|||||||
isDataScheme,
|
isDataScheme,
|
||||||
isPdfFile,
|
isPdfFile,
|
||||||
isValidExplicitDest,
|
isValidExplicitDest,
|
||||||
|
makeArr,
|
||||||
|
makeMap,
|
||||||
|
makeObj,
|
||||||
MathClamp,
|
MathClamp,
|
||||||
noContextMenu,
|
noContextMenu,
|
||||||
normalizeUnicode,
|
normalizeUnicode,
|
||||||
@ -182,6 +188,9 @@ export {
|
|||||||
isDataScheme,
|
isDataScheme,
|
||||||
isPdfFile,
|
isPdfFile,
|
||||||
isValidExplicitDest,
|
isValidExplicitDest,
|
||||||
|
makeArr,
|
||||||
|
makeMap,
|
||||||
|
makeObj,
|
||||||
MathClamp,
|
MathClamp,
|
||||||
noContextMenu,
|
noContextMenu,
|
||||||
normalizeUnicode,
|
normalizeUnicode,
|
||||||
|
|||||||
@ -1234,6 +1234,12 @@ function _isValidExplicitDest(validRef, validName, dest) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Helpers for simple `Map.prototype.getOrInsertComputed()` invocations,
|
||||||
|
// to avoid duplicate function creation.
|
||||||
|
const makeArr = () => [];
|
||||||
|
const makeMap = () => new Map();
|
||||||
|
const makeObj = () => Object.create(null);
|
||||||
|
|
||||||
// TODO: Replace all occurrences of this function with `Math.clamp` once
|
// TODO: Replace all occurrences of this function with `Math.clamp` once
|
||||||
// https://github.com/tc39/proposal-math-clamp/ is generally available.
|
// https://github.com/tc39/proposal-math-clamp/ is generally available.
|
||||||
function MathClamp(v, min, max) {
|
function MathClamp(v, min, max) {
|
||||||
@ -1331,6 +1337,9 @@ export {
|
|||||||
isNodeJS,
|
isNodeJS,
|
||||||
LINE_DESCENT_FACTOR,
|
LINE_DESCENT_FACTOR,
|
||||||
LINE_FACTOR,
|
LINE_FACTOR,
|
||||||
|
makeArr,
|
||||||
|
makeMap,
|
||||||
|
makeObj,
|
||||||
MathClamp,
|
MathClamp,
|
||||||
MeshFigureType,
|
MeshFigureType,
|
||||||
normalizeUnicode,
|
normalizeUnicode,
|
||||||
|
|||||||
@ -24,6 +24,9 @@ import {
|
|||||||
getUuid,
|
getUuid,
|
||||||
ImageKind,
|
ImageKind,
|
||||||
InvalidPDFException,
|
InvalidPDFException,
|
||||||
|
makeArr,
|
||||||
|
makeMap,
|
||||||
|
makeObj,
|
||||||
MathClamp,
|
MathClamp,
|
||||||
normalizeUnicode,
|
normalizeUnicode,
|
||||||
OPS,
|
OPS,
|
||||||
@ -107,6 +110,9 @@ const expectedAPI = Object.freeze({
|
|||||||
isDataScheme,
|
isDataScheme,
|
||||||
isPdfFile,
|
isPdfFile,
|
||||||
isValidExplicitDest,
|
isValidExplicitDest,
|
||||||
|
makeArr,
|
||||||
|
makeMap,
|
||||||
|
makeObj,
|
||||||
MathClamp,
|
MathClamp,
|
||||||
noContextMenu,
|
noContextMenu,
|
||||||
normalizeUnicode,
|
normalizeUnicode,
|
||||||
|
|||||||
@ -33,6 +33,7 @@ import {
|
|||||||
AnnotationEditorType,
|
AnnotationEditorType,
|
||||||
AnnotationEditorUIManager,
|
AnnotationEditorUIManager,
|
||||||
AnnotationMode,
|
AnnotationMode,
|
||||||
|
makeArr,
|
||||||
MathClamp,
|
MathClamp,
|
||||||
PermissionFlag,
|
PermissionFlag,
|
||||||
PixelsPerInch,
|
PixelsPerInch,
|
||||||
@ -2281,7 +2282,7 @@ class PDFViewer {
|
|||||||
if (percent === 0 || widthPercent < 100) {
|
if (percent === 0 || widthPercent < 100) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
pageLayout.getOrInsert(y, []).push(id);
|
pageLayout.getOrInsertComputed(y, makeArr).push(id);
|
||||||
}
|
}
|
||||||
// Find the row of the current page.
|
// Find the row of the current page.
|
||||||
for (const yArray of pageLayout.values()) {
|
for (const yArray of pageLayout.values()) {
|
||||||
|
|||||||
@ -44,6 +44,9 @@ const {
|
|||||||
isDataScheme,
|
isDataScheme,
|
||||||
isPdfFile,
|
isPdfFile,
|
||||||
isValidExplicitDest,
|
isValidExplicitDest,
|
||||||
|
makeArr,
|
||||||
|
makeMap,
|
||||||
|
makeObj,
|
||||||
MathClamp,
|
MathClamp,
|
||||||
noContextMenu,
|
noContextMenu,
|
||||||
normalizeUnicode,
|
normalizeUnicode,
|
||||||
@ -103,6 +106,9 @@ export {
|
|||||||
isDataScheme,
|
isDataScheme,
|
||||||
isPdfFile,
|
isPdfFile,
|
||||||
isValidExplicitDest,
|
isValidExplicitDest,
|
||||||
|
makeArr,
|
||||||
|
makeMap,
|
||||||
|
makeObj,
|
||||||
MathClamp,
|
MathClamp,
|
||||||
noContextMenu,
|
noContextMenu,
|
||||||
normalizeUnicode,
|
normalizeUnicode,
|
||||||
|
|||||||
@ -15,7 +15,7 @@
|
|||||||
|
|
||||||
/** @typedef {import("../src/display/api").PDFPageProxy} PDFPageProxy */
|
/** @typedef {import("../src/display/api").PDFPageProxy} PDFPageProxy */
|
||||||
|
|
||||||
import { FeatureTest, shadow } from "pdfjs-lib";
|
import { FeatureTest, makeMap, shadow } from "pdfjs-lib";
|
||||||
import { removeNullCharacters } from "./ui_utils.js";
|
import { removeNullCharacters } from "./ui_utils.js";
|
||||||
|
|
||||||
const PDF_ROLE_TO_HTML_ROLE = {
|
const PDF_ROLE_TO_HTML_ROLE = {
|
||||||
@ -251,12 +251,9 @@ class StructTreeLayerBuilder {
|
|||||||
const label = removeNullCharacters(alt);
|
const label = removeNullCharacters(alt);
|
||||||
for (const child of structElement.children) {
|
for (const child of structElement.children) {
|
||||||
if (child.type === "annotation") {
|
if (child.type === "annotation") {
|
||||||
let attrs = this.#elementAttributes.get(child.id);
|
this.#elementAttributes
|
||||||
if (!attrs) {
|
.getOrInsertComputed(child.id, makeMap)
|
||||||
attrs = new Map();
|
.set("aria-label", label);
|
||||||
this.#elementAttributes.set(child.id, attrs);
|
|
||||||
}
|
|
||||||
attrs.set("aria-label", label);
|
|
||||||
added = true;
|
added = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user