@lpdfio/lpdf 0.32.0 → 0.33.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.
@@ -0,0 +1,74 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.runRenderJob = runRenderJob;
4
+ exports.transferList = transferList;
5
+ /**
6
+ * A render as a worker runs it: everything the engine needs, sent in one message, and the reply that comes back.
7
+ * Shared by the Node worker and the browser's.
8
+ */
9
+ const render_error_1 = require("./render-error");
10
+ /**
11
+ * Runs a render on an engine of its own, which is freed after it, and returns the PDF or the error. It never throws: a
12
+ * failure is the reply.
13
+ */
14
+ function runRenderJob(createEngine, job) {
15
+ let engine;
16
+ let reply;
17
+ try {
18
+ engine = createEngine(job.licenseKey);
19
+ // Without a clock the engine cannot check the key's expiry, and an expired key renders as though it were
20
+ // current.
21
+ engine.set_now(job.now);
22
+ engine.set_max_memory_mb(job.maxMemoryMb);
23
+ if (job.createdOn)
24
+ engine.set_created_on(job.createdOn);
25
+ for (const [name, bytes] of job.fonts)
26
+ engine.load_font(name, bytes);
27
+ for (const [name, bytes] of job.images)
28
+ engine.load_image(name, bytes);
29
+ for (const [name, bytes] of job.files)
30
+ engine.load_file(name, bytes);
31
+ for (const [name, bytes] of job.profiles)
32
+ engine.load_profile(name, bytes);
33
+ for (const [src, text] of job.markdownStyles)
34
+ engine.load_markdown_styles(src, text);
35
+ const { document } = job;
36
+ const pdf = 'xml' in document
37
+ ? engine.render_pdf(document.xml, document.data, ...job.encryption)
38
+ : 'tree' in document
39
+ ? engine.render_tree_pdf(document.tree, ...job.encryption)
40
+ : engine.stamp(document.pdf, document.stamps);
41
+ reply = { pdf };
42
+ }
43
+ catch (e) {
44
+ // A trap, or the stack running out inside the engine, which some browsers report as a RangeError, leaves the
45
+ // engine part way through a call: its memory can't be trusted. Either is a crash of the engine.
46
+ const crashed = e instanceof WebAssembly.RuntimeError || e instanceof RangeError;
47
+ reply = crashed
48
+ ? { error: render_error_1.ENGINE_CRASHED, broken: true, cause: `${e.name}: ${e.message}` }
49
+ : { error: e instanceof Error ? e.message : String(e), broken: false };
50
+ }
51
+ // An engine left part way through a call is still borrowed, and wasm-bindgen's free() throws "attempted to take
52
+ // ownership of Rust value while it was borrowed". Such an engine goes with its worker; the reply keeps the
53
+ // engine's own error.
54
+ if ('pdf' in reply || !reply.broken) {
55
+ try {
56
+ engine?.free();
57
+ }
58
+ catch {
59
+ if ('error' in reply)
60
+ reply = { ...reply, broken: true };
61
+ }
62
+ }
63
+ return reply;
64
+ }
65
+ /**
66
+ * The buffers a reply moves to the other thread instead of copying: the PDF's, when the PDF has a buffer of its own.
67
+ * A view into a larger buffer, such as the engine's memory, is copied.
68
+ */
69
+ function transferList(reply) {
70
+ if (!('pdf' in reply))
71
+ return [];
72
+ const { buffer, byteLength } = reply.pdf;
73
+ return buffer instanceof ArrayBuffer && buffer.byteLength === byteLength ? [buffer] : [];
74
+ }
@@ -0,0 +1,52 @@
1
+ import type { RenderJob, RenderReply } from './render-job';
2
+ /** The seconds a render may run when `timeout` is left out. A timeout of 0 means no limit. */
3
+ export declare const DEFAULT_TIMEOUT = 5;
4
+ /** A worker as the queue drives it, in Node or in the browser. */
5
+ export interface RenderWorker {
6
+ /** Sends it a render. */
7
+ post(job: RenderJob): void;
8
+ /** Stops it, whatever it is doing. */
9
+ terminate(): void;
10
+ /** In Node: whether the worker keeps the process running, which it does only while it renders. */
11
+ hold?(busy: boolean): void;
12
+ }
13
+ /** What a worker tells the queue. */
14
+ export interface RenderWorkerEvents {
15
+ /** The render it was sent ended, with a PDF or an error. */
16
+ replied(reply: RenderReply): void;
17
+ /** The worker failed outside a render, or stopped. */
18
+ failed(message: string): void;
19
+ }
20
+ /** Starts a worker that reports to `events`. */
21
+ export type StartRenderWorker = (events: RenderWorkerEvents) => RenderWorker;
22
+ /**
23
+ * The seconds a render may run, from the `timeout` of the engine's options: 5 when left out, no limit at 0.
24
+ *
25
+ * @throws {RangeError} when `timeout` is negative or not a finite number.
26
+ */
27
+ export declare function renderTimeout(timeout: number | undefined): number;
28
+ /**
29
+ * Renders one at a time on one worker, kept warm between renders with the engine loaded. A render that runs past its
30
+ * timeout ends the worker, since a running WebAssembly call can't be stopped any other way, and the next render
31
+ * starts a new one.
32
+ */
33
+ export declare class RenderQueue {
34
+ private readonly _start;
35
+ private _worker;
36
+ private _running;
37
+ private readonly _waiting;
38
+ constructor(_start: StartRenderWorker);
39
+ /**
40
+ * Renders `job` once the renders before it have ended. Its timeout counts from when it starts.
41
+ *
42
+ * @param timeout - The seconds it may run, 0 for no limit.
43
+ * @returns The PDF; rejects with an `LpdfRenderError` when the engine refuses the document or the render runs
44
+ * past its timeout.
45
+ */
46
+ render(job: RenderJob, timeout: number): Promise<Uint8Array>;
47
+ private _next;
48
+ private _startWorker;
49
+ private _dropWorker;
50
+ private _settle;
51
+ private _timedOut;
52
+ }
@@ -0,0 +1,116 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.RenderQueue = exports.DEFAULT_TIMEOUT = void 0;
4
+ exports.renderTimeout = renderTimeout;
5
+ const render_error_1 = require("./render-error");
6
+ /** The seconds a render may run when `timeout` is left out. A timeout of 0 means no limit. */
7
+ exports.DEFAULT_TIMEOUT = 5;
8
+ // The longest delay setTimeout takes: a longer one fires at once. A limit of 24 days is no limit for a render.
9
+ const MAX_DELAY_MS = 2 ** 31 - 1;
10
+ /**
11
+ * The seconds a render may run, from the `timeout` of the engine's options: 5 when left out, no limit at 0.
12
+ *
13
+ * @throws {RangeError} when `timeout` is negative or not a finite number.
14
+ */
15
+ function renderTimeout(timeout) {
16
+ if (timeout === undefined)
17
+ return exports.DEFAULT_TIMEOUT;
18
+ if (!Number.isFinite(timeout) || timeout < 0) {
19
+ throw new RangeError(`timeout must be a number of seconds, 0 for no limit, not ${timeout}`);
20
+ }
21
+ return timeout;
22
+ }
23
+ function seconds(count) {
24
+ return count === 1 ? '1 second' : `${count} seconds`;
25
+ }
26
+ /**
27
+ * Renders one at a time on one worker, kept warm between renders with the engine loaded. A render that runs past its
28
+ * timeout ends the worker, since a running WebAssembly call can't be stopped any other way, and the next render
29
+ * starts a new one.
30
+ */
31
+ class RenderQueue {
32
+ constructor(_start) {
33
+ this._start = _start;
34
+ this._waiting = [];
35
+ }
36
+ /**
37
+ * Renders `job` once the renders before it have ended. Its timeout counts from when it starts.
38
+ *
39
+ * @param timeout - The seconds it may run, 0 for no limit.
40
+ * @returns The PDF; rejects with an `LpdfRenderError` when the engine refuses the document or the render runs
41
+ * past its timeout.
42
+ */
43
+ render(job, timeout) {
44
+ return new Promise((resolve, reject) => {
45
+ this._waiting.push({ job, timeout, resolve, reject });
46
+ this._next();
47
+ });
48
+ }
49
+ _next() {
50
+ if (this._running)
51
+ return;
52
+ const pending = this._waiting.shift();
53
+ if (!pending) {
54
+ this._worker?.hold?.(false);
55
+ return;
56
+ }
57
+ this._running = pending;
58
+ try {
59
+ const worker = this._worker ?? (this._worker = this._startWorker());
60
+ worker.hold?.(true);
61
+ if (pending.timeout > 0) {
62
+ pending.timer = setTimeout(() => this._timedOut(pending), Math.min(pending.timeout * 1000, MAX_DELAY_MS));
63
+ }
64
+ worker.post(pending.job);
65
+ }
66
+ catch (e) {
67
+ // A worker that can't be started or sent the render fails this render, and the next one tries a new worker.
68
+ this._dropWorker();
69
+ this._settle({ error: `The render worker failed: ${e instanceof Error ? e.message : String(e)}`, broken: true });
70
+ }
71
+ }
72
+ _startWorker() {
73
+ // A worker that was ended still delivers what it sent before, and its exit: only the current one counts.
74
+ const worker = this._start({
75
+ replied: reply => {
76
+ if (worker !== this._worker)
77
+ return;
78
+ if ('error' in reply && reply.broken)
79
+ this._dropWorker();
80
+ this._settle(reply);
81
+ },
82
+ failed: message => {
83
+ if (worker !== this._worker)
84
+ return;
85
+ this._dropWorker();
86
+ this._settle({ error: message, broken: true });
87
+ },
88
+ });
89
+ return worker;
90
+ }
91
+ _dropWorker() {
92
+ this._worker?.terminate();
93
+ this._worker = undefined;
94
+ }
95
+ _settle(reply) {
96
+ const pending = this._running;
97
+ if (!pending)
98
+ return;
99
+ this._running = undefined;
100
+ clearTimeout(pending.timer);
101
+ if ('pdf' in reply) {
102
+ pending.resolve(reply.pdf);
103
+ }
104
+ else {
105
+ pending.reject(new render_error_1.LpdfRenderError(reply.error, reply.cause));
106
+ }
107
+ this._next();
108
+ }
109
+ _timedOut(pending) {
110
+ if (pending !== this._running)
111
+ return;
112
+ this._dropWorker();
113
+ this._settle({ error: `The render timed out after ${seconds(pending.timeout)}.`, broken: true });
114
+ }
115
+ }
116
+ exports.RenderQueue = RenderQueue;
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,16 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ /**
4
+ * The Node worker a `PdfEngine` renders on: it loads the engine once and runs each render it is sent.
5
+ */
6
+ const node_worker_threads_1 = require("node:worker_threads");
7
+ const render_job_1 = require("./render-job");
8
+ // require() path is relative to the compiled output at dist/render-worker.js, as engine.ts's is.
9
+ // eslint-disable-next-line @typescript-eslint/no-require-imports
10
+ const wasm = require('./wasm/lpdf.js');
11
+ // The file runs only as a worker, where parentPort is the port to the thread that started it.
12
+ const port = node_worker_threads_1.parentPort;
13
+ port.on('message', (job) => {
14
+ const reply = (0, render_job_1.runRenderJob)(licenseKey => new wasm.LpdfEngine(licenseKey), job);
15
+ port.postMessage(reply, (0, render_job_1.transferList)(reply));
16
+ });
@@ -0,0 +1,51 @@
1
+ /**
2
+ * Stamps: PNG images drawn over the pages of an existing PDF, by `stamp` on the engine. Shared by the Node.js and
3
+ * browser entry points.
4
+ */
5
+ /**
6
+ * One stamp: a PNG, the pages it goes on, and the box it is drawn in on each. The box is placed as a layer element
7
+ * is, and the image is fitted in it without distortion.
8
+ */
9
+ export interface StampAttr {
10
+ /** The PNG's bytes. An image given to several stamps is embedded in the PDF once. */
11
+ image: Uint8Array;
12
+ /** The pages: a page scope, such as `3`, `1-2`, `last`, `each`, `odd` or `1,3,5-last`. A page the PDF doesn't have is an error. */
13
+ page: string;
14
+ /**
15
+ * Where the box goes, in `pt`, `mm` or `in`: its top-left corner, from the page's top-left corner as a viewer shows
16
+ * it, or with `anchor`, signed offsets from that point of the page. Required without `anchor`.
17
+ */
18
+ x?: string;
19
+ y?: string;
20
+ /**
21
+ * The point of the page the box is placed from, and the point of the box that goes there: `top-left`,
22
+ * `top-center`, `top-right`, `center-left`, `center`, `center-right`, `bottom-left`, `bottom-center` or
23
+ * `bottom-right`.
24
+ */
25
+ anchor?: string;
26
+ /** The size of the box, in `pt`, `mm` or `in`. */
27
+ width: string;
28
+ height: string;
29
+ /** Where the image sits across the box, in the room it leaves: `start`, `center` (the default) or `end`. */
30
+ align?: string;
31
+ /** Where the image sits down the box, in the room it leaves: `start`, `center` (the default) or `end`. */
32
+ justify?: string;
33
+ /**
34
+ * How the image is sized in the box, keeping its proportions: `fit` (the default) shrinks an image larger than the
35
+ * box and keeps a smaller one at its natural size, from the resolution the PNG records, or a pixel to a point;
36
+ * `fill` takes the largest size that fits.
37
+ */
38
+ scale?: string;
39
+ /** How many times its natural size `fit` may grow an image, never past the box: 1, the default, or more. */
40
+ maxGrow?: number;
41
+ }
42
+ /**
43
+ * The stamps as the engine takes them: the JSON of the stamps, each naming its image, and the images by name. The same
44
+ * bytes, given to several stamps, go under one name.
45
+ *
46
+ * @throws {TypeError} when a stamp's `image` is not the PNG's bytes.
47
+ */
48
+ export declare function stampRequest(stamps: StampAttr[]): {
49
+ stamps: string;
50
+ images: Map<string, Uint8Array>;
51
+ };
package/dist/stamp.js ADDED
@@ -0,0 +1,30 @@
1
+ "use strict";
2
+ /**
3
+ * Stamps: PNG images drawn over the pages of an existing PDF, by `stamp` on the engine. Shared by the Node.js and
4
+ * browser entry points.
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
7
+ exports.stampRequest = stampRequest;
8
+ /**
9
+ * The stamps as the engine takes them: the JSON of the stamps, each naming its image, and the images by name. The same
10
+ * bytes, given to several stamps, go under one name.
11
+ *
12
+ * @throws {TypeError} when a stamp's `image` is not the PNG's bytes.
13
+ */
14
+ function stampRequest(stamps) {
15
+ const images = new Map();
16
+ const names = new Map();
17
+ const list = stamps.map(({ image, maxGrow, ...rest }, i) => {
18
+ if (!(image instanceof Uint8Array)) {
19
+ throw new TypeError(`stamp ${i + 1}: image must be the PNG's bytes, a Uint8Array`);
20
+ }
21
+ let name = names.get(image);
22
+ if (name === undefined) {
23
+ name = `stamp-${names.size}`;
24
+ names.set(image, name);
25
+ images.set(name, image);
26
+ }
27
+ return { ...rest, image: name, ...(maxGrow === undefined ? {} : { 'max-grow': maxGrow }) };
28
+ });
29
+ return { stamps: JSON.stringify(list), images };
30
+ }
@@ -235,6 +235,20 @@ export class LpdfEngine {
235
235
  const len0 = WASM_VECTOR_LEN;
236
236
  wasm.lpdfengine_set_font_metrics(this.__wbg_ptr, ptr0, len0);
237
237
  }
238
+ /**
239
+ * Set the memory a render may allocate, in megabytes: 1024 when it isn't set. A render that needs more stops
240
+ * with an error that names the cap. What the engine holds before the render, such as its loaded fonts, doesn't
241
+ * count.
242
+ *
243
+ * Returns an error when `mb` is 0 or above 4096, the most 32-bit WebAssembly addresses.
244
+ * @param {number} mb
245
+ */
246
+ set_max_memory_mb(mb) {
247
+ const ret = wasm.lpdfengine_set_max_memory_mb(this.__wbg_ptr, mb);
248
+ if (ret[1]) {
249
+ throw takeFromExternrefTable0(ret[0]);
250
+ }
251
+ }
238
252
  /**
239
253
  * Set the current Unix timestamp (seconds) for license expiry checking.
240
254
  * Must be called before `render_pdf` when using a time-limited token.
@@ -244,6 +258,32 @@ export class LpdfEngine {
244
258
  set_now(unix) {
245
259
  wasm.lpdfengine_set_now(this.__wbg_ptr, unix);
246
260
  }
261
+ /**
262
+ * Draw PNG stamps over the pages of an existing PDF, and return the file with them added as an incremental
263
+ * update: the input, byte for byte, then the images and the pages they change. The original bytes stay as they
264
+ * were, so an owner password and its permissions stay, and so does a digital signature's revision.
265
+ *
266
+ * `stamps` is a JSON list of stamps, each with an `image`, the name of a PNG loaded with `load_image`, a `page`
267
+ * scope, a box (`x`, `y`, `anchor`, `width`, `height`, placed as a layer element is) and how the image sits in it
268
+ * (`align`, `justify`, `scale`, `max-grow`). Without a valid license key, each stamped page gets the attribution
269
+ * line of a render in its top-right corner.
270
+ * @param {Uint8Array} pdf
271
+ * @param {string} stamps
272
+ * @returns {Uint8Array}
273
+ */
274
+ stamp(pdf, stamps) {
275
+ const ptr0 = passArray8ToWasm0(pdf, wasm.__wbindgen_malloc);
276
+ const len0 = WASM_VECTOR_LEN;
277
+ const ptr1 = passStringToWasm0(stamps, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
278
+ const len1 = WASM_VECTOR_LEN;
279
+ const ret = wasm.lpdfengine_stamp(this.__wbg_ptr, ptr0, len0, ptr1, len1);
280
+ if (ret[3]) {
281
+ throw takeFromExternrefTable0(ret[2]);
282
+ }
283
+ var v3 = getArrayU8FromWasm0(ret[0], ret[1]).slice();
284
+ wasm.__wbindgen_free(ret[0], ret[1] * 1, 1);
285
+ return v3;
286
+ }
247
287
  }
248
288
  if (Symbol.dispose) LpdfEngine.prototype[Symbol.dispose] = LpdfEngine.prototype.free;
249
289
 
@@ -292,7 +332,7 @@ export function check_license(token, now_unix) {
292
332
  * in multiple target languages.
293
333
  *
294
334
  * `options_json` accepts the same shape as `codegen_wasm`:
295
- * - `target`: `"js"`, `"dotnet"`, `"php"`, or `"python"` (required)
335
+ * - `target`: `"js"`, `"dotnet"`, `"php"`, `"python"` or `"java"` (required)
296
336
  * - `indent`: `2` or `4` (optional, default `4`)
297
337
  * @param {string} xml
298
338
  * @param {string} options_json
@@ -325,7 +365,7 @@ export function codegen_fragment_wasm(xml, options_json) {
325
365
  * Generate SDK source code from an Lpdf XML string.
326
366
  *
327
367
  * `options_json` is a JSON object with:
328
- * - `target`: `"js"` (required)
368
+ * - `target`: `"js"`, `"dotnet"`, `"php"`, `"python"` or `"java"` (required)
329
369
  * - `indent`: `2` or `4` (optional, default `4`)
330
370
  *
331
371
  * Returns the generated source code as a string.
@@ -518,6 +558,9 @@ function __wbg_get_imports() {
518
558
  __wbg___wbindgen_throw_6b64449b9b9ed33c: function(arg0, arg1) {
519
559
  throw new Error(getStringFromWasm0(arg0, arg1));
520
560
  },
561
+ __wbg_getRandomValues_cc7f052a444bb2ce: function() { return handleError(function (arg0, arg1) {
562
+ globalThis.crypto.getRandomValues(getArrayU8FromWasm0(arg0, arg1));
563
+ }, arguments); },
521
564
  __wbindgen_cast_0000000000000001: function(arg0, arg1) {
522
565
  // Cast intrinsic for `Ref(String) -> Externref`.
523
566
  const ret = getStringFromWasm0(arg0, arg1);
@@ -543,6 +586,12 @@ const LpdfEngineFinalization = (typeof FinalizationRegistry === 'undefined')
543
586
  ? { register: () => {}, unregister: () => {} }
544
587
  : new FinalizationRegistry(ptr => wasm.__wbg_lpdfengine_free(ptr >>> 0, 1));
545
588
 
589
+ function addToExternrefTable0(obj) {
590
+ const idx = wasm.__externref_table_alloc();
591
+ wasm.__wbindgen_externrefs.set(idx, obj);
592
+ return idx;
593
+ }
594
+
546
595
  function getArrayU8FromWasm0(ptr, len) {
547
596
  ptr = ptr >>> 0;
548
597
  return getUint8ArrayMemory0().subarray(ptr / 1, ptr / 1 + len);
@@ -561,6 +610,15 @@ function getUint8ArrayMemory0() {
561
610
  return cachedUint8ArrayMemory0;
562
611
  }
563
612
 
613
+ function handleError(f, args) {
614
+ try {
615
+ return f.apply(this, args);
616
+ } catch (e) {
617
+ const idx = addToExternrefTable0(e);
618
+ wasm.__wbindgen_exn_store(idx);
619
+ }
620
+ }
621
+
564
622
  function isLikeNone(x) {
565
623
  return x === undefined || x === null;
566
624
  }
package/dist/wasm/lpdf.js CHANGED
@@ -235,6 +235,20 @@ class LpdfEngine {
235
235
  const len0 = WASM_VECTOR_LEN;
236
236
  wasm.lpdfengine_set_font_metrics(this.__wbg_ptr, ptr0, len0);
237
237
  }
238
+ /**
239
+ * Set the memory a render may allocate, in megabytes: 1024 when it isn't set. A render that needs more stops
240
+ * with an error that names the cap. What the engine holds before the render, such as its loaded fonts, doesn't
241
+ * count.
242
+ *
243
+ * Returns an error when `mb` is 0 or above 4096, the most 32-bit WebAssembly addresses.
244
+ * @param {number} mb
245
+ */
246
+ set_max_memory_mb(mb) {
247
+ const ret = wasm.lpdfengine_set_max_memory_mb(this.__wbg_ptr, mb);
248
+ if (ret[1]) {
249
+ throw takeFromExternrefTable0(ret[0]);
250
+ }
251
+ }
238
252
  /**
239
253
  * Set the current Unix timestamp (seconds) for license expiry checking.
240
254
  * Must be called before `render_pdf` when using a time-limited token.
@@ -244,6 +258,32 @@ class LpdfEngine {
244
258
  set_now(unix) {
245
259
  wasm.lpdfengine_set_now(this.__wbg_ptr, unix);
246
260
  }
261
+ /**
262
+ * Draw PNG stamps over the pages of an existing PDF, and return the file with them added as an incremental
263
+ * update: the input, byte for byte, then the images and the pages they change. The original bytes stay as they
264
+ * were, so an owner password and its permissions stay, and so does a digital signature's revision.
265
+ *
266
+ * `stamps` is a JSON list of stamps, each with an `image`, the name of a PNG loaded with `load_image`, a `page`
267
+ * scope, a box (`x`, `y`, `anchor`, `width`, `height`, placed as a layer element is) and how the image sits in it
268
+ * (`align`, `justify`, `scale`, `max-grow`). Without a valid license key, each stamped page gets the attribution
269
+ * line of a render in its top-right corner.
270
+ * @param {Uint8Array} pdf
271
+ * @param {string} stamps
272
+ * @returns {Uint8Array}
273
+ */
274
+ stamp(pdf, stamps) {
275
+ const ptr0 = passArray8ToWasm0(pdf, wasm.__wbindgen_malloc);
276
+ const len0 = WASM_VECTOR_LEN;
277
+ const ptr1 = passStringToWasm0(stamps, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
278
+ const len1 = WASM_VECTOR_LEN;
279
+ const ret = wasm.lpdfengine_stamp(this.__wbg_ptr, ptr0, len0, ptr1, len1);
280
+ if (ret[3]) {
281
+ throw takeFromExternrefTable0(ret[2]);
282
+ }
283
+ var v3 = getArrayU8FromWasm0(ret[0], ret[1]).slice();
284
+ wasm.__wbindgen_free(ret[0], ret[1] * 1, 1);
285
+ return v3;
286
+ }
247
287
  }
248
288
  if (Symbol.dispose) LpdfEngine.prototype[Symbol.dispose] = LpdfEngine.prototype.free;
249
289
  exports.LpdfEngine = LpdfEngine;
@@ -294,7 +334,7 @@ exports.check_license = check_license;
294
334
  * in multiple target languages.
295
335
  *
296
336
  * `options_json` accepts the same shape as `codegen_wasm`:
297
- * - `target`: `"js"`, `"dotnet"`, `"php"`, or `"python"` (required)
337
+ * - `target`: `"js"`, `"dotnet"`, `"php"`, `"python"` or `"java"` (required)
298
338
  * - `indent`: `2` or `4` (optional, default `4`)
299
339
  * @param {string} xml
300
340
  * @param {string} options_json
@@ -328,7 +368,7 @@ exports.codegen_fragment_wasm = codegen_fragment_wasm;
328
368
  * Generate SDK source code from an Lpdf XML string.
329
369
  *
330
370
  * `options_json` is a JSON object with:
331
- * - `target`: `"js"` (required)
371
+ * - `target`: `"js"`, `"dotnet"`, `"php"`, `"python"` or `"java"` (required)
332
372
  * - `indent`: `2` or `4` (optional, default `4`)
333
373
  *
334
374
  * Returns the generated source code as a string.
@@ -529,6 +569,9 @@ function __wbg_get_imports() {
529
569
  __wbg___wbindgen_throw_6b64449b9b9ed33c: function(arg0, arg1) {
530
570
  throw new Error(getStringFromWasm0(arg0, arg1));
531
571
  },
572
+ __wbg_getRandomValues_cc7f052a444bb2ce: function() { return handleError(function (arg0, arg1) {
573
+ globalThis.crypto.getRandomValues(getArrayU8FromWasm0(arg0, arg1));
574
+ }, arguments); },
532
575
  __wbindgen_cast_0000000000000001: function(arg0, arg1) {
533
576
  // Cast intrinsic for `Ref(String) -> Externref`.
534
577
  const ret = getStringFromWasm0(arg0, arg1);
@@ -554,6 +597,12 @@ const LpdfEngineFinalization = (typeof FinalizationRegistry === 'undefined')
554
597
  ? { register: () => {}, unregister: () => {} }
555
598
  : new FinalizationRegistry(ptr => wasm.__wbg_lpdfengine_free(ptr >>> 0, 1));
556
599
 
600
+ function addToExternrefTable0(obj) {
601
+ const idx = wasm.__externref_table_alloc();
602
+ wasm.__wbindgen_externrefs.set(idx, obj);
603
+ return idx;
604
+ }
605
+
557
606
  function getArrayU8FromWasm0(ptr, len) {
558
607
  ptr = ptr >>> 0;
559
608
  return getUint8ArrayMemory0().subarray(ptr / 1, ptr / 1 + len);
@@ -572,6 +621,15 @@ function getUint8ArrayMemory0() {
572
621
  return cachedUint8ArrayMemory0;
573
622
  }
574
623
 
624
+ function handleError(f, args) {
625
+ try {
626
+ return f.apply(this, args);
627
+ } catch (e) {
628
+ const idx = addToExternrefTable0(e);
629
+ wasm.__wbindgen_exn_store(idx);
630
+ }
631
+ }
632
+
575
633
  function isLikeNone(x) {
576
634
  return x === undefined || x === null;
577
635
  }
Binary file
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lpdfio/lpdf",
3
- "version": "0.32.0",
3
+ "version": "0.33.0",
4
4
  "description": "Node.js SDK for Lpdf — PDF as Code on every platform. You describe a document as code or XML. Lpdf renders a compact, pixel-perfect PDF — identical across platforms.",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -19,7 +19,7 @@
19
19
  "build": "tsc && node build-browser.mjs && node -e \"require('node:fs').cpSync('./wasm', './dist/wasm', {recursive:true})\"",
20
20
  "build:node": "tsc",
21
21
  "build:browser": "node build-browser.mjs",
22
- "test": "node --test test/render.test.mjs test/package-entry.test.mjs"
22
+ "test": "node --test test/render.test.mjs test/package-entry.test.mjs test/timeout.test.mjs test/memory.test.mjs test/stamp.test.mjs"
23
23
  },
24
24
  "author": "lpdf.io",
25
25
  "homepage": "https://lpdf.io",