@peisar/peisar-wasm32-wasi 0.2.0 → 0.2.21

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,585 @@
1
+ /* auto-generated by NAPI-RS */
2
+ /* eslint-disable */
3
+
4
+ /** The WASI flavor this loader instantiates. */
5
+ export declare const __napiBindingTarget: 'wasm32-wasi'
6
+
7
+ /**
8
+ * Parses one Markdown document and exposes its AST, HTML, and front matter
9
+ * to JavaScript.
10
+ *
11
+ * Construct this class with the Markdown source and an optional
12
+ * [`PeisarOptions`] object. Properties are computed from the source document;
13
+ * accessing `ast`, `html`, or `astJson` also applies registered visitors.
14
+ */
15
+ export declare class Peisar {
16
+ /**
17
+ * Creates a parser for `rawMd`.
18
+ *
19
+ * When `options` is omitted, GFM and Kramdown parsing are enabled and
20
+ * `html` returns a complete HTML document.
21
+ */
22
+ constructor(rawMd: string, options?: PeisarOptions | undefined | null)
23
+ /**
24
+ * Gets the parsed Markdown document as a JavaScript AST object.
25
+ *
26
+ * Registered visitors run before the AST is returned. The returned value
27
+ * is a clone, so reading this property does not consume the parser state.
28
+ */
29
+ get ast(): Document
30
+ /**
31
+ * Registers a JavaScript AST visitor.
32
+ *
33
+ * The visitor can provide `visitBlock` and/or `visitInline` callbacks.
34
+ * Each callback receives a one-item node tuple and may return a control object that
35
+ * changes the node or determines whether its children are visited.
36
+ */
37
+ useVisitor(visitor: Visitor): void
38
+ /**
39
+ * Registers a JavaScript custom parser hook.
40
+ *
41
+ * The parser can provide `parseBlock` and/or `parseInline` callbacks.
42
+ * `parseBlock` receives `{ line, lineIndex, lines }` and returns
43
+ * `{ block, consumed }`; `parseInline` receives `{ rest, index }` and
44
+ * returns `{ inline, consumed }`. Return `undefined` (or omit the
45
+ * node) to decline a position.
46
+ *
47
+ * Hooks run before the built-in parsers, in registration order. Since
48
+ * the document is parsed at construction, registering a parser hook
49
+ * re-parses the original Markdown so hook syntax is recognized.
50
+ */
51
+ useParser(parser: Parser): void
52
+ /**
53
+ * Renders the parsed Markdown as HTML using the configured render options.
54
+ *
55
+ * Registered visitors run before rendering.
56
+ */
57
+ get html(): string
58
+ /** Gets the deserialized YAML front matter, or `null` when none exists. */
59
+ get frontmatter(): any | null
60
+ /**
61
+ * Gets the parsed Markdown AST serialized as JSON.
62
+ *
63
+ * Registered visitors run before serialization.
64
+ */
65
+ get astJson(): string
66
+ }
67
+
68
+ /**
69
+ * Options that control how Markdown is parsed.
70
+ *
71
+ * # Defaults
72
+ *
73
+ * Both GFM and Kramdown extensions are enabled by default. To parse
74
+ * strict CommonMark only:
75
+ */
76
+ export interface AstOptions {
77
+ /**
78
+ * Enable GitHub Flavored Markdown (tables, strikethrough, task lists,
79
+ * autolinks). Default: `true`.
80
+ */
81
+ gfm: boolean
82
+ /**
83
+ * Enable Kramdown-style block attributes (`{:#id .class key="val"}`).
84
+ * Default: `true`.
85
+ */
86
+ kramdown: boolean
87
+ /**
88
+ * Optional file name to attach to the parsed
89
+ * [`Document`](crate::markdown::ast::Document).
90
+ */
91
+ fileName?: string
92
+ }
93
+
94
+ /** Parsed Kramdown block attributes (`{:#id .class key="val"}`). */
95
+ export interface Attributes {
96
+ /** HTML `id` attribute. */
97
+ id?: string
98
+ /** CSS class list. */
99
+ classes?: Array<string>
100
+ /** Arbitrary key/value attributes. */
101
+ attributes?: Array<[string, string]>
102
+ }
103
+
104
+ /** Block-level nodes. */
105
+ export type Block =
106
+ | { type: 'Heading'; /** Heading level (1–6). */
107
+ level: number; /** Inline content of the heading. */
108
+ children: Array<Inline>; /** Source span. */
109
+ pos: Span; /** Optional Kramdown attributes. */
110
+ attrs?: Attributes }
111
+ | { type: 'Paragraph'; /** Inline content of the paragraph. */
112
+ children: Array<Inline>; /** Source span. */
113
+ pos: Span; /** Optional Kramdown attributes. */
114
+ attrs?: Attributes }
115
+ | { type: 'CodeBlock'; /** Language hint from the info string (e.g. `rust` from ` ```rust `). */
116
+ lang?: string; /** The raw code content. */
117
+ code: string; /** Source span. */
118
+ pos: Span; /** Optional Kramdown attributes. */
119
+ attrs?: Attributes }
120
+ | { type: 'BlockQuote'; /** Nested block content inside the quote. */
121
+ children: Array<Block>; /** Source span. */
122
+ pos: Span; /** Optional Kramdown attributes. */
123
+ attrs?: Attributes }
124
+ | { type: 'List'; /** `true` for ordered lists, `false` for unordered. */
125
+ ordered: boolean; /** The list items. */
126
+ items: Array<ListItem>; /** Source span. */
127
+ pos: Span; /** Optional Kramdown attributes. */
128
+ attrs?: Attributes }
129
+ | { type: 'ThematicBreak'; /** Source span. */
130
+ pos: Span }
131
+ | { type: 'HtmlBlock'; /** The raw HTML content. */
132
+ html: string; /** Source span. */
133
+ pos: Span; /** Optional Kramdown attributes. */
134
+ attrs?: Attributes }
135
+ | { type: 'Table'; /** The table structure (header, rows, alignments). */
136
+ table: Table; /** Source span. */
137
+ pos: Span; /** Optional Kramdown attributes. */
138
+ attrs?: Attributes }
139
+ | { type: 'LinkReferenceDefinition'; /** Normalised label (lowercased, trimmed). */
140
+ label: string; /** The destination URL. */
141
+ url: string; /** Optional link title. */
142
+ title?: string; /** Source span. */
143
+ pos: Span }
144
+ | { type: 'Comment'; /** The comment text (markers stripped). */
145
+ value: string; /** Source span. */
146
+ pos: Span }
147
+
148
+ /**
149
+ * Synchronous block-visitor callback. Receives a `Block`, returns
150
+ * `VisitControlJs` (or `undefined` for no changes).
151
+ */
152
+ export type BlockCallback = (arg: [Block]) => VisitControlJs | null
153
+
154
+ /**
155
+ * Synchronous block parser hook. Receives a [`BlockParseContext`], returns
156
+ * a [`BlockParseResultJs`] (or `undefined` to decline).
157
+ */
158
+ export type BlockParseCallback = (arg: [BlockParseContext]) => BlockParseResultJs | null
159
+
160
+ /**
161
+ * Context passed to block parser hooks.
162
+ *
163
+ * On the JavaScript side the fields are exposed as `line`, `lineIndex`,
164
+ * and `lines`.
165
+ */
166
+ export interface BlockParseContext {
167
+ /** The current (unmodified) source line. */
168
+ line: string
169
+ /** 0-based index of the current line in the (sub-)document. */
170
+ lineIndex: number
171
+ /** Remaining lines starting at the current line (`lines[0]` is `line`). */
172
+ lines: Array<string>
173
+ }
174
+
175
+ /**
176
+ * Result returned from the JS `parseBlock` callback.
177
+ *
178
+ * All fields are optional; omitting `block` (or returning `undefined`)
179
+ * declines the position so the next hook / built-in parser handles it.
180
+ */
181
+ export interface BlockParseResultJs {
182
+ /** The parsed block node. */
183
+ block?: Block
184
+ /** Number of source lines consumed (must be at least `1`). */
185
+ consumed?: number
186
+ }
187
+
188
+ /**
189
+ * A Markdown document — the root of the AST.
190
+ *
191
+ * Contains the top-level block children and all link reference definitions
192
+ * collected from the source text.
193
+ */
194
+ export interface Document {
195
+ /** Always `"root"`. */
196
+ nodeType: string
197
+ /** Optional source file name. */
198
+ fileName?: string
199
+ /** Span of the whole document in the source text. */
200
+ pos: Span
201
+ /** Top-level block children. */
202
+ children: Array<Block>
203
+ /** All link reference definitions collected from the document. */
204
+ linkReferences: Array<LinkReferenceDefinition>
205
+ }
206
+
207
+ /** Emphasis strength. */
208
+ export declare const enum EmphasisLevel {
209
+ /** `*italic*` / `_italic_` */
210
+ Italic = 0,
211
+ /** `**bold**` / `__bold__` */
212
+ Bold = 1,
213
+ }
214
+
215
+ /** Inline-level nodes. */
216
+ export type Inline =
217
+ | { type: 'Text'; /** The text value. */
218
+ value: string; /** Source span. */
219
+ pos: Span }
220
+ | { type: 'Emphasis'; /** Emphasis level (italic or bold). */
221
+ level: EmphasisLevel; /** Nested inline content. */
222
+ children: Array<Inline>; /** Source span. */
223
+ pos: Span }
224
+ | { type: 'Code'; /** The code text. */
225
+ code: string; /** Source span. */
226
+ pos: Span }
227
+ | { type: 'HtmlInline'; /** The raw HTML string. */
228
+ html: string; /** Source span. */
229
+ pos: Span }
230
+ | { type: 'Strikethrough'; /** Nested inline content. */
231
+ children: Array<Inline>; /** Source span. */
232
+ pos: Span }
233
+ | { type: 'HardBreak'; /** Source span. */
234
+ pos: Span }
235
+ | { type: 'SoftBreak'; /** Source span. */
236
+ pos: Span }
237
+ | { type: 'Image'; /** Alternative text. */
238
+ alt: string; /** Image URL. */
239
+ url: string; /** Optional title. */
240
+ title?: string; /** Source span. */
241
+ pos: Span }
242
+ | { type: 'Link'; /** Link text (inline children). */
243
+ text: Array<Inline>; /** Destination URL. */
244
+ url: string; /** Optional link title. */
245
+ title?: string; /** `true` if this is a GFM autolink (bare URL). */
246
+ autolink: boolean; /** Source span. */
247
+ pos: Span }
248
+ | { type: 'LinkReference'; /** Link text (inline children). */
249
+ text: Array<Inline>; /** Normalised label used to look up the reference. */
250
+ label: string; /** Resolved destination URL. */
251
+ url: string; /** Optional resolved title. */
252
+ title?: string; /** Source span. */
253
+ pos: Span }
254
+
255
+ /**
256
+ * Synchronous inline-visitor callback. Receives an `Inline`, returns
257
+ * `InlineVisitControlJs` (or `undefined` for no changes).
258
+ */
259
+ export type InlineCallback = (arg: [Inline]) => InlineVisitControlJs | null
260
+
261
+ /**
262
+ * Synchronous inline parser hook. Receives an [`InlineParseContext`],
263
+ * returns an [`InlineParseResultJs`] (or `undefined` to decline).
264
+ */
265
+ export type InlineParseCallback = (arg: [InlineParseContext]) => InlineParseResultJs | null
266
+
267
+ /**
268
+ * Context passed to inline parser hooks.
269
+ *
270
+ * On the JavaScript side the fields are exposed as `rest` and `index`.
271
+ */
272
+ export interface InlineParseContext {
273
+ /** Remaining inline text starting at the current character position. */
274
+ rest: string
275
+ /** 0-based character index of the current position in the inline text. */
276
+ index: number
277
+ }
278
+
279
+ /**
280
+ * Result returned from the JS `parseInline` callback.
281
+ *
282
+ * All fields are optional; omitting `inline` (or returning `undefined`)
283
+ * declines the position so the next hook / built-in parser handles it.
284
+ */
285
+ export interface InlineParseResultJs {
286
+ /** The parsed inline node. */
287
+ inline?: Inline
288
+ /** Number of characters consumed (`0` or missing declines). */
289
+ consumed?: number
290
+ }
291
+
292
+ /**
293
+ * JS-facing mirror of [`InlineVisitControl`].
294
+ *
295
+ * Returned from the JS `visitInline` callback. All fields are optional;
296
+ * omitting a field means "no change" for that operation.
297
+ */
298
+ export interface InlineVisitControlJs {
299
+ /** Nodes to insert before the current node. */
300
+ insertBefore?: Array<Inline>
301
+ /** Nodes to insert after the current node. */
302
+ insertAfter?: Array<Inline>
303
+ /** Replace the current node with these nodes. */
304
+ replaceWith?: Array<Inline>
305
+ /** Remove the current node entirely. */
306
+ remove?: boolean
307
+ /** Whether to recurse into this node's children. */
308
+ recurse?: boolean
309
+ }
310
+
311
+ /** A link reference definition collected at the document level. */
312
+ export interface LinkReferenceDefinition {
313
+ /** Normalised label (lowercased, trimmed). */
314
+ label: string
315
+ /** The destination URL. */
316
+ url: string
317
+ /** Optional link title. */
318
+ title?: string
319
+ /** Source span. */
320
+ pos: Span
321
+ }
322
+
323
+ /** A single list item (an `<li>`). Contains nested block content. */
324
+ export interface ListItem {
325
+ /** Nested block content of the item. */
326
+ children: Array<Block>
327
+ /** GFM task-list state: `None` = not a task, `Some` = checked / unchecked. */
328
+ task?: TaskState
329
+ /** Span of the item in the *sub-document* of its enclosing list. */
330
+ pos: Span
331
+ }
332
+
333
+ /**
334
+ * JavaScript object shape for a parser hook pair.
335
+ *
336
+ * ```js
337
+ * const myParser = {
338
+ * parseBlock(ctx) {
339
+ * if (!ctx.line.startsWith(':::')) return; // decline
340
+ * const name = ctx.line.slice(3).trim();
341
+ * return {
342
+ * block: { type: 'HtmlBlock', html: `<div data-name="${name}"></div>`, pos: { start: {}, end: {} } },
343
+ * consumed: 1,
344
+ * };
345
+ * },
346
+ * parseInline(ctx) {
347
+ * if (!ctx.rest.startsWith('@@')) return; // decline
348
+ * const end = ctx.rest.indexOf(' ', 2);
349
+ * const name = end === -1 ? ctx.rest.slice(2) : ctx.rest.slice(2, end);
350
+ * return {
351
+ * inline: { type: 'HtmlInline', html: `<span data-name="${name}"></span>`, pos: { start: {}, end: {} } },
352
+ * consumed: name.length + 2,
353
+ * };
354
+ * },
355
+ * };
356
+ * document.useParser(myParser);
357
+ * ```
358
+ *
359
+ * Either property may be omitted / `null` to skip that phase.
360
+ */
361
+ export interface Parser {
362
+ /** Optional JS block parser hook (JS: `parseBlock`). */
363
+ parseBlock?: BlockParseCallback
364
+ /** Optional JS inline parser hook (JS: `parseInline`). */
365
+ parseInline?: InlineParseCallback
366
+ }
367
+
368
+ /** The Markdown body and YAML metadata parsed from a front-matter document. */
369
+ export interface ParseResult {
370
+ /** Markdown source after the leading YAML front matter is removed. */
371
+ pureMarkdownContent: string
372
+ /** Deserialized YAML front matter, or `null` when no front matter exists. */
373
+ yamlData?: Record<string, any>
374
+ }
375
+
376
+ /**
377
+ * JavaScript options for Markdown parsing and HTML rendering.
378
+ *
379
+ * Every property is optional. Omitted parsing options enable GFM and
380
+ * Kramdown; omitted rendering options produce a complete HTML document with
381
+ * charset and viewport metadata.
382
+ *
383
+ * # Defaults
384
+ *
385
+ * | Property | Default |
386
+ * |------------|-------------|
387
+ * | `gfm` | `true` |
388
+ * | `kramdown` | `true` |
389
+ * | `fragment` | `false` (full document) |
390
+ * | `charset` | `true` |
391
+ * | `viewport` | `true` |
392
+ * | `file_name`, `title`, `body_class`, `style` | `null` |
393
+ */
394
+ export interface PeisarOptions {
395
+ /**
396
+ * Enable GitHub Flavored Markdown (tables, strikethrough, task lists,
397
+ * autolinks). Default: `true`.
398
+ */
399
+ gfm?: boolean
400
+ /**
401
+ * Enable Kramdown-style block attributes (`{:#id .class key="val"}`).
402
+ * Default: `true`.
403
+ */
404
+ kramdown?: boolean
405
+ /**
406
+ * Optional file name to attach to the parsed
407
+ * [`Document`](crate::markdown::ast::Document).
408
+ */
409
+ fileName?: string
410
+ /**
411
+ * If `true`, emit only the body content (no `<!DOCTYPE>`, `<html>`,
412
+ * `<head>`, or `<body>` wrapper). If `false`, emit a full HTML
413
+ * document. Default: `true` (fragment).
414
+ */
415
+ fragment?: boolean
416
+ /**
417
+ * Include a `<meta charset="utf-8">` in the head (only relevant when
418
+ * `fragment` is `false`). Default: `true`.
419
+ */
420
+ charset?: boolean
421
+ /**
422
+ * Include a `<meta name="viewport" content="width=device-width,
423
+ * initial-scale=1.0">` in the head (only relevant when `fragment` is
424
+ * `false`). Default: `true`.
425
+ */
426
+ viewport?: boolean
427
+ /**
428
+ * Optional `<title>` for the HTML head (only relevant when
429
+ * `fragment` is `false`). Default: `None`.
430
+ */
431
+ title?: string
432
+ /**
433
+ * Optional additional CSS classes to add to `<body>` (only relevant
434
+ * when `fragment` is `false`). Default: `None`.
435
+ */
436
+ bodyClass?: string
437
+ /**
438
+ * Optional inline CSS to inject in a `<style>` tag in the head.
439
+ * Default: `None`.
440
+ */
441
+ style?: string
442
+ }
443
+
444
+ /** A zero-based point in the source text. */
445
+ export interface Position {
446
+ /** Line number, 0-based. */
447
+ line: number
448
+ /** Column number, 0-based (in characters). */
449
+ column: number
450
+ /** Byte offset from the start of the input. */
451
+ offset: number
452
+ }
453
+
454
+ /** Options that control how the AST is rendered to HTML. */
455
+ export interface RenderOptions {
456
+ /**
457
+ * If `true`, emit only the body content (no `<!DOCTYPE>`, `<html>`,
458
+ * `<head>`, or `<body>` wrapper). If `false`, emit a full HTML
459
+ * document. Default: `true` (fragment).
460
+ */
461
+ fragment: boolean
462
+ /**
463
+ * Include a `<meta charset="utf-8">` in the head (only relevant when
464
+ * `fragment` is `false`). Default: `true`.
465
+ */
466
+ charset: boolean
467
+ /**
468
+ * Include a `<meta name="viewport" content="width=device-width,
469
+ * initial-scale=1.0">` in the head (only relevant when `fragment` is
470
+ * `false`). Default: `true`.
471
+ */
472
+ viewport: boolean
473
+ /**
474
+ * Optional `<title>` for the HTML head (only relevant when
475
+ * `fragment` is `false`). Default: `None`.
476
+ */
477
+ title?: string
478
+ /**
479
+ * Optional additional CSS classes to add to `<body>` (only relevant
480
+ * when `fragment` is `false`). Default: `None`.
481
+ */
482
+ bodyClass?: string
483
+ /**
484
+ * Optional inline CSS to inject in a `<style>` tag in the head.
485
+ * Default: `None`.
486
+ */
487
+ style?: string
488
+ }
489
+
490
+ /**
491
+ * A half-open span `[start, end)` covering a node's source text.
492
+ *
493
+ * `start` is inclusive and `end` is exclusive; both positions point into the
494
+ * original source string.
495
+ */
496
+ export interface Span {
497
+ /** The start position (inclusive). */
498
+ start: Position
499
+ /** The end position (exclusive). */
500
+ end: Position
501
+ }
502
+
503
+ /** A GFM table. */
504
+ export interface Table {
505
+ /** The header row. */
506
+ header: TableRow
507
+ /** Body rows. */
508
+ rows: Array<TableRow>
509
+ /** Column alignment specifications (one per column). */
510
+ alignments: Array<TableCellAlignment>
511
+ }
512
+
513
+ /** A single table cell. */
514
+ export interface TableCell {
515
+ /** Inline content of the cell. */
516
+ children: Array<Inline>
517
+ }
518
+
519
+ /** Column alignment for table cells. */
520
+ export declare const enum TableCellAlignment {
521
+ /** `:---` or `---` — default (left) */
522
+ Default = 0,
523
+ /** `:---` */
524
+ Left = 1,
525
+ /** `:---:` */
526
+ Center = 2,
527
+ /** `---:` */
528
+ Right = 3,
529
+ }
530
+
531
+ /** A single table row (header or body). */
532
+ export interface TableRow {
533
+ /** The cells in this row. */
534
+ cells: Array<TableCell>
535
+ }
536
+
537
+ /** GFM task-list checkbox state. */
538
+ export declare const enum TaskState {
539
+ /** `[ ]` — unchecked */
540
+ Unchecked = 0,
541
+ /** `[x]` / `[X]` — checked */
542
+ Checked = 1,
543
+ }
544
+
545
+ /**
546
+ * JS-facing mirror of [`VisitControl`].
547
+ *
548
+ * Returned from the JS `visitBlock` callback. All fields are optional;
549
+ * omitting a field means "no change" for that operation.
550
+ */
551
+ export interface VisitControlJs {
552
+ /** Nodes to insert before the current node. */
553
+ insertBefore?: Array<Block>
554
+ /** Nodes to insert after the current node. */
555
+ insertAfter?: Array<Block>
556
+ /** Replace the current node with these nodes. */
557
+ replaceWith?: Array<Block>
558
+ /** Remove the current node entirely. */
559
+ remove?: boolean
560
+ /** Whether to recurse into this node's children. */
561
+ recurse?: boolean
562
+ }
563
+
564
+ /**
565
+ * JavaScript object shape for a visitor callback pair.
566
+ *
567
+ * On the JS side it is a plain object with two optional
568
+ * function properties:
569
+ *
570
+ * ```js
571
+ * const myPlugin = {
572
+ * visitBlock(block) { return { recurse: true }; },
573
+ * visitInline(inline) { return {}; },
574
+ * };
575
+ * ast.addVisitor(myPlugin);
576
+ * ```
577
+ *
578
+ * Either property may be omitted / `null` to skip that node kind.
579
+ */
580
+ export interface Visitor {
581
+ /** Optional JS callback for block nodes (JS: `visitBlock`). */
582
+ visitBlock?: BlockCallback
583
+ /** Optional JS callback for inline nodes (JS: `visitInline`). */
584
+ visitInline?: InlineCallback
585
+ }
Binary file
@@ -0,0 +1,67 @@
1
+ import {
2
+ instantiateNapiModuleSync,
3
+ MessageHandler,
4
+ WASI,
5
+ emnapiAsyncWorkPlugin,
6
+ emnapiTSFNPlugin,
7
+ } from '@napi-rs/wasm-runtime'
8
+
9
+ const handler = new MessageHandler({
10
+ onLoad({ wasmModule, wasmMemory }) {
11
+ const wasi = new WASI({
12
+ print: function () {
13
+ // eslint-disable-next-line no-console
14
+ console.log.apply(console, arguments)
15
+ },
16
+ printErr: function () {
17
+ // eslint-disable-next-line no-console
18
+ console.error.apply(console, arguments)
19
+ },
20
+ })
21
+ return instantiateNapiModuleSync(wasmModule, {
22
+ childThread: true,
23
+ wasi,
24
+ // The wasm links a "basic" emnapi archive (no C async-work /
25
+ // threadsafe-function implementations), so every thread that
26
+ // instantiates it must provide the JavaScript implementations
27
+ // through the emnapi plugins.
28
+ plugins: [emnapiAsyncWorkPlugin, emnapiTSFNPlugin],
29
+ overwriteImports(importObject) {
30
+ importObject.env = {
31
+ ...importObject.env,
32
+ ...importObject.napi,
33
+ ...importObject.emnapi,
34
+ memory: wasmMemory,
35
+ }
36
+ },
37
+ })
38
+ },
39
+ })
40
+
41
+ // When this wasm thread dies, raise the addon's crash flag before emnapi reports
42
+ // it. The loader thread may be inside wasm, in a cleanup call that waits on this
43
+ // thread; the flag is what those waits check between short slices, and once it
44
+ // is up they trap instead of waiting for good. It is a word in the shared wasm
45
+ // memory, and the loader posts a view of it (see
46
+ // napi_wasm_thread_crash_flag_address) after it instantiated the wasm, or right
47
+ // after it created this worker. No view, no flag: an addon built with an older
48
+ // napi, or a failure before the view arrived.
49
+ let __addonCrashFlag
50
+ const __beforeReportError = handler.beforeReportError
51
+ handler.beforeReportError = function (...args) {
52
+ if (__addonCrashFlag !== undefined) {
53
+ try {
54
+ Atomics.store(__addonCrashFlag, 0, 1)
55
+ } catch {}
56
+ }
57
+ return __beforeReportError.apply(this, args)
58
+ }
59
+
60
+ globalThis.onmessage = function (e) {
61
+ const data = e && e.data
62
+ if (data && data.__napiRsAddonCrashFlag instanceof Int32Array) {
63
+ __addonCrashFlag = data.__napiRsAddonCrashFlag
64
+ return
65
+ }
66
+ handler.handle(e)
67
+ }