@oomol-lab/open-flow 0.1.0-beta.75 → 0.1.0-beta.77
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 +3 -1
- package/dist/browser/{ContentIcon-FCpKiwjp.js → ContentIcon-VZQO8VZU.js} +9 -6
- package/dist/browser/{FlowCanvas-dzRBnlUT.js → FlowCanvas-BNGDMaWr.js} +75 -63
- package/dist/browser/{createResourceDialog-BeYDdUl-.js → createResourceDialog-BmtakfVg.js} +63 -57
- package/dist/browser/{dialog-ZtpsFbl4.js → dialog-BcFBfRB1.js} +126 -32
- package/dist/browser/{exportSvg-DqXw1yf-.js → exportSvg-CG8hEUNk.js} +2 -2
- package/dist/browser/{flowChanges-b_5UobFj.js → flowChanges-BGo_4Ypo.js} +6063 -11285
- package/dist/browser/{flowWorkspace-ItojZbO4.js → flowWorkspace-BFHGev7s.js} +1065 -2570
- package/dist/browser/preview.css +626 -653
- package/dist/browser/preview.js +1907 -9663
- package/dist/browser/theme.css +117 -263
- package/dist/browser/{tooltip-wZJRB9oP.js → tooltip-BAWSUexx.js} +2 -2
- package/dist/browser/{typeScriptSession-CSRwWmZm.js → typeScriptSession-CRoezJPN.js} +1 -1
- package/dist/browser/ui.css +464 -463
- package/dist/browser/ui.js +4 -3
- package/dist/browser/workbench.css +9891 -9897
- package/dist/browser/workbench.d.ts +6 -2
- package/dist/browser/workbench.js +838 -499
- package/dist/browser/{workbenchSelect-M441Lz0d.js → workbenchSelect-CjK-xdm3.js} +2 -2
- package/dist/command/index.js +48 -50
- package/dist/common/authoring.d.ts +5 -5
- package/dist/common/authoringExamples.d.ts +3 -2
- package/dist/common/authoringSchema.d.ts +26 -4
- package/dist/common/connector-proxy.d.ts +1 -1
- package/dist/common/control-api-conformance.js +352 -144
- package/dist/common/control-api-errors.d.ts +12 -0
- package/dist/common/control-api.d.ts +38 -4
- package/dist/common/control-api.js +373 -162
- package/dist/common/control-requests.d.ts +22 -3
- package/dist/common/control-requests.js +268 -28
- package/dist/common/cron-trigger.d.ts +2 -1
- package/dist/common/decision.d.ts +4 -4
- package/dist/common/decision.js +5 -2
- package/dist/common/engine-contract.d.ts +6 -1
- package/dist/common/event-source-definition.d.ts +1 -1
- package/dist/common/event-source-view.d.ts +22 -0
- package/dist/common/event-source.d.ts +1 -1
- package/dist/common/event-source.js +24 -65
- package/dist/common/event-sources.d.ts +0 -21
- package/dist/common/flow-authoring.js +90 -20
- package/dist/common/flow-change-schema.d.ts +9 -1
- package/dist/common/flow-change.d.ts +8 -202
- package/dist/common/flow-change.js +96 -24
- package/dist/common/flow-encoding.js +89 -21
- package/dist/common/flow-input-value.d.ts +1 -1
- package/dist/common/flow-model.d.ts +121 -0
- package/dist/common/flow-notifications.d.ts +1 -1
- package/dist/common/flow-retry.d.ts +2 -4
- package/dist/common/flow-semantics.js +161 -80
- package/dist/common/flow-state.d.ts +123 -0
- package/dist/common/flow-state.js +5852 -0
- package/dist/common/flow-workflowReferences.d.ts +8 -0
- package/dist/common/flowInspection.d.ts +1 -1
- package/dist/common/http-hosts.d.ts +6 -0
- package/dist/common/http-request.d.ts +13 -5
- package/dist/common/http-request.js +23 -5
- package/dist/common/integration-trigger.d.ts +2 -1
- package/dist/common/mcp.d.ts +96 -3
- package/dist/common/mcp.js +355 -142
- package/dist/common/openapi.d.ts +4 -4
- package/dist/common/openapi.js +4 -1
- package/dist/common/poll-trigger.d.ts +2 -1
- package/dist/common/run-events.js +1 -0
- package/dist/common/runtime-contract.d.ts +37 -1
- package/dist/common/runtime-contract.js +717 -72
- package/dist/common/runtime-nodejs-compat.d.ts +44 -0
- package/dist/common/runtime-nodejs-compat.js +5870 -0
- package/dist/common/scheduler-checkpoint.d.ts +1 -1
- package/dist/common/scheduler-node-execution.d.ts +2 -1
- package/dist/common/scheduler.d.ts +2 -2
- package/dist/common/scheduler.js +76 -6
- package/dist/common/state-conformance.d.ts +16 -0
- package/dist/common/tags.d.ts +4 -0
- package/dist/common/trigger-catalog.d.ts +1 -7
- package/dist/common/trigger-config-options.d.ts +1 -1
- package/dist/common/trigger-config.d.ts +1 -1
- package/dist/common/trigger-contract.d.ts +2 -1
- package/dist/common/trigger-localization.d.ts +8 -2
- package/dist/common/trigger-model.d.ts +101 -0
- package/dist/common/webhook-response.d.ts +1 -1
- package/dist/common/webhook-trigger.d.ts +3 -1
- package/dist/common/workflow.d.ts +3 -12
- package/dist/common/workflow.js +25 -23
- package/dist/index.d.ts +52 -14
- package/package.json +9 -1
- package/src/base/common/json.ts +1 -1
- package/src/connector/common/proxy.ts +1 -1
- package/src/control/common/api.ts +90 -16
- package/src/control/common/authoring.ts +6 -1
- package/src/control/common/authoringExamples.ts +8 -0
- package/src/control/common/authoringSchema.ts +26 -13
- package/src/control/common/authoringTools.ts +1 -1
- package/src/control/common/conformance.ts +1 -1
- package/src/control/common/connectorDecoders.ts +1 -1
- package/src/control/common/errors.ts +6 -0
- package/src/control/common/eventSources.ts +2 -29
- package/src/control/common/flowDecoders.ts +1 -0
- package/src/control/common/mcp.ts +16 -0
- package/src/control/common/requests.ts +10 -2
- package/src/control/common/tags.ts +20 -0
- package/src/control/common/triggerCatalog.ts +1 -8
- package/src/decision/common/decision.ts +15 -7
- package/src/event-source/common/definition.ts +1 -1
- package/src/event-source/common/index.ts +1 -1
- package/src/event-source/common/view.ts +20 -0
- package/src/execution/common/checkpoint.ts +1 -1
- package/src/execution/common/events.ts +3 -0
- package/src/execution/common/node-execution.ts +4 -1
- package/src/execution/common/scheduler.ts +3 -1
- package/src/flow/common/change.ts +60 -193
- package/src/flow/common/changeSchema.ts +39 -4
- package/src/flow/common/connectionUsage.ts +1 -1
- package/src/flow/common/errorHandling.ts +1 -1
- package/src/flow/common/inputValue.ts +1 -1
- package/src/flow/common/model.ts +130 -0
- package/src/flow/common/modules.ts +1 -1
- package/src/flow/common/portChanges.ts +1 -1
- package/src/flow/common/retry.ts +2 -4
- package/src/flow/common/semantics.ts +31 -4
- package/src/flow/common/webhookResponse.ts +1 -1
- package/src/flow/common/workflowReferences.ts +31 -0
- package/src/http/common/authBindings.ts +6 -9
- package/src/http/common/hosts.ts +13 -0
- package/src/http/common/httpRequest.ts +30 -15
- package/src/openapi/common/openapi.ts +9 -5
- package/src/{execution → runtime}/common/engineContract.ts +23 -15
- package/src/runtime/common/nodejsCompat.ts +275 -0
- package/src/runtime/common/nodejsGuest.generated.json +47 -0
- package/src/runtime/common/runtime.ts +1254 -0
- package/src/state/common/conformance.ts +86 -0
- package/src/state/common/state.ts +169 -0
- package/src/trigger/common/config.ts +1 -1
- package/src/trigger/common/configOptions.ts +1 -1
- package/src/trigger/common/contract.ts +2 -1
- package/src/trigger/common/cron.ts +2 -1
- package/src/trigger/common/integration.ts +2 -1
- package/src/trigger/common/model.ts +87 -0
- package/src/trigger/common/poll.ts +2 -1
- package/src/trigger/common/webhook.ts +3 -1
- package/src/trigger/providers/fieldDescriptions.ts +1 -1
- package/src/trigger/providers/localization.ts +9 -2
- package/src/trigger/providers/remote.ts +1 -1
- package/src/types/index.ts +55 -15
- package/src/workflow/common/workflow.ts +3 -44
- package/src/execution/common/runtime.ts +0 -563
- /package/src/{control → connector}/common/providerIconSprite.ts +0 -0
|
@@ -0,0 +1,275 @@
|
|
|
1
|
+
import type { EngineContract } from './engineContract.ts'
|
|
2
|
+
|
|
3
|
+
import * as z from 'zod'
|
|
4
|
+
import guestModules from './nodejsGuest.generated.json' with { type: 'json' }
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Guest modules of the Node compatibility engine, keyed by engine module path.
|
|
8
|
+
*
|
|
9
|
+
* A Host evaluates `engine/web.mjs` after installing the guest bridge, then `engine/globals.mjs`, then the Task.
|
|
10
|
+
* The bridge consists of `__hostPrimitive(request, buffer?, extra?)`, which forwards to {@link NodejsPrimitives.call};
|
|
11
|
+
* `__hostTimer(callback, delay, repeat)` and `__hostClearTimer(id)`, which schedule guest callbacks; and
|
|
12
|
+
* `__hostBuiltin(group)`, which synchronously evaluates {@link nodejsBuiltinGroupModule} and returns its namespace.
|
|
13
|
+
*/
|
|
14
|
+
export const nodejsGuestModules: Readonly<Record<string, string>> = guestModules
|
|
15
|
+
export const nodejsWebModule = 'engine/web.mjs'
|
|
16
|
+
export const nodejsGlobalsModule = 'engine/globals.mjs'
|
|
17
|
+
|
|
18
|
+
const builtinGroups: ReadonlySet<string> = new Set(['abort', 'buffer', 'crypto', 'process', 'streams', 'url'])
|
|
19
|
+
|
|
20
|
+
/** Returns the engine module of a lazily loaded builtin group requested through `__hostBuiltin`. */
|
|
21
|
+
export function nodejsBuiltinGroupModule(group: string): string {
|
|
22
|
+
if (!builtinGroups.has(group)) throw new TypeError('Unknown builtin group.')
|
|
23
|
+
return group == 'crypto' ? 'engine/deferred/crypto.mjs' : `engine/globals/${group}.mjs`
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/** Resolves a builtin specifier or an import between engine modules; other specifiers belong to the Host closure. */
|
|
27
|
+
export function resolveNodejsModule(contract: EngineContract, specifier: string, referrer: string): string | undefined {
|
|
28
|
+
if (contract.builtinModules?.has(specifier)) return `engine/builtin/${specifier.replace(/^node:/, '')}.mjs`
|
|
29
|
+
if (!referrer.startsWith('engine/')) return undefined
|
|
30
|
+
const resolved = new URL(specifier, `https://modules.invalid/${referrer}`).pathname.slice(1)
|
|
31
|
+
return Object.hasOwn(nodejsGuestModules, resolved) ? resolved : undefined
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
type Encoding = 'utf8' | 'utf-8' | 'hex' | 'base64' | 'ascii' | 'latin1' | 'binary' | 'ucs2' | 'ucs-2' | 'utf16le' | 'utf-16le'
|
|
35
|
+
type ZlibMethod = 'gzipSync' | 'gunzipSync' | 'deflateSync' | 'inflateSync' | 'deflateRawSync' | 'inflateRawSync' | 'unzipSync'
|
|
36
|
+
|
|
37
|
+
interface PlatformHash {
|
|
38
|
+
update(data: Uint8Array): unknown
|
|
39
|
+
digest(): Uint8Array
|
|
40
|
+
destroy(): unknown
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/** Platform implementations behind the primitives; Node.js and Workers with `nodejs_compat` supply their own modules. */
|
|
44
|
+
export interface NodejsPrimitivePlatform {
|
|
45
|
+
readonly Buffer: {
|
|
46
|
+
from(text: string, encoding: Encoding): Uint8Array
|
|
47
|
+
from(buffer: ArrayBuffer, offset: number, length: number): { toString(encoding: Encoding): string }
|
|
48
|
+
byteLength(text: string, encoding: Encoding): number
|
|
49
|
+
}
|
|
50
|
+
createHash(algorithm: string): PlatformHash
|
|
51
|
+
createHmac(algorithm: string, key: Uint8Array): PlatformHash
|
|
52
|
+
readonly zlib: Readonly<Record<ZlibMethod, (input: Uint8Array, options: object) => Uint8Array>>
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export interface NodejsPrimitives {
|
|
56
|
+
/** Serves one `__hostPrimitive` request; failures are returned as a serialized guest error. */
|
|
57
|
+
call(request: string, buffer?: ArrayBuffer, extra?: ArrayBuffer): string | ArrayBuffer
|
|
58
|
+
close(): void
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const binaryLimit = 1024 * 1024
|
|
62
|
+
const range = { offset: z.number().int().nonnegative(), length: z.number().int().min(0).max(binaryLimit) }
|
|
63
|
+
const encoding = z.enum(['utf8', 'utf-8', 'hex', 'base64', 'ascii', 'latin1', 'binary', 'ucs2', 'ucs-2', 'utf16le', 'utf-16le'])
|
|
64
|
+
const operation = z.discriminatedUnion('operation', [
|
|
65
|
+
z.object({
|
|
66
|
+
operation: z.literal('url'),
|
|
67
|
+
input: z.string(),
|
|
68
|
+
base: z.string().optional(),
|
|
69
|
+
change: z
|
|
70
|
+
.object({ key: z.enum(['href', 'protocol', 'username', 'password', 'host', 'hostname', 'port', 'pathname', 'search', 'hash']), value: z.string() })
|
|
71
|
+
.optional(),
|
|
72
|
+
entries: z.array(z.tuple([z.string(), z.string()])).optional(),
|
|
73
|
+
}),
|
|
74
|
+
z.object({ operation: z.literal('params.parse'), input: z.string() }),
|
|
75
|
+
z.object({ operation: z.literal('params.stringify'), entries: z.array(z.tuple([z.string(), z.string()])) }),
|
|
76
|
+
z.object({ operation: z.literal('encode'), text: z.string() }),
|
|
77
|
+
z.object({ operation: z.literal('decoder'), label: z.string(), fatal: z.boolean(), ignoreBOM: z.boolean() }),
|
|
78
|
+
z.object({
|
|
79
|
+
operation: z.literal('decode'),
|
|
80
|
+
id: z.number().int().positive().optional(),
|
|
81
|
+
label: z.string(),
|
|
82
|
+
fatal: z.boolean(),
|
|
83
|
+
ignoreBOM: z.boolean(),
|
|
84
|
+
...range,
|
|
85
|
+
stream: z.boolean(),
|
|
86
|
+
}),
|
|
87
|
+
z.object({ operation: z.enum(['atob', 'btoa']), text: z.string() }),
|
|
88
|
+
z.object({ operation: z.literal('random'), length: z.number().int().min(0).max(65536) }),
|
|
89
|
+
z.object({ operation: z.literal('uuid') }),
|
|
90
|
+
z.object({ operation: z.enum(['buffer.from', 'buffer.byteLength']), text: z.string(), encoding }),
|
|
91
|
+
z.object({ operation: z.literal('buffer.toString'), encoding, ...range }),
|
|
92
|
+
z.object({ operation: z.literal('hash.create'), algorithm: z.string(), hmac: z.boolean(), ...range, length: z.number().int().min(0).max(65536) }),
|
|
93
|
+
z.object({ operation: z.literal('hash.update'), id: z.number().int().positive(), ...range }),
|
|
94
|
+
z.object({ operation: z.enum(['hash.digest', 'hash.dispose']), id: z.number().int().positive() }),
|
|
95
|
+
z.object({
|
|
96
|
+
operation: z.literal('zlib'),
|
|
97
|
+
method: z.enum(['gzipSync', 'gunzipSync', 'deflateSync', 'inflateSync', 'deflateRawSync', 'inflateRawSync', 'unzipSync']),
|
|
98
|
+
...range,
|
|
99
|
+
dictionary: z.object(range).optional(),
|
|
100
|
+
options: z.object({
|
|
101
|
+
level: z.number().optional(),
|
|
102
|
+
windowBits: z.number().optional(),
|
|
103
|
+
memLevel: z.number().optional(),
|
|
104
|
+
strategy: z.number().optional(),
|
|
105
|
+
chunkSize: z.number().int().min(64).max(binaryLimit).optional(),
|
|
106
|
+
flush: z.number().optional(),
|
|
107
|
+
finishFlush: z.number().optional(),
|
|
108
|
+
maxOutputLength: z.number().int().min(1).max(binaryLimit).optional(),
|
|
109
|
+
}),
|
|
110
|
+
}),
|
|
111
|
+
])
|
|
112
|
+
|
|
113
|
+
/** Creates the per-Task primitive state behind the guest bridge, bounded by call count, bytes, and live instances. */
|
|
114
|
+
export function createNodejsPrimitives(platform: NodejsPrimitivePlatform): NodejsPrimitives {
|
|
115
|
+
// Only streaming decodes keep a host decoder, so Tasks may create any number of guest TextDecoders.
|
|
116
|
+
const decoders = new Map<number, TextDecoder>()
|
|
117
|
+
let nextDecoder = 0
|
|
118
|
+
const hashes = new Map<number, PlatformHash>()
|
|
119
|
+
let nextHash = 0
|
|
120
|
+
let remainingBytes = 64 * binaryLimit
|
|
121
|
+
let calls = 0
|
|
122
|
+
let closed = false
|
|
123
|
+
const spend = (bytes: number): void => {
|
|
124
|
+
remainingBytes -= bytes
|
|
125
|
+
if (remainingBytes < 0) throw new Error('Native builtin byte limit exceeded.')
|
|
126
|
+
}
|
|
127
|
+
const binaryResult = (bytes: Uint8Array): ArrayBuffer => {
|
|
128
|
+
if (bytes.byteLength > binaryLimit) throw new RangeError('Builtin result too large.')
|
|
129
|
+
spend(bytes.byteLength)
|
|
130
|
+
return bytes.buffer.slice(bytes.byteOffset, bytes.byteOffset + bytes.byteLength) as ArrayBuffer
|
|
131
|
+
}
|
|
132
|
+
const binaryView = (buffer: ArrayBuffer | undefined, offset: number, length: number): Uint8Array => {
|
|
133
|
+
const byteLength = buffer?.byteLength ?? 0
|
|
134
|
+
if (byteLength > binaryLimit || offset + length > byteLength) throw new RangeError('Invalid buffer range.')
|
|
135
|
+
spend(length)
|
|
136
|
+
return new Uint8Array(buffer ?? new ArrayBuffer(0), offset, length)
|
|
137
|
+
}
|
|
138
|
+
const serve = (source: string, buffer: ArrayBuffer | undefined, extra: ArrayBuffer | undefined): unknown => {
|
|
139
|
+
const request = operation.parse(JSON.parse(source))
|
|
140
|
+
switch (request.operation) {
|
|
141
|
+
case 'buffer.from':
|
|
142
|
+
spend(request.text.length * 2)
|
|
143
|
+
return binaryResult(platform.Buffer.from(request.text, request.encoding))
|
|
144
|
+
case 'buffer.byteLength':
|
|
145
|
+
spend(request.text.length * 2)
|
|
146
|
+
return { value: platform.Buffer.byteLength(request.text, request.encoding) }
|
|
147
|
+
case 'buffer.toString': {
|
|
148
|
+
const view = binaryView(buffer, request.offset, request.length)
|
|
149
|
+
const value = platform.Buffer.from(view.buffer as ArrayBuffer, view.byteOffset, view.byteLength).toString(request.encoding)
|
|
150
|
+
spend(value.length * 2)
|
|
151
|
+
return { value }
|
|
152
|
+
}
|
|
153
|
+
case 'hash.create': {
|
|
154
|
+
if (hashes.size >= 256) throw new Error('Hash instance limit exceeded.')
|
|
155
|
+
const key = binaryView(buffer, request.offset, request.length)
|
|
156
|
+
hashes.set(++nextHash, request.hmac ? platform.createHmac(request.algorithm, key) : platform.createHash(request.algorithm))
|
|
157
|
+
return { value: nextHash }
|
|
158
|
+
}
|
|
159
|
+
case 'hash.update': {
|
|
160
|
+
const hash = hashes.get(request.id)
|
|
161
|
+
if (hash == null) throw new Error('Digest already called or hash destroyed.')
|
|
162
|
+
try {
|
|
163
|
+
hash.update(binaryView(buffer, request.offset, request.length))
|
|
164
|
+
} catch (error) {
|
|
165
|
+
hashes.delete(request.id)
|
|
166
|
+
hash.destroy()
|
|
167
|
+
throw error
|
|
168
|
+
}
|
|
169
|
+
return { value: undefined }
|
|
170
|
+
}
|
|
171
|
+
case 'hash.digest': {
|
|
172
|
+
const hash = hashes.get(request.id)
|
|
173
|
+
if (hash == null) throw new Error('Digest already called or hash destroyed.')
|
|
174
|
+
hashes.delete(request.id)
|
|
175
|
+
try {
|
|
176
|
+
return binaryResult(hash.digest())
|
|
177
|
+
} finally {
|
|
178
|
+
hash.destroy()
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
case 'hash.dispose':
|
|
182
|
+
hashes.get(request.id)?.destroy()
|
|
183
|
+
hashes.delete(request.id)
|
|
184
|
+
return { value: undefined }
|
|
185
|
+
case 'zlib': {
|
|
186
|
+
const input = binaryView(buffer, request.offset, request.length)
|
|
187
|
+
const options = {
|
|
188
|
+
...request.options,
|
|
189
|
+
maxOutputLength: request.options.maxOutputLength ?? binaryLimit,
|
|
190
|
+
dictionary: request.dictionary == null ? undefined : binaryView(extra, request.dictionary.offset, request.dictionary.length),
|
|
191
|
+
}
|
|
192
|
+
return binaryResult(platform.zlib[request.method](input, options))
|
|
193
|
+
}
|
|
194
|
+
case 'url': {
|
|
195
|
+
let url: URL
|
|
196
|
+
try {
|
|
197
|
+
url = new URL(request.input, request.base)
|
|
198
|
+
} catch (error) {
|
|
199
|
+
if (!(error instanceof TypeError)) throw error
|
|
200
|
+
return { value: null }
|
|
201
|
+
}
|
|
202
|
+
if (request.change != null) url[request.change.key] = request.change.value
|
|
203
|
+
if (request.entries != null) url.search = new URLSearchParams(request.entries).toString()
|
|
204
|
+
const { hash, host, hostname, href, origin, password, pathname, port, protocol, search, username } = url
|
|
205
|
+
return { value: { hash, host, hostname, href, origin, password, pathname, port, protocol, search, username, entries: [...url.searchParams] } }
|
|
206
|
+
}
|
|
207
|
+
case 'params.parse':
|
|
208
|
+
return { value: [...new URLSearchParams(request.input)] }
|
|
209
|
+
case 'params.stringify':
|
|
210
|
+
return { value: new URLSearchParams(request.entries).toString() }
|
|
211
|
+
case 'encode': {
|
|
212
|
+
const encoded = new TextEncoder().encode(request.text)
|
|
213
|
+
if (encoded.byteLength > binaryLimit) throw new Error('Builtin result too large.')
|
|
214
|
+
return encoded.buffer
|
|
215
|
+
}
|
|
216
|
+
case 'decoder':
|
|
217
|
+
return { value: { encoding: new TextDecoder(request.label, { fatal: request.fatal, ignoreBOM: request.ignoreBOM }).encoding } }
|
|
218
|
+
case 'decode': {
|
|
219
|
+
const byteLength = buffer?.byteLength ?? 0
|
|
220
|
+
if (request.offset + request.length > byteLength) throw new RangeError('Invalid buffer range.')
|
|
221
|
+
const stored = request.id == null ? undefined : decoders.get(request.id)
|
|
222
|
+
if (request.id != null && stored == null) throw new TypeError('Unknown TextDecoder.')
|
|
223
|
+
const decoder = stored ?? new TextDecoder(request.label, { fatal: request.fatal, ignoreBOM: request.ignoreBOM })
|
|
224
|
+
let text: string
|
|
225
|
+
try {
|
|
226
|
+
text = decoder.decode(new Uint8Array(buffer ?? new ArrayBuffer(0), request.offset, request.length), { stream: request.stream })
|
|
227
|
+
} catch (error) {
|
|
228
|
+
if (request.id != null) decoders.delete(request.id)
|
|
229
|
+
throw error
|
|
230
|
+
}
|
|
231
|
+
if (!request.stream) {
|
|
232
|
+
if (request.id != null) decoders.delete(request.id)
|
|
233
|
+
return { value: { text } }
|
|
234
|
+
}
|
|
235
|
+
if (stored != null) return { value: { id: request.id, text } }
|
|
236
|
+
if (decoders.size >= 256) throw new Error('TextDecoder limit exceeded.')
|
|
237
|
+
decoders.set(++nextDecoder, decoder)
|
|
238
|
+
return { value: { id: nextDecoder, text } }
|
|
239
|
+
}
|
|
240
|
+
case 'atob':
|
|
241
|
+
return { value: atob(request.text) }
|
|
242
|
+
case 'btoa':
|
|
243
|
+
return { value: btoa(request.text) }
|
|
244
|
+
case 'random':
|
|
245
|
+
return crypto.getRandomValues(new Uint8Array(request.length)).buffer
|
|
246
|
+
case 'uuid':
|
|
247
|
+
return { value: crypto.randomUUID() }
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
return {
|
|
251
|
+
call(source, buffer, extra) {
|
|
252
|
+
if (closed) throw new Error('Task completed.')
|
|
253
|
+
if (++calls > 100_000) throw new Error('Builtin call limit exceeded.')
|
|
254
|
+
if (source.length > binaryLimit) throw new Error('Builtin payload too large.')
|
|
255
|
+
try {
|
|
256
|
+
const result = serve(source, buffer, extra)
|
|
257
|
+
if (result instanceof ArrayBuffer) return result
|
|
258
|
+
const serialized = JSON.stringify(result)
|
|
259
|
+
if (serialized.length > binaryLimit) throw new Error('Builtin result too large.')
|
|
260
|
+
return serialized
|
|
261
|
+
} catch (error) {
|
|
262
|
+
const code = error instanceof Error && 'code' in error && typeof error.code == 'string' ? error.code : undefined
|
|
263
|
+
return JSON.stringify({
|
|
264
|
+
error: { name: error instanceof Error ? error.name : 'Error', message: String(error instanceof Error ? error.message : error), code },
|
|
265
|
+
})
|
|
266
|
+
}
|
|
267
|
+
},
|
|
268
|
+
close() {
|
|
269
|
+
closed = true
|
|
270
|
+
decoders.clear()
|
|
271
|
+
for (const hash of hashes.values()) hash.destroy()
|
|
272
|
+
hashes.clear()
|
|
273
|
+
},
|
|
274
|
+
}
|
|
275
|
+
}
|