@embedpdf/engines 1.0.26 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{engine-BH98VpS7.js → engine-Cm-940a0.js} +135 -12
- package/dist/engine-Cm-940a0.js.map +1 -0
- package/dist/engine-DVTbcCVE.cjs +2 -0
- package/dist/engine-DVTbcCVE.cjs.map +1 -0
- package/dist/index-BZKyCIIQ.cjs +2 -0
- package/dist/{index-CpWF5iWs.cjs.map → index-BZKyCIIQ.cjs.map} +1 -1
- package/dist/{index-DF0oRaJr.js → index-D9GgzViI.js} +6 -3
- package/dist/{index-DF0oRaJr.js.map → index-D9GgzViI.js.map} +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +8 -4
- package/dist/index.js.map +1 -1
- package/dist/lib/pdfium/cache.d.ts +43 -5
- package/dist/lib/pdfium/engine.d.ts +11 -1
- package/dist/lib/pdfium/index.cjs +1 -1
- package/dist/lib/pdfium/index.js +2 -2
- package/dist/lib/pdfium/web/direct-engine.cjs +1 -1
- package/dist/lib/pdfium/web/direct-engine.js +1 -1
- package/dist/lib/pdfium/web/worker-engine.cjs +1 -1
- package/dist/lib/pdfium/web/worker-engine.js +1 -1
- package/dist/lib/webworker/engine.cjs +1 -1
- package/dist/lib/webworker/engine.cjs.map +1 -1
- package/dist/lib/webworker/engine.d.ts +6 -0
- package/dist/lib/webworker/engine.js +14 -1
- package/dist/lib/webworker/engine.js.map +1 -1
- package/dist/preact/adapter.d.ts +3 -1
- package/dist/preact/index.cjs +1 -1
- package/dist/preact/index.cjs.map +1 -1
- package/dist/preact/index.js +47 -7
- package/dist/preact/index.js.map +1 -1
- package/dist/react/adapter.d.ts +2 -1
- package/dist/react/index.cjs +1 -1
- package/dist/react/index.cjs.map +1 -1
- package/dist/react/index.js +46 -7
- package/dist/react/index.js.map +1 -1
- package/dist/shared-preact/components/index.d.ts +1 -0
- package/dist/shared-preact/components/pdf-engine-provider.d.ts +16 -0
- package/dist/shared-preact/context/index.d.ts +1 -0
- package/dist/shared-preact/context/pdf-engine-context.d.ts +7 -0
- package/dist/shared-preact/hooks/index.d.ts +1 -0
- package/dist/shared-preact/hooks/use-engine-context.d.ts +12 -0
- package/dist/shared-preact/index.d.ts +1 -0
- package/dist/shared-react/components/index.d.ts +1 -0
- package/dist/shared-react/components/pdf-engine-provider.d.ts +16 -0
- package/dist/shared-react/context/index.d.ts +1 -0
- package/dist/shared-react/context/pdf-engine-context.d.ts +7 -0
- package/dist/shared-react/hooks/index.d.ts +1 -0
- package/dist/shared-react/hooks/use-engine-context.d.ts +12 -0
- package/dist/shared-react/index.d.ts +1 -0
- package/dist/vue/components/index.d.ts +1 -0
- package/dist/vue/components/pdf-engine-provider.vue.d.ts +18 -0
- package/dist/vue/composables/index.d.ts +2 -0
- package/dist/vue/composables/use-engine-context.d.ts +12 -0
- package/dist/vue/context/pdf-engine-context.d.ts +8 -0
- package/dist/vue/index.cjs +1 -1
- package/dist/vue/index.cjs.map +1 -1
- package/dist/vue/index.d.ts +2 -1
- package/dist/vue/index.js +57 -7
- package/dist/vue/index.js.map +1 -1
- package/package.json +3 -3
- package/dist/engine-BH98VpS7.js.map +0 -1
- package/dist/engine-CudZwyui.cjs +0 -2
- package/dist/engine-CudZwyui.cjs.map +0 -1
- package/dist/index-CpWF5iWs.cjs +0 -2
- package/dist/vue/hooks/index.d.ts +0 -1
- /package/dist/vue/{hooks → composables}/use-pdfium-engine.d.ts +0 -0
|
@@ -53,16 +53,22 @@ function isValidCustomKey(key) {
|
|
|
53
53
|
}
|
|
54
54
|
return true;
|
|
55
55
|
}
|
|
56
|
+
const DEFAULT_CONFIG = {
|
|
57
|
+
pageTtl: 5e3,
|
|
58
|
+
// 5 seconds
|
|
59
|
+
maxPagesPerDocument: 10
|
|
60
|
+
};
|
|
56
61
|
class PdfCache {
|
|
57
|
-
constructor(pdfium) {
|
|
62
|
+
constructor(pdfium, config = {}) {
|
|
58
63
|
this.pdfium = pdfium;
|
|
59
64
|
this.docs = /* @__PURE__ */ new Map();
|
|
65
|
+
this.config = { ...DEFAULT_CONFIG, ...config };
|
|
60
66
|
}
|
|
61
67
|
/** Open (or re-use) a document */
|
|
62
68
|
setDocument(id, filePtr, docPtr) {
|
|
63
69
|
let ctx = this.docs.get(id);
|
|
64
70
|
if (!ctx) {
|
|
65
|
-
ctx = new DocumentContext(filePtr, docPtr, this.pdfium);
|
|
71
|
+
ctx = new DocumentContext(filePtr, docPtr, this.pdfium, this.config);
|
|
66
72
|
this.docs.set(id, ctx);
|
|
67
73
|
}
|
|
68
74
|
}
|
|
@@ -78,12 +84,41 @@ class PdfCache {
|
|
|
78
84
|
this.docs.delete(docId);
|
|
79
85
|
return true;
|
|
80
86
|
}
|
|
87
|
+
/** Close all documents */
|
|
88
|
+
closeAllDocuments() {
|
|
89
|
+
for (const ctx of this.docs.values()) {
|
|
90
|
+
ctx.dispose();
|
|
91
|
+
}
|
|
92
|
+
this.docs.clear();
|
|
93
|
+
}
|
|
94
|
+
/** Update cache configuration for all existing documents */
|
|
95
|
+
updateConfig(newConfig) {
|
|
96
|
+
Object.assign(this.config, newConfig);
|
|
97
|
+
for (const ctx of this.docs.values()) {
|
|
98
|
+
ctx.updateConfig(this.config);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
/** Get current cache statistics */
|
|
102
|
+
getCacheStats() {
|
|
103
|
+
const pagesByDocument = {};
|
|
104
|
+
let totalPages = 0;
|
|
105
|
+
for (const [docId, ctx] of this.docs.entries()) {
|
|
106
|
+
const pageCount = ctx.getCacheSize();
|
|
107
|
+
pagesByDocument[docId] = pageCount;
|
|
108
|
+
totalPages += pageCount;
|
|
109
|
+
}
|
|
110
|
+
return {
|
|
111
|
+
documents: this.docs.size,
|
|
112
|
+
totalPages,
|
|
113
|
+
pagesByDocument
|
|
114
|
+
};
|
|
115
|
+
}
|
|
81
116
|
}
|
|
82
117
|
class DocumentContext {
|
|
83
|
-
constructor(filePtr, docPtr, pdfium) {
|
|
118
|
+
constructor(filePtr, docPtr, pdfium, config) {
|
|
84
119
|
this.filePtr = filePtr;
|
|
85
120
|
this.docPtr = docPtr;
|
|
86
|
-
this.pageCache = new PageCache(pdfium, docPtr);
|
|
121
|
+
this.pageCache = new PageCache(pdfium, docPtr, config);
|
|
87
122
|
}
|
|
88
123
|
/** Main accessor for pages */
|
|
89
124
|
acquirePage(pageIdx) {
|
|
@@ -93,6 +128,14 @@ class DocumentContext {
|
|
|
93
128
|
borrowPage(pageIdx, fn) {
|
|
94
129
|
return this.pageCache.borrowPage(pageIdx, fn);
|
|
95
130
|
}
|
|
131
|
+
/** Update cache configuration */
|
|
132
|
+
updateConfig(config) {
|
|
133
|
+
this.pageCache.updateConfig(config);
|
|
134
|
+
}
|
|
135
|
+
/** Get number of pages currently in cache */
|
|
136
|
+
getCacheSize() {
|
|
137
|
+
return this.pageCache.size();
|
|
138
|
+
}
|
|
96
139
|
/** Tear down all pages + this document */
|
|
97
140
|
dispose() {
|
|
98
141
|
this.pageCache.forceReleaseAll();
|
|
@@ -101,25 +144,30 @@ class DocumentContext {
|
|
|
101
144
|
}
|
|
102
145
|
}
|
|
103
146
|
class PageCache {
|
|
104
|
-
constructor(pdf, docPtr) {
|
|
147
|
+
constructor(pdf, docPtr, config) {
|
|
105
148
|
this.pdf = pdf;
|
|
106
149
|
this.docPtr = docPtr;
|
|
107
150
|
this.cache = /* @__PURE__ */ new Map();
|
|
151
|
+
this.accessOrder = [];
|
|
152
|
+
this.config = config;
|
|
108
153
|
}
|
|
109
154
|
acquire(pageIdx) {
|
|
110
155
|
let ctx = this.cache.get(pageIdx);
|
|
111
156
|
if (!ctx) {
|
|
157
|
+
this.evictIfNeeded();
|
|
112
158
|
const pagePtr = this.pdf.FPDF_LoadPage(this.docPtr, pageIdx);
|
|
113
|
-
ctx = new PageContext(this.pdf, this.docPtr, pageIdx, pagePtr, () => {
|
|
159
|
+
ctx = new PageContext(this.pdf, this.docPtr, pageIdx, pagePtr, this.config.pageTtl, () => {
|
|
114
160
|
this.cache.delete(pageIdx);
|
|
161
|
+
this.removeFromAccessOrder(pageIdx);
|
|
115
162
|
});
|
|
116
163
|
this.cache.set(pageIdx, ctx);
|
|
117
164
|
}
|
|
165
|
+
this.updateAccessOrder(pageIdx);
|
|
118
166
|
ctx.clearExpiryTimer();
|
|
119
167
|
ctx.bumpRefCount();
|
|
120
168
|
return ctx;
|
|
121
169
|
}
|
|
122
|
-
/** Helper: run a function
|
|
170
|
+
/** Helper: run a function "scoped" to a page.
|
|
123
171
|
* – if the page was already cached → .release() (keeps TTL logic)
|
|
124
172
|
* – if the page was loaded just now → .disposeImmediate() (free right away)
|
|
125
173
|
*/
|
|
@@ -137,11 +185,55 @@ class PageCache {
|
|
|
137
185
|
ctx.disposeImmediate();
|
|
138
186
|
}
|
|
139
187
|
this.cache.clear();
|
|
188
|
+
this.accessOrder.length = 0;
|
|
189
|
+
}
|
|
190
|
+
/** Update cache configuration */
|
|
191
|
+
updateConfig(config) {
|
|
192
|
+
this.config = config;
|
|
193
|
+
for (const ctx of this.cache.values()) {
|
|
194
|
+
ctx.updateTtl(config.pageTtl);
|
|
195
|
+
}
|
|
196
|
+
this.evictIfNeeded();
|
|
197
|
+
}
|
|
198
|
+
/** Get current cache size */
|
|
199
|
+
size() {
|
|
200
|
+
return this.cache.size;
|
|
201
|
+
}
|
|
202
|
+
/** Evict least recently used pages if cache exceeds max size */
|
|
203
|
+
evictIfNeeded() {
|
|
204
|
+
while (this.cache.size >= this.config.maxPagesPerDocument) {
|
|
205
|
+
const lruPageIdx = this.accessOrder[0];
|
|
206
|
+
if (lruPageIdx !== void 0) {
|
|
207
|
+
const ctx = this.cache.get(lruPageIdx);
|
|
208
|
+
if (ctx) {
|
|
209
|
+
if (ctx.getRefCount() === 0) {
|
|
210
|
+
ctx.disposeImmediate();
|
|
211
|
+
} else {
|
|
212
|
+
break;
|
|
213
|
+
}
|
|
214
|
+
} else {
|
|
215
|
+
this.removeFromAccessOrder(lruPageIdx);
|
|
216
|
+
}
|
|
217
|
+
} else {
|
|
218
|
+
break;
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
/** Update the access order for LRU tracking */
|
|
223
|
+
updateAccessOrder(pageIdx) {
|
|
224
|
+
this.removeFromAccessOrder(pageIdx);
|
|
225
|
+
this.accessOrder.push(pageIdx);
|
|
226
|
+
}
|
|
227
|
+
/** Remove a page from the access order array */
|
|
228
|
+
removeFromAccessOrder(pageIdx) {
|
|
229
|
+
const index = this.accessOrder.indexOf(pageIdx);
|
|
230
|
+
if (index > -1) {
|
|
231
|
+
this.accessOrder.splice(index, 1);
|
|
232
|
+
}
|
|
140
233
|
}
|
|
141
234
|
}
|
|
142
|
-
const PAGE_TTL = 5e3;
|
|
143
235
|
class PageContext {
|
|
144
|
-
constructor(pdf, docPtr, pageIdx, pagePtr, onFinalDispose) {
|
|
236
|
+
constructor(pdf, docPtr, pageIdx, pagePtr, ttl, onFinalDispose) {
|
|
145
237
|
this.pdf = pdf;
|
|
146
238
|
this.docPtr = docPtr;
|
|
147
239
|
this.pageIdx = pageIdx;
|
|
@@ -149,12 +241,17 @@ class PageContext {
|
|
|
149
241
|
this.onFinalDispose = onFinalDispose;
|
|
150
242
|
this.refCount = 0;
|
|
151
243
|
this.disposed = false;
|
|
244
|
+
this.ttl = ttl;
|
|
152
245
|
}
|
|
153
246
|
/** Called by PageCache.acquire() */
|
|
154
247
|
bumpRefCount() {
|
|
155
248
|
if (this.disposed) throw new Error("Context already disposed");
|
|
156
249
|
this.refCount++;
|
|
157
250
|
}
|
|
251
|
+
/** Get current reference count */
|
|
252
|
+
getRefCount() {
|
|
253
|
+
return this.refCount;
|
|
254
|
+
}
|
|
158
255
|
/** Called by PageCache.acquire() */
|
|
159
256
|
clearExpiryTimer() {
|
|
160
257
|
if (this.expiryTimer) {
|
|
@@ -162,18 +259,27 @@ class PageContext {
|
|
|
162
259
|
this.expiryTimer = void 0;
|
|
163
260
|
}
|
|
164
261
|
}
|
|
262
|
+
/** Update TTL configuration */
|
|
263
|
+
updateTtl(newTtl) {
|
|
264
|
+
this.ttl = newTtl;
|
|
265
|
+
if (this.expiryTimer && this.refCount === 0) {
|
|
266
|
+
this.clearExpiryTimer();
|
|
267
|
+
this.expiryTimer = setTimeout(() => this.disposeImmediate(), this.ttl);
|
|
268
|
+
}
|
|
269
|
+
}
|
|
165
270
|
/** Called by PageCache.release() internally */
|
|
166
271
|
release() {
|
|
167
272
|
if (this.disposed) return;
|
|
168
273
|
this.refCount--;
|
|
169
274
|
if (this.refCount === 0) {
|
|
170
|
-
this.expiryTimer = setTimeout(() => this.disposeImmediate(),
|
|
275
|
+
this.expiryTimer = setTimeout(() => this.disposeImmediate(), this.ttl);
|
|
171
276
|
}
|
|
172
277
|
}
|
|
173
278
|
/** Tear down _all_ sub-pointers & the page. */
|
|
174
279
|
disposeImmediate() {
|
|
175
280
|
if (this.disposed) return;
|
|
176
281
|
this.disposed = true;
|
|
282
|
+
this.clearExpiryTimer();
|
|
177
283
|
if (this.textPagePtr !== void 0) {
|
|
178
284
|
this.pdf.FPDFText_ClosePage(this.textPagePtr);
|
|
179
285
|
}
|
|
@@ -365,6 +471,7 @@ class PdfiumEngine {
|
|
|
365
471
|
*/
|
|
366
472
|
constructor(pdfiumModule, options = {}) {
|
|
367
473
|
this.pdfiumModule = pdfiumModule;
|
|
474
|
+
this.memoryLeakCheckInterval = null;
|
|
368
475
|
const {
|
|
369
476
|
logger = new NoopLogger(),
|
|
370
477
|
imageDataConverter = browserImageDataToBlobConverter
|
|
@@ -374,7 +481,7 @@ class PdfiumEngine {
|
|
|
374
481
|
this.imageDataConverter = imageDataConverter;
|
|
375
482
|
this.memoryManager = new MemoryManager(this.pdfiumModule, this.logger);
|
|
376
483
|
if (this.logger.isEnabled("debug")) {
|
|
377
|
-
setInterval(() => {
|
|
484
|
+
this.memoryLeakCheckInterval = setInterval(() => {
|
|
378
485
|
this.memoryManager.checkLeaks();
|
|
379
486
|
}, 1e4);
|
|
380
487
|
}
|
|
@@ -400,6 +507,10 @@ class PdfiumEngine {
|
|
|
400
507
|
this.logger.debug(LOG_SOURCE, LOG_CATEGORY, "destroy");
|
|
401
508
|
this.logger.perf(LOG_SOURCE, LOG_CATEGORY, `Destroy`, "Begin", "General");
|
|
402
509
|
this.pdfiumModule.FPDF_DestroyLibrary();
|
|
510
|
+
if (this.memoryLeakCheckInterval) {
|
|
511
|
+
clearInterval(this.memoryLeakCheckInterval);
|
|
512
|
+
this.memoryLeakCheckInterval = null;
|
|
513
|
+
}
|
|
403
514
|
this.logger.perf(LOG_SOURCE, LOG_CATEGORY, `Destroy`, "End", "General");
|
|
404
515
|
return PdfTaskHelper.resolve(true);
|
|
405
516
|
}
|
|
@@ -2026,6 +2137,18 @@ class PdfiumEngine {
|
|
|
2026
2137
|
this.logger.perf(LOG_SOURCE, LOG_CATEGORY, `CloseDocument`, "End", doc.id);
|
|
2027
2138
|
return PdfTaskHelper.resolve(true);
|
|
2028
2139
|
}
|
|
2140
|
+
/**
|
|
2141
|
+
* {@inheritDoc @embedpdf/models!PdfEngine.closeAllDocuments}
|
|
2142
|
+
*
|
|
2143
|
+
* @public
|
|
2144
|
+
*/
|
|
2145
|
+
closeAllDocuments() {
|
|
2146
|
+
this.logger.debug(LOG_SOURCE, LOG_CATEGORY, "closeAllDocuments");
|
|
2147
|
+
this.logger.perf(LOG_SOURCE, LOG_CATEGORY, `CloseAllDocuments`, "Begin");
|
|
2148
|
+
this.cache.closeAllDocuments();
|
|
2149
|
+
this.logger.perf(LOG_SOURCE, LOG_CATEGORY, `CloseAllDocuments`, "End");
|
|
2150
|
+
return PdfTaskHelper.resolve(true);
|
|
2151
|
+
}
|
|
2029
2152
|
/**
|
|
2030
2153
|
* Add text content to annotation
|
|
2031
2154
|
* @param page - page info
|
|
@@ -6502,4 +6625,4 @@ export {
|
|
|
6502
6625
|
isValidCustomKey as i,
|
|
6503
6626
|
readString as r
|
|
6504
6627
|
};
|
|
6505
|
-
//# sourceMappingURL=engine-
|
|
6628
|
+
//# sourceMappingURL=engine-Cm-940a0.js.map
|