@embedpdf/core-acrojs 3.0.0-next.1 → 3.0.0-next.11

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/index.d.cts CHANGED
@@ -1,4 +1,4 @@
1
- import { FormEffect, FormFieldDisplay, FormFieldFamily, FormFieldRef, FormSnapshot, PdfActionTree } from "@embedpdf/engine-core/runtime";
1
+ import { AnnotationRef, DocumentHandle, FormEffect, FormFieldDisplay, FormFieldFamily, FormFieldRef, FormSnapshot, PdfActionTree } from "@embedpdf/engine-core/runtime";
2
2
  //#region src/actions.d.ts
3
3
  /**
4
4
  * Return executable JavaScript in PDF action order (root, then `/Next`
@@ -50,6 +50,15 @@ interface ScriptEnvironment {
50
50
  type ScriptEventKind = 'name-tree-boot' | 'widget-activate' | 'field-keystroke' | 'field-validate' | 'field-calculate' | 'field-format';
51
51
  interface ScriptEventInput {
52
52
  kind: ScriptEventKind;
53
+ /**
54
+ * Explicit Acrobat `event.type` / `event.name` overrides for action-driven
55
+ * runs (built from the dispatcher's trigger provenance — `Field` × `Mouse
56
+ * Enter`, `Page` × `Open`, …; the `Annot` type is an EmbedPDF EXTENSION,
57
+ * Acrobat has no event type for plain-annotation events). When omitted the
58
+ * prelude derives them from `kind` (the K/V/C/F pipeline path).
59
+ */
60
+ type?: string;
61
+ name?: string;
53
62
  target?: FormFieldRef;
54
63
  source?: FormFieldRef;
55
64
  value?: ScriptValue;
@@ -60,12 +69,95 @@ interface ScriptEventInput {
60
69
  modifier?: boolean;
61
70
  shift?: boolean;
62
71
  }
72
+ /**
73
+ * An Acrobat color: `['T']` transparent, `['G', g]`, `['RGB', r, g, b]`,
74
+ * `['CMYK', c, m, y, k]` — components 0..1. The wire format scripts read and
75
+ * write; conversion to renderer/engine colors happens host-side (color.ts).
76
+ */
77
+ type ScriptColorArray = ['T'] | ['G', number] | ['RGB', number, number, number] | ['CMYK', number, number, number, number];
78
+ /**
79
+ * One script-addressable annotation in the prefetched world — every subtype
80
+ * EXCEPT link and widget (Acrobat serves those through `Link`/`Field`
81
+ * objects; here they are separate event planes). Curated read surface only —
82
+ * never a raw dictionary.
83
+ */
84
+ interface ScriptAnnotInput {
85
+ ref: AnnotationRef;
86
+ /** `/NM` — the `getAnnot(nPage, name)` key. Empty when the PDF has none. */
87
+ name: string;
88
+ /** The engine subtype (e.g. `'square'`). */
89
+ subtype: string;
90
+ /** Zero-based page index (Acrobat's `page`). */
91
+ page: number;
92
+ /** PDF-space `[llx, lly, urx, ury]`. */
93
+ rect: [number, number, number, number];
94
+ contents: string;
95
+ /** `/T` author and `/Subj` — read-only in v1 (collab identity stamping). */
96
+ author: string;
97
+ subject: string;
98
+ strokeColor: ScriptColorArray;
99
+ fillColor: ScriptColorArray;
100
+ opacity: number;
101
+ /** `/BS /W` border width in points. */
102
+ width: number;
103
+ /** Border style: `'S'` solid or `'D'` dashed. */
104
+ borderStyle: 'S' | 'D';
105
+ dash: number[];
106
+ hidden: boolean;
107
+ print: boolean;
108
+ readOnly: boolean;
109
+ locked: boolean;
110
+ noView: boolean;
111
+ toggleNoView: boolean;
112
+ /** True for kinds whose appearance cannot be re-derived from properties
113
+ * (stamps, images): appearance writes are refused with a diagnostic. */
114
+ opaqueBody: boolean;
115
+ }
116
+ /** The curated WRITE patch one script staged for one annotation — a
117
+ * canonical per-annot diff (last-write-wins per key, derived at run end
118
+ * exactly like form effects). Visibility keys ride `flags` so the commit
119
+ * sink maps them onto ONE engine flags patch. */
120
+ interface ScriptAnnotEffect {
121
+ ref: AnnotationRef;
122
+ patch: {
123
+ strokeColor?: ScriptColorArray;
124
+ fillColor?: ScriptColorArray;
125
+ opacity?: number;
126
+ width?: number;
127
+ borderStyle?: 'S' | 'D';
128
+ dash?: number[];
129
+ rect?: [number, number, number, number];
130
+ contents?: string;
131
+ flags?: Partial<{
132
+ hidden: boolean;
133
+ print: boolean;
134
+ readOnly: boolean;
135
+ locked: boolean;
136
+ noView: boolean;
137
+ toggleNoView: boolean;
138
+ }>;
139
+ };
140
+ }
141
+ /**
142
+ * The writable-property validity matrix, keyed by engine subtype — the ONE
143
+ * exported table (the prelude inlines an identical copy; a parity test pins
144
+ * them together, and plugin-annotation drift-guards this against the kind
145
+ * registry's PropSpecs). Flags + contents are writable everywhere
146
+ * script-addressable; appearance keys vary by kind.
147
+ */
148
+ declare const ANNOT_WRITABLE_KEYS: Readonly<Record<string, readonly string[]>>;
63
149
  /** Complete input for one deterministic run. No ambient host values are read. */
64
150
  interface ScriptInput {
65
151
  document: ScriptDocumentInput;
66
152
  identity: ScriptIdentity;
67
153
  environment: ScriptEnvironment;
68
154
  fields: ScriptFieldInput[];
155
+ /** The prefetched annots plane (page-scoped — see the D6 deviation). */
156
+ annots?: ScriptAnnotInput[];
157
+ /** Zero-based page indexes the plane covers. */
158
+ annotPages?: number[];
159
+ /** True when annotPages spans the whole document (no scope diagnostic). */
160
+ annotsCoverDocument?: boolean;
69
161
  event: ScriptEventInput;
70
162
  }
71
163
  type ScriptUiEffect = {
@@ -78,12 +170,36 @@ type ScriptUiEffect = {
78
170
  } | {
79
171
  kind: 'gotoPage';
80
172
  page: number;
173
+ } |
174
+ /** `doc.submitForm(...)` — a submit INTENT, resolved and sink-routed
175
+ * outside the VM (never a network call from here). `fieldNames` are
176
+ * include-mode (Acrobat's aFields); `null` = the whole eligible form. */
177
+ {
178
+ kind: 'submitForm';
179
+ url: string | null;
180
+ fieldNames: string[] | null;
181
+ includeEmpty: boolean;
182
+ format?: 'fdf' | 'html' | 'xfdf' | 'pdf';
183
+ method?: 'post' | 'get';
81
184
  };
82
- type ScriptDiagnosticCode = 'blocked-network' | 'unsupported-api' | 'invalid-field-value' | 'script-error';
185
+ type ScriptDiagnosticCode = 'blocked-network' | 'unsupported-api' | 'invalid-field-value' | 'script-error' | 'ui-effect-suppressed';
83
186
  interface ScriptDiagnostic {
84
187
  code: ScriptDiagnosticCode;
85
188
  message: string;
86
189
  }
190
+ /** One isolated, stateful Acrobat-JavaScript realm for one PDF document. */
191
+ interface ScriptSandbox {
192
+ /** True after explicit disposal or a resource/runtime fault. */
193
+ readonly disposed: boolean;
194
+ /** Evaluate document name-tree sources once. Top-level effects are returned
195
+ * so the orchestrator can include them in the first transaction. */
196
+ boot(sources: string[], input: ScriptInput, budget?: ScriptBudget): ScriptOutput;
197
+ /** Run one event program against the realm's persistent globals. */
198
+ run(source: string, input: ScriptInput, budget?: ScriptBudget): ScriptOutput;
199
+ /** Release the realm. Idempotent. */
200
+ dispose(): void;
201
+ }
202
+ type ScriptSandboxFactory = () => Promise<ScriptSandbox>;
87
203
  interface ScriptExecutionError {
88
204
  kind: 'exception' | 'budget' | 'invalid-output';
89
205
  message: string;
@@ -96,10 +212,16 @@ interface ScriptEventOutput {
96
212
  selStart: number;
97
213
  selEnd: number;
98
214
  }
99
- /** Effects are committed only by the originating client's orchestrator. */
215
+ /**
216
+ * Effects are committed only by the originating client's orchestrator, in
217
+ * the DECLARED cross-plane order: `formEffects` first (field order — matching
218
+ * the derive-by-diff model), then `annotEffects` (annot order); the first
219
+ * failing effect marks every later effect in BOTH streams skipped.
220
+ */
100
221
  interface ScriptOutput {
101
222
  event: ScriptEventOutput;
102
223
  formEffects: FormEffect[];
224
+ annotEffects: ScriptAnnotEffect[];
103
225
  uiEffects: ScriptUiEffect[];
104
226
  diagnostics: ScriptDiagnostic[];
105
227
  error?: ScriptExecutionError;
@@ -112,19 +234,29 @@ interface ScriptBudget {
112
234
  maxOutputBytes: number;
113
235
  }
114
236
  declare const DEFAULT_SCRIPT_BUDGET: Readonly<ScriptBudget>;
115
- /** V1 security posture. The only configurable switch is explicit opt-in. */
237
+ /**
238
+ * The shipped security posture (updated per phase — the live authority for
239
+ * per-type × origin decisions is the actions plugin's policy; these
240
+ * constants DOCUMENT the posture, they do not enforce it). The only
241
+ * configurable switch is explicit opt-in.
242
+ */
116
243
  interface ScriptSecurityPolicy {
117
244
  enabled: boolean;
118
245
  executionOwner: 'originating-client-only';
119
246
  nameTreeBoot: 'lazy-first-transaction';
120
- submitForm: 'blocked';
121
- openAction: 'preserve-only';
122
- pageActions: 'preserve-only';
123
- catalogLifecycleActions: 'preserve-only';
124
- annotationActions: 'widget-activate-only';
247
+ /** Submit is a sink chain — embedder handler → the document's HOME
248
+ * (`doc.forms.submit`, engine-asserted) → blocked. Never auto-network. */
249
+ submitForm: 'sink-chain';
250
+ openAction: 'execute-lifecycle';
251
+ pageActions: 'execute-lifecycle';
252
+ /** WC/WS/DS/WP/DP run when the VERB OWNER dispatches them. */
253
+ catalogLifecycleActions: 'execute-on-verb';
254
+ annotationActions: 'execute-full-matrix';
125
255
  }
126
256
  declare const DEFAULT_SCRIPT_SECURITY_POLICY: Readonly<ScriptSecurityPolicy>;
127
- /** Frozen V1 dispatch matrix; extracted actions outside it remain data only. */
257
+ /** The shipped dispatch matrix; extracted actions outside it remain data
258
+ * only. (Historical note: v1 froze everything beyond K/V/C/F as
259
+ * preserve-only; phases 1–4 executed the rest.) */
128
260
  declare const SCRIPT_EVENT_MATRIX: Readonly<{
129
261
  readonly nameTree: "lazy-first-originating-field-transaction";
130
262
  readonly field: Readonly<{
@@ -133,14 +265,14 @@ declare const SCRIPT_EVENT_MATRIX: Readonly<{
133
265
  calculate: "execute-in-calculation-order";
134
266
  format: "execute-after-value-calculation";
135
267
  }>;
136
- readonly openAction: "preserve-only";
137
- readonly page: "preserve-only";
138
- readonly catalogLifecycle: "preserve-only";
268
+ readonly openAction: "execute-lifecycle";
269
+ readonly page: "execute-lifecycle";
270
+ readonly catalogLifecycle: "execute-on-verb";
139
271
  readonly annotation: Readonly<{
140
272
  widgetActivate: "execute-on-originating-client";
141
- other: "preserve-only";
273
+ other: "execute-full-matrix";
142
274
  }>;
143
- readonly submitForm: "blocked";
275
+ readonly submitForm: "sink-chain";
144
276
  }>;
145
277
  /** Functions installed into the isolated VM global by `PRELUDE_SOURCE`. */
146
278
  interface AcroJsVmGlobal {
@@ -148,6 +280,99 @@ interface AcroJsVmGlobal {
148
280
  __acrojsRun(source: string, input: ScriptInput, budget?: Pick<ScriptBudget, 'maxEffects'>): ScriptOutput;
149
281
  }
150
282
  //#endregion
283
+ //#region src/color.d.ts
284
+ /**
285
+ * Host-side Acrobat color-array conversions — the commit sinks and world
286
+ * builders cross the Acrobat-array ↔ renderer-color boundary through these.
287
+ * The PRELUDE inlines its own identical formulas (it must stay
288
+ * self-contained); `prelude.test.ts` pins the two implementations together.
289
+ *
290
+ * Conversion vectors (the documented Acrobat semantics):
291
+ * G → RGB: replicate the gray component.
292
+ * CMYK → RGB: component = 1 − min(1, channel + k).
293
+ * RGB → G: luminosity 0.3r + 0.59g + 0.11b.
294
+ * RGB → CMYK: k = 1 − max(r,g,b); channels = 1 − component − k.
295
+ * T (transparent) converts to itself only.
296
+ */
297
+ declare function scriptColorToRgb(color: ScriptColorArray): {
298
+ r: number;
299
+ g: number;
300
+ b: number;
301
+ } | null;
302
+ /** Acrobat array → CSS hex, or null for transparent. */
303
+ declare function scriptColorToCss(color: ScriptColorArray): string | null;
304
+ /** CSS hex (#rgb/#rrggbb) → Acrobat RGB array; null/undefined → transparent. */
305
+ declare function cssToScriptColor(css: string | null | undefined): ScriptColorArray;
306
+ /** Structural validation for values scripts assign. */
307
+ declare function isScriptColorArray(value: unknown): value is ScriptColorArray;
308
+ //#endregion
309
+ //#region src/host.d.ts
310
+ /** The per-run world a CALLER supplies (fields snapshot, prefetched annots
311
+ * plane, the event). Document/identity/environment come from the host. */
312
+ interface ScriptWorldInput {
313
+ fields: ScriptFieldInput[];
314
+ annots?: ScriptAnnotInput[];
315
+ annotPages?: number[];
316
+ annotsCoverDocument?: boolean;
317
+ /** Zero-based current page for `this.pageNum` — overrides the host's
318
+ * document input (the form pipeline anchors it on the target field). */
319
+ pageNumber?: number;
320
+ event: ScriptEventInput;
321
+ }
322
+ interface ScriptTransaction {
323
+ /**
324
+ * Run the name-tree boot if it has not run in this realm yet; returns the
325
+ * boot output exactly ONCE (its effects belong to the first transaction —
326
+ * commit them, tag their UI effects `phase: 'boot'`), null thereafter.
327
+ */
328
+ boot(world: ScriptWorldInput, budget?: ScriptBudget): Promise<ScriptOutput | null>;
329
+ /** One deterministic run against the shared realm. Auto-boots defensively
330
+ * (that boot's output is then returned by the next `boot()` call).
331
+ * `budget` overrides the host default per run — the form pipeline slices
332
+ * ONE transaction-wide time budget across its K/V/C/F passes. */
333
+ run(program: string, world: ScriptWorldInput, budget?: ScriptBudget): Promise<ScriptOutput>;
334
+ }
335
+ interface ScriptHostOptions {
336
+ sandboxFactory: ScriptSandboxFactory;
337
+ document: () => ScriptDocumentInput;
338
+ identity: () => ScriptIdentity;
339
+ /** Deterministic environment per run; `sequence` is the host's monotonic
340
+ * run counter (seed derivation — see {@link seedFrom}). */
341
+ environment: (sequence: number) => ScriptEnvironment;
342
+ /** Name-tree programs, fetched lazily once per realm build. */
343
+ bootSources: () => Promise<string[]>;
344
+ budget?: ScriptBudget;
345
+ }
346
+ /**
347
+ * The ONE realm per document (umbrella law #5): a name-tree function must be
348
+ * callable from a page-open script and a field calculate alike.
349
+ *
350
+ * `transaction(body)` is the realm mutex, and the body performs EVERYTHING
351
+ * for one logical script transaction — world prefetch, VM run(s), document
352
+ * commits through the owner sinks, model reconciliation — BEFORE the mutex
353
+ * releases, so the next transaction always prefetches post-commit truth
354
+ * (the commit-inside-the-boundary law). Lock hierarchy: caller queues
355
+ * (actions dispatch / form mutation) acquire this queue, never the reverse,
356
+ * and commit sinks called inside the body never re-enter it.
357
+ *
358
+ * Fault ladder: a sandbox that reports itself disposed (interrupt/memory
359
+ * faults) poisons the realm for the REST of the current transaction; the
360
+ * next transaction rebuilds it lazily and re-runs the boot. Boot errors
361
+ * degrade (diagnose, continue) — they never brick scripting.
362
+ */
363
+ interface ScriptHost {
364
+ transaction<T>(body: (txn: ScriptTransaction) => Promise<T>): Promise<T>;
365
+ dispose(): void;
366
+ }
367
+ /** FNV-1a over `documentId:sequence` — the deterministic default random seed
368
+ * (ported verbatim from the form controller; exported for callers building
369
+ * `ScriptHostOptions.environment`). */
370
+ declare function seedFrom(documentId: string, sequence: number): number;
371
+ /** Engine JWT/session identity composed under embedder overrides — the
372
+ * standard `ScriptHostOptions.identity` builder. */
373
+ declare function resolveScriptIdentity(doc: DocumentHandle, overrides?: Partial<ScriptIdentity> | (() => Partial<ScriptIdentity>)): ScriptIdentity;
374
+ declare function createScriptHost(options: ScriptHostOptions): ScriptHost;
375
+ //#endregion
151
376
  //#region src/input.d.ts
152
377
  /** Build the VM's detached field view from the engine's lossless snapshot. */
153
378
  declare function scriptFieldsFromSnapshot(snapshot: FormSnapshot): ScriptFieldInput[];
@@ -164,5 +389,5 @@ declare function installAcroJs(g: Record<string, unknown>): void;
164
389
  /** The exact self-contained source evaluated in Node parity tests and QuickJS. */
165
390
  declare const PRELUDE_SOURCE: string;
166
391
  //#endregion
167
- export { type AcroJsVmGlobal, DEFAULT_SCRIPT_BUDGET, DEFAULT_SCRIPT_SECURITY_POLICY, PRELUDE_SOURCE, SCRIPT_EVENT_MATRIX, type ScriptBudget, type ScriptDiagnostic, type ScriptDiagnosticCode, type ScriptDocumentInput, type ScriptEnvironment, type ScriptEventInput, type ScriptEventKind, type ScriptEventOutput, type ScriptExecutionError, type ScriptFieldInput, type ScriptFieldOption, type ScriptIdentity, type ScriptInput, type ScriptOutput, type ScriptSecurityPolicy, type ScriptUiEffect, type ScriptValue, installAcroJs, javaScriptProgramFromActionTree, javaScriptSourcesFromActionTree, scriptFieldsFromSnapshot };
392
+ export { ANNOT_WRITABLE_KEYS, type AcroJsVmGlobal, DEFAULT_SCRIPT_BUDGET, DEFAULT_SCRIPT_SECURITY_POLICY, PRELUDE_SOURCE, SCRIPT_EVENT_MATRIX, type ScriptAnnotEffect, type ScriptAnnotInput, type ScriptBudget, type ScriptColorArray, type ScriptDiagnostic, type ScriptDiagnosticCode, type ScriptDocumentInput, type ScriptEnvironment, type ScriptEventInput, type ScriptEventKind, type ScriptEventOutput, type ScriptExecutionError, type ScriptFieldInput, type ScriptFieldOption, type ScriptHost, type ScriptHostOptions, type ScriptIdentity, type ScriptInput, type ScriptOutput, type ScriptSandbox, type ScriptSandboxFactory, type ScriptSecurityPolicy, type ScriptTransaction, type ScriptUiEffect, type ScriptValue, type ScriptWorldInput, createScriptHost, cssToScriptColor, installAcroJs, isScriptColorArray, javaScriptProgramFromActionTree, javaScriptSourcesFromActionTree, resolveScriptIdentity, scriptColorToCss, scriptColorToRgb, scriptFieldsFromSnapshot, seedFrom };
168
393
  //# sourceMappingURL=index.d.cts.map
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { FormEffect, FormFieldDisplay, FormFieldFamily, FormFieldRef, FormSnapshot, PdfActionTree } from "@embedpdf/engine-core/runtime";
1
+ import { AnnotationRef, DocumentHandle, FormEffect, FormFieldDisplay, FormFieldFamily, FormFieldRef, FormSnapshot, PdfActionTree } from "@embedpdf/engine-core/runtime";
2
2
  //#region src/actions.d.ts
3
3
  /**
4
4
  * Return executable JavaScript in PDF action order (root, then `/Next`
@@ -50,6 +50,15 @@ interface ScriptEnvironment {
50
50
  type ScriptEventKind = 'name-tree-boot' | 'widget-activate' | 'field-keystroke' | 'field-validate' | 'field-calculate' | 'field-format';
51
51
  interface ScriptEventInput {
52
52
  kind: ScriptEventKind;
53
+ /**
54
+ * Explicit Acrobat `event.type` / `event.name` overrides for action-driven
55
+ * runs (built from the dispatcher's trigger provenance — `Field` × `Mouse
56
+ * Enter`, `Page` × `Open`, …; the `Annot` type is an EmbedPDF EXTENSION,
57
+ * Acrobat has no event type for plain-annotation events). When omitted the
58
+ * prelude derives them from `kind` (the K/V/C/F pipeline path).
59
+ */
60
+ type?: string;
61
+ name?: string;
53
62
  target?: FormFieldRef;
54
63
  source?: FormFieldRef;
55
64
  value?: ScriptValue;
@@ -60,12 +69,95 @@ interface ScriptEventInput {
60
69
  modifier?: boolean;
61
70
  shift?: boolean;
62
71
  }
72
+ /**
73
+ * An Acrobat color: `['T']` transparent, `['G', g]`, `['RGB', r, g, b]`,
74
+ * `['CMYK', c, m, y, k]` — components 0..1. The wire format scripts read and
75
+ * write; conversion to renderer/engine colors happens host-side (color.ts).
76
+ */
77
+ type ScriptColorArray = ['T'] | ['G', number] | ['RGB', number, number, number] | ['CMYK', number, number, number, number];
78
+ /**
79
+ * One script-addressable annotation in the prefetched world — every subtype
80
+ * EXCEPT link and widget (Acrobat serves those through `Link`/`Field`
81
+ * objects; here they are separate event planes). Curated read surface only —
82
+ * never a raw dictionary.
83
+ */
84
+ interface ScriptAnnotInput {
85
+ ref: AnnotationRef;
86
+ /** `/NM` — the `getAnnot(nPage, name)` key. Empty when the PDF has none. */
87
+ name: string;
88
+ /** The engine subtype (e.g. `'square'`). */
89
+ subtype: string;
90
+ /** Zero-based page index (Acrobat's `page`). */
91
+ page: number;
92
+ /** PDF-space `[llx, lly, urx, ury]`. */
93
+ rect: [number, number, number, number];
94
+ contents: string;
95
+ /** `/T` author and `/Subj` — read-only in v1 (collab identity stamping). */
96
+ author: string;
97
+ subject: string;
98
+ strokeColor: ScriptColorArray;
99
+ fillColor: ScriptColorArray;
100
+ opacity: number;
101
+ /** `/BS /W` border width in points. */
102
+ width: number;
103
+ /** Border style: `'S'` solid or `'D'` dashed. */
104
+ borderStyle: 'S' | 'D';
105
+ dash: number[];
106
+ hidden: boolean;
107
+ print: boolean;
108
+ readOnly: boolean;
109
+ locked: boolean;
110
+ noView: boolean;
111
+ toggleNoView: boolean;
112
+ /** True for kinds whose appearance cannot be re-derived from properties
113
+ * (stamps, images): appearance writes are refused with a diagnostic. */
114
+ opaqueBody: boolean;
115
+ }
116
+ /** The curated WRITE patch one script staged for one annotation — a
117
+ * canonical per-annot diff (last-write-wins per key, derived at run end
118
+ * exactly like form effects). Visibility keys ride `flags` so the commit
119
+ * sink maps them onto ONE engine flags patch. */
120
+ interface ScriptAnnotEffect {
121
+ ref: AnnotationRef;
122
+ patch: {
123
+ strokeColor?: ScriptColorArray;
124
+ fillColor?: ScriptColorArray;
125
+ opacity?: number;
126
+ width?: number;
127
+ borderStyle?: 'S' | 'D';
128
+ dash?: number[];
129
+ rect?: [number, number, number, number];
130
+ contents?: string;
131
+ flags?: Partial<{
132
+ hidden: boolean;
133
+ print: boolean;
134
+ readOnly: boolean;
135
+ locked: boolean;
136
+ noView: boolean;
137
+ toggleNoView: boolean;
138
+ }>;
139
+ };
140
+ }
141
+ /**
142
+ * The writable-property validity matrix, keyed by engine subtype — the ONE
143
+ * exported table (the prelude inlines an identical copy; a parity test pins
144
+ * them together, and plugin-annotation drift-guards this against the kind
145
+ * registry's PropSpecs). Flags + contents are writable everywhere
146
+ * script-addressable; appearance keys vary by kind.
147
+ */
148
+ declare const ANNOT_WRITABLE_KEYS: Readonly<Record<string, readonly string[]>>;
63
149
  /** Complete input for one deterministic run. No ambient host values are read. */
64
150
  interface ScriptInput {
65
151
  document: ScriptDocumentInput;
66
152
  identity: ScriptIdentity;
67
153
  environment: ScriptEnvironment;
68
154
  fields: ScriptFieldInput[];
155
+ /** The prefetched annots plane (page-scoped — see the D6 deviation). */
156
+ annots?: ScriptAnnotInput[];
157
+ /** Zero-based page indexes the plane covers. */
158
+ annotPages?: number[];
159
+ /** True when annotPages spans the whole document (no scope diagnostic). */
160
+ annotsCoverDocument?: boolean;
69
161
  event: ScriptEventInput;
70
162
  }
71
163
  type ScriptUiEffect = {
@@ -78,12 +170,36 @@ type ScriptUiEffect = {
78
170
  } | {
79
171
  kind: 'gotoPage';
80
172
  page: number;
173
+ } |
174
+ /** `doc.submitForm(...)` — a submit INTENT, resolved and sink-routed
175
+ * outside the VM (never a network call from here). `fieldNames` are
176
+ * include-mode (Acrobat's aFields); `null` = the whole eligible form. */
177
+ {
178
+ kind: 'submitForm';
179
+ url: string | null;
180
+ fieldNames: string[] | null;
181
+ includeEmpty: boolean;
182
+ format?: 'fdf' | 'html' | 'xfdf' | 'pdf';
183
+ method?: 'post' | 'get';
81
184
  };
82
- type ScriptDiagnosticCode = 'blocked-network' | 'unsupported-api' | 'invalid-field-value' | 'script-error';
185
+ type ScriptDiagnosticCode = 'blocked-network' | 'unsupported-api' | 'invalid-field-value' | 'script-error' | 'ui-effect-suppressed';
83
186
  interface ScriptDiagnostic {
84
187
  code: ScriptDiagnosticCode;
85
188
  message: string;
86
189
  }
190
+ /** One isolated, stateful Acrobat-JavaScript realm for one PDF document. */
191
+ interface ScriptSandbox {
192
+ /** True after explicit disposal or a resource/runtime fault. */
193
+ readonly disposed: boolean;
194
+ /** Evaluate document name-tree sources once. Top-level effects are returned
195
+ * so the orchestrator can include them in the first transaction. */
196
+ boot(sources: string[], input: ScriptInput, budget?: ScriptBudget): ScriptOutput;
197
+ /** Run one event program against the realm's persistent globals. */
198
+ run(source: string, input: ScriptInput, budget?: ScriptBudget): ScriptOutput;
199
+ /** Release the realm. Idempotent. */
200
+ dispose(): void;
201
+ }
202
+ type ScriptSandboxFactory = () => Promise<ScriptSandbox>;
87
203
  interface ScriptExecutionError {
88
204
  kind: 'exception' | 'budget' | 'invalid-output';
89
205
  message: string;
@@ -96,10 +212,16 @@ interface ScriptEventOutput {
96
212
  selStart: number;
97
213
  selEnd: number;
98
214
  }
99
- /** Effects are committed only by the originating client's orchestrator. */
215
+ /**
216
+ * Effects are committed only by the originating client's orchestrator, in
217
+ * the DECLARED cross-plane order: `formEffects` first (field order — matching
218
+ * the derive-by-diff model), then `annotEffects` (annot order); the first
219
+ * failing effect marks every later effect in BOTH streams skipped.
220
+ */
100
221
  interface ScriptOutput {
101
222
  event: ScriptEventOutput;
102
223
  formEffects: FormEffect[];
224
+ annotEffects: ScriptAnnotEffect[];
103
225
  uiEffects: ScriptUiEffect[];
104
226
  diagnostics: ScriptDiagnostic[];
105
227
  error?: ScriptExecutionError;
@@ -112,19 +234,29 @@ interface ScriptBudget {
112
234
  maxOutputBytes: number;
113
235
  }
114
236
  declare const DEFAULT_SCRIPT_BUDGET: Readonly<ScriptBudget>;
115
- /** V1 security posture. The only configurable switch is explicit opt-in. */
237
+ /**
238
+ * The shipped security posture (updated per phase — the live authority for
239
+ * per-type × origin decisions is the actions plugin's policy; these
240
+ * constants DOCUMENT the posture, they do not enforce it). The only
241
+ * configurable switch is explicit opt-in.
242
+ */
116
243
  interface ScriptSecurityPolicy {
117
244
  enabled: boolean;
118
245
  executionOwner: 'originating-client-only';
119
246
  nameTreeBoot: 'lazy-first-transaction';
120
- submitForm: 'blocked';
121
- openAction: 'preserve-only';
122
- pageActions: 'preserve-only';
123
- catalogLifecycleActions: 'preserve-only';
124
- annotationActions: 'widget-activate-only';
247
+ /** Submit is a sink chain — embedder handler → the document's HOME
248
+ * (`doc.forms.submit`, engine-asserted) → blocked. Never auto-network. */
249
+ submitForm: 'sink-chain';
250
+ openAction: 'execute-lifecycle';
251
+ pageActions: 'execute-lifecycle';
252
+ /** WC/WS/DS/WP/DP run when the VERB OWNER dispatches them. */
253
+ catalogLifecycleActions: 'execute-on-verb';
254
+ annotationActions: 'execute-full-matrix';
125
255
  }
126
256
  declare const DEFAULT_SCRIPT_SECURITY_POLICY: Readonly<ScriptSecurityPolicy>;
127
- /** Frozen V1 dispatch matrix; extracted actions outside it remain data only. */
257
+ /** The shipped dispatch matrix; extracted actions outside it remain data
258
+ * only. (Historical note: v1 froze everything beyond K/V/C/F as
259
+ * preserve-only; phases 1–4 executed the rest.) */
128
260
  declare const SCRIPT_EVENT_MATRIX: Readonly<{
129
261
  readonly nameTree: "lazy-first-originating-field-transaction";
130
262
  readonly field: Readonly<{
@@ -133,14 +265,14 @@ declare const SCRIPT_EVENT_MATRIX: Readonly<{
133
265
  calculate: "execute-in-calculation-order";
134
266
  format: "execute-after-value-calculation";
135
267
  }>;
136
- readonly openAction: "preserve-only";
137
- readonly page: "preserve-only";
138
- readonly catalogLifecycle: "preserve-only";
268
+ readonly openAction: "execute-lifecycle";
269
+ readonly page: "execute-lifecycle";
270
+ readonly catalogLifecycle: "execute-on-verb";
139
271
  readonly annotation: Readonly<{
140
272
  widgetActivate: "execute-on-originating-client";
141
- other: "preserve-only";
273
+ other: "execute-full-matrix";
142
274
  }>;
143
- readonly submitForm: "blocked";
275
+ readonly submitForm: "sink-chain";
144
276
  }>;
145
277
  /** Functions installed into the isolated VM global by `PRELUDE_SOURCE`. */
146
278
  interface AcroJsVmGlobal {
@@ -148,6 +280,99 @@ interface AcroJsVmGlobal {
148
280
  __acrojsRun(source: string, input: ScriptInput, budget?: Pick<ScriptBudget, 'maxEffects'>): ScriptOutput;
149
281
  }
150
282
  //#endregion
283
+ //#region src/color.d.ts
284
+ /**
285
+ * Host-side Acrobat color-array conversions — the commit sinks and world
286
+ * builders cross the Acrobat-array ↔ renderer-color boundary through these.
287
+ * The PRELUDE inlines its own identical formulas (it must stay
288
+ * self-contained); `prelude.test.ts` pins the two implementations together.
289
+ *
290
+ * Conversion vectors (the documented Acrobat semantics):
291
+ * G → RGB: replicate the gray component.
292
+ * CMYK → RGB: component = 1 − min(1, channel + k).
293
+ * RGB → G: luminosity 0.3r + 0.59g + 0.11b.
294
+ * RGB → CMYK: k = 1 − max(r,g,b); channels = 1 − component − k.
295
+ * T (transparent) converts to itself only.
296
+ */
297
+ declare function scriptColorToRgb(color: ScriptColorArray): {
298
+ r: number;
299
+ g: number;
300
+ b: number;
301
+ } | null;
302
+ /** Acrobat array → CSS hex, or null for transparent. */
303
+ declare function scriptColorToCss(color: ScriptColorArray): string | null;
304
+ /** CSS hex (#rgb/#rrggbb) → Acrobat RGB array; null/undefined → transparent. */
305
+ declare function cssToScriptColor(css: string | null | undefined): ScriptColorArray;
306
+ /** Structural validation for values scripts assign. */
307
+ declare function isScriptColorArray(value: unknown): value is ScriptColorArray;
308
+ //#endregion
309
+ //#region src/host.d.ts
310
+ /** The per-run world a CALLER supplies (fields snapshot, prefetched annots
311
+ * plane, the event). Document/identity/environment come from the host. */
312
+ interface ScriptWorldInput {
313
+ fields: ScriptFieldInput[];
314
+ annots?: ScriptAnnotInput[];
315
+ annotPages?: number[];
316
+ annotsCoverDocument?: boolean;
317
+ /** Zero-based current page for `this.pageNum` — overrides the host's
318
+ * document input (the form pipeline anchors it on the target field). */
319
+ pageNumber?: number;
320
+ event: ScriptEventInput;
321
+ }
322
+ interface ScriptTransaction {
323
+ /**
324
+ * Run the name-tree boot if it has not run in this realm yet; returns the
325
+ * boot output exactly ONCE (its effects belong to the first transaction —
326
+ * commit them, tag their UI effects `phase: 'boot'`), null thereafter.
327
+ */
328
+ boot(world: ScriptWorldInput, budget?: ScriptBudget): Promise<ScriptOutput | null>;
329
+ /** One deterministic run against the shared realm. Auto-boots defensively
330
+ * (that boot's output is then returned by the next `boot()` call).
331
+ * `budget` overrides the host default per run — the form pipeline slices
332
+ * ONE transaction-wide time budget across its K/V/C/F passes. */
333
+ run(program: string, world: ScriptWorldInput, budget?: ScriptBudget): Promise<ScriptOutput>;
334
+ }
335
+ interface ScriptHostOptions {
336
+ sandboxFactory: ScriptSandboxFactory;
337
+ document: () => ScriptDocumentInput;
338
+ identity: () => ScriptIdentity;
339
+ /** Deterministic environment per run; `sequence` is the host's monotonic
340
+ * run counter (seed derivation — see {@link seedFrom}). */
341
+ environment: (sequence: number) => ScriptEnvironment;
342
+ /** Name-tree programs, fetched lazily once per realm build. */
343
+ bootSources: () => Promise<string[]>;
344
+ budget?: ScriptBudget;
345
+ }
346
+ /**
347
+ * The ONE realm per document (umbrella law #5): a name-tree function must be
348
+ * callable from a page-open script and a field calculate alike.
349
+ *
350
+ * `transaction(body)` is the realm mutex, and the body performs EVERYTHING
351
+ * for one logical script transaction — world prefetch, VM run(s), document
352
+ * commits through the owner sinks, model reconciliation — BEFORE the mutex
353
+ * releases, so the next transaction always prefetches post-commit truth
354
+ * (the commit-inside-the-boundary law). Lock hierarchy: caller queues
355
+ * (actions dispatch / form mutation) acquire this queue, never the reverse,
356
+ * and commit sinks called inside the body never re-enter it.
357
+ *
358
+ * Fault ladder: a sandbox that reports itself disposed (interrupt/memory
359
+ * faults) poisons the realm for the REST of the current transaction; the
360
+ * next transaction rebuilds it lazily and re-runs the boot. Boot errors
361
+ * degrade (diagnose, continue) — they never brick scripting.
362
+ */
363
+ interface ScriptHost {
364
+ transaction<T>(body: (txn: ScriptTransaction) => Promise<T>): Promise<T>;
365
+ dispose(): void;
366
+ }
367
+ /** FNV-1a over `documentId:sequence` — the deterministic default random seed
368
+ * (ported verbatim from the form controller; exported for callers building
369
+ * `ScriptHostOptions.environment`). */
370
+ declare function seedFrom(documentId: string, sequence: number): number;
371
+ /** Engine JWT/session identity composed under embedder overrides — the
372
+ * standard `ScriptHostOptions.identity` builder. */
373
+ declare function resolveScriptIdentity(doc: DocumentHandle, overrides?: Partial<ScriptIdentity> | (() => Partial<ScriptIdentity>)): ScriptIdentity;
374
+ declare function createScriptHost(options: ScriptHostOptions): ScriptHost;
375
+ //#endregion
151
376
  //#region src/input.d.ts
152
377
  /** Build the VM's detached field view from the engine's lossless snapshot. */
153
378
  declare function scriptFieldsFromSnapshot(snapshot: FormSnapshot): ScriptFieldInput[];
@@ -164,5 +389,5 @@ declare function installAcroJs(g: Record<string, unknown>): void;
164
389
  /** The exact self-contained source evaluated in Node parity tests and QuickJS. */
165
390
  declare const PRELUDE_SOURCE: string;
166
391
  //#endregion
167
- export { type AcroJsVmGlobal, DEFAULT_SCRIPT_BUDGET, DEFAULT_SCRIPT_SECURITY_POLICY, PRELUDE_SOURCE, SCRIPT_EVENT_MATRIX, type ScriptBudget, type ScriptDiagnostic, type ScriptDiagnosticCode, type ScriptDocumentInput, type ScriptEnvironment, type ScriptEventInput, type ScriptEventKind, type ScriptEventOutput, type ScriptExecutionError, type ScriptFieldInput, type ScriptFieldOption, type ScriptIdentity, type ScriptInput, type ScriptOutput, type ScriptSecurityPolicy, type ScriptUiEffect, type ScriptValue, installAcroJs, javaScriptProgramFromActionTree, javaScriptSourcesFromActionTree, scriptFieldsFromSnapshot };
392
+ export { ANNOT_WRITABLE_KEYS, type AcroJsVmGlobal, DEFAULT_SCRIPT_BUDGET, DEFAULT_SCRIPT_SECURITY_POLICY, PRELUDE_SOURCE, SCRIPT_EVENT_MATRIX, type ScriptAnnotEffect, type ScriptAnnotInput, type ScriptBudget, type ScriptColorArray, type ScriptDiagnostic, type ScriptDiagnosticCode, type ScriptDocumentInput, type ScriptEnvironment, type ScriptEventInput, type ScriptEventKind, type ScriptEventOutput, type ScriptExecutionError, type ScriptFieldInput, type ScriptFieldOption, type ScriptHost, type ScriptHostOptions, type ScriptIdentity, type ScriptInput, type ScriptOutput, type ScriptSandbox, type ScriptSandboxFactory, type ScriptSecurityPolicy, type ScriptTransaction, type ScriptUiEffect, type ScriptValue, type ScriptWorldInput, createScriptHost, cssToScriptColor, installAcroJs, isScriptColorArray, javaScriptProgramFromActionTree, javaScriptSourcesFromActionTree, resolveScriptIdentity, scriptColorToCss, scriptColorToRgb, scriptFieldsFromSnapshot, seedFrom };
168
393
  //# sourceMappingURL=index.d.ts.map