@strategicprojects/rpic 0.6.1 → 0.6.2

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/README.md CHANGED
@@ -25,7 +25,7 @@ rpic.renderSvg('A:(0,0); B:(2,0)\nresistor(A,B)', { circuits: true });
25
25
  ```js
26
26
  import { readFileSync } from 'node:fs';
27
27
  import * as rpic from '@strategicprojects/rpic';
28
- await rpic.ready(readFileSync(new URL('./node_modules/rpic/pkg/rpic_wasm_bg.wasm', import.meta.url)));
28
+ await rpic.ready(readFileSync(new URL('./node_modules/@strategicprojects/rpic/pkg/rpic_wasm_bg.wasm', import.meta.url)));
29
29
  console.log(rpic.renderSvg('box "hi"'));
30
30
  ```
31
31
 
@@ -38,19 +38,20 @@ data) that is only fetched when you ask for it:
38
38
 
39
39
  ```js
40
40
  await rpic.ready(undefined, { math: true }); // browser: fetches pkg/rpic_wasm_math_bg.wasm
41
- rpic.renderSvg('box "$-\\\\frac{T}{2}$" fit', { texlabels: true });
41
+ rpic.renderSvg('box "$-\\frac{T}{2}$" fit', { texlabels: true });
42
42
  ```
43
43
 
44
44
  Apps can keep the fast path untouched and lazy-load math only when the source
45
- contains `$…$`. The build choice is fixed by the first `ready()` call. In
46
- Node, pass the math artifact's bytes:
45
+ contains `$…$`. The build choice is fixed by the first `ready()` call; a later
46
+ call that asks for the other build rejects instead of silently reusing the
47
+ first build. In Node, pass the math artifact's bytes:
47
48
  `ready(readFileSync(new URL('…/pkg/rpic_wasm_math_bg.wasm', import.meta.url)), { math: true })`.
48
49
 
49
50
  ## API
50
51
 
51
52
  | Function | Description |
52
53
  |----------|-------------|
53
- | `ready(wasmInput?, {math?})` | Initialize WASM. Browser: no arg. Node: pass `.wasm` bytes/URL. `math: true` loads the math-enabled build. |
54
+ | `ready(wasmInput?, {math?})` | Initialize WASM. Browser: no arg. Node: pass `.wasm` bytes/URL. `math: true` loads the math-enabled build; conflicting later calls reject. |
54
55
  | `compile(src, {circuits?, texlabels?})` | → `{ svg, animations, diagnostics, warnings }` (throws on a pic error with `errorInfo`). |
55
56
  | `renderSvg(src, {circuits?, texlabels?})` | → SVG string. |
56
57
  | `animate(root, animations, gsap)` | Build/play a GSAP timeline (`draw`/`fade`/`pop`). Browser only. |
package/index.d.ts CHANGED
@@ -59,15 +59,16 @@ export interface ReadyOptions {
59
59
  * Load the math-enabled wasm build (`pkg/rpic_wasm_math_bg.wasm`), which
60
60
  * bundles the RaTeX renderer so `texlabels` sources typeset `$…$` labels.
61
61
  * The heavier artifact is only fetched when requested; the choice is fixed
62
- * by the first `ready()` call. In Node, pass the math wasm bytes as
63
- * `wasmInput`.
62
+ * by the first `ready()` call, and conflicting later calls reject. In Node,
63
+ * pass the math wasm bytes as `wasmInput`.
64
64
  */
65
65
  math?: boolean;
66
66
  }
67
67
 
68
68
  /**
69
69
  * Initialize the WebAssembly module. In the browser call with no argument; in
70
- * Node pass the `.wasm` bytes or a file URL.
70
+ * Node pass the `.wasm` bytes or a file URL. Idempotent while pending or
71
+ * after success; a *failed* init clears the slot so `ready()` can be retried.
71
72
  */
72
73
  export function ready(
73
74
  wasmInput?: BufferSource | URL | string,
package/index.js CHANGED
@@ -7,6 +7,7 @@ import * as leanModule from './pkg/rpic_wasm.js';
7
7
 
8
8
  let initPromise = null;
9
9
  let wasm = null; // the initialized glue module (lean or math)
10
+ let initMath = null;
10
11
 
11
12
  /**
12
13
  * Initialize the WebAssembly module (idempotent; concurrent calls share one
@@ -16,18 +17,42 @@ let wasm = null; // the initialized glue module (lean or math)
16
17
  * Pass `{ math: true }` to load the math-enabled build instead: it bundles
17
18
  * the RaTeX renderer so `texlabels` sources typeset `$…$` labels exactly like
18
19
  * the native CLI. The math glue + wasm are only fetched when requested, so
19
- * the lean fast path stays untouched. The choice is fixed by the first call;
20
- * in Node, pass the bytes of `pkg/rpic_wasm_math_bg.wasm` along with it.
20
+ * the lean fast path stays untouched. The choice is fixed by the first
21
+ * successful (or in-flight) call; later calls asking for the other build
22
+ * reject. A *failed* init (bad bytes, fetch error) clears the slot so
23
+ * `ready()` can be retried. In Node, pass the bytes of
24
+ * `pkg/rpic_wasm_math_bg.wasm` along with it.
21
25
  */
22
26
  export function ready(wasmInput, opts = {}) {
23
- if (!initPromise) {
24
- initPromise = (
25
- opts.math ? import('./pkg/rpic_wasm_math.js') : Promise.resolve(leanModule)
26
- ).then(async (mod) => {
27
+ const wantsMath = !!opts.math;
28
+ if (initPromise) {
29
+ if (initMath !== wantsMath) {
30
+ const current = initMath ? 'math-enabled' : 'lean';
31
+ const requested = wantsMath ? 'math-enabled' : 'lean';
32
+ return Promise.reject(
33
+ new Error(`rpic: ready() already initialized the ${current} build; cannot switch to ${requested}`)
34
+ );
35
+ }
36
+ return initPromise;
37
+ }
38
+ initMath = wantsMath;
39
+ const attempt = (
40
+ wantsMath ? import('./pkg/rpic_wasm_math.js') : Promise.resolve(leanModule)
41
+ )
42
+ .then(async (mod) => {
27
43
  await mod.default(wasmInput === undefined ? undefined : { module_or_path: wasmInput });
28
44
  wasm = mod;
45
+ })
46
+ .catch((e) => {
47
+ // a settled rejection must not poison future calls — clear the slot
48
+ // (only if it is still ours) so the next ready() starts fresh
49
+ if (initPromise === attempt) {
50
+ initPromise = null;
51
+ initMath = null;
52
+ }
53
+ throw e;
29
54
  });
30
- }
55
+ initPromise = attempt;
31
56
  return initPromise;
32
57
  }
33
58
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@strategicprojects/rpic",
3
- "version": "0.6.1",
3
+ "version": "0.6.2",
4
4
  "description": "The pic graphics language compiled to SVG with animation manifests, via WebAssembly. Browser + Node.",
5
5
  "type": "module",
6
6
  "main": "./index.js",
Binary file
Binary file