@fluidgrids/workflows 2026.1027.0 → 2026.1028.1
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 +170 -18
- package/dist/activation-BBh1p82z.d.cts +57 -0
- package/dist/activation-DnhG7SmF.d.ts +57 -0
- package/dist/assemble-BLqQ8lSu.d.cts +39 -0
- package/dist/assemble-DWgaXHd-.d.ts +39 -0
- package/dist/chunk-2DP2Y6EU.cjs +832 -0
- package/dist/chunk-2J6TF7YI.cjs +86 -0
- package/dist/chunk-3FOTFQ3J.js +1622 -0
- package/dist/chunk-4LYSEANA.js +199 -0
- package/dist/{chunk-KUTMY2IO.cjs → chunk-57MSZ24T.cjs} +162 -98
- package/dist/{chunk-BWSLWF2E.js → chunk-5HDSBTBX.js} +99 -32
- package/dist/chunk-623FVQSN.cjs +251 -0
- package/dist/{chunk-4DPEGDPW.js → chunk-6FSHT5IL.js} +4 -4
- package/dist/{chunk-REV7ZOA4.js → chunk-7AAZGVKD.js} +1 -35
- package/dist/chunk-7NQ37GZU.js +73 -0
- package/dist/chunk-ABFZWYHT.js +612 -0
- package/dist/{chunk-SS4LT2IP.js → chunk-BD7ZPG53.js} +5 -10
- package/dist/chunk-BO6OVILK.js +79 -0
- package/dist/chunk-C5OLWZ42.js +245 -0
- package/dist/chunk-CBL5JSCC.cjs +75 -0
- package/dist/{chunk-LSKSBVL4.cjs → chunk-CPDK3K5N.cjs} +6 -6
- package/dist/chunk-CSNWNFKU.cjs +1635 -0
- package/dist/chunk-DJYMDLV5.js +227 -0
- package/dist/{chunk-X4HKU3MX.js → chunk-E2VK7J2C.js} +3 -1
- package/dist/chunk-FMSW2HDF.cjs +267 -0
- package/dist/chunk-FQIHX7YI.cjs +80 -0
- package/dist/chunk-FR7KYWRO.cjs +41 -0
- package/dist/{chunk-AU3YW7FZ.cjs → chunk-GBQ33SIZ.cjs} +46 -51
- package/dist/{chunk-RRQ5HOBF.cjs → chunk-GVTZMA5C.cjs} +4 -4
- package/dist/chunk-H7KEVW2M.js +816 -0
- package/dist/chunk-HR3BN4C4.cjs +27 -0
- package/dist/chunk-IISBRUWJ.js +13 -0
- package/dist/chunk-JD2VQIDZ.cjs +15 -0
- package/dist/{chunk-PL73GJR4.js → chunk-JZ4TOOLN.js} +1 -1
- package/dist/chunk-L24YIZY7.cjs +207 -0
- package/dist/chunk-LNUQE6D6.js +39 -0
- package/dist/{chunk-BYJ7QTLY.cjs → chunk-NEIUQASE.cjs} +13 -13
- package/dist/chunk-P6TA5EZT.cjs +634 -0
- package/dist/chunk-PDHLTDZB.js +72 -0
- package/dist/chunk-PMCM2OH4.js +46 -0
- package/dist/chunk-PZCVF76Q.cjs +868 -0
- package/dist/{chunk-GO34UHSY.js → chunk-QAN5MZEM.js} +3 -3
- package/dist/{chunk-27HASETB.cjs → chunk-QKZL3ONM.cjs} +3 -1
- package/dist/chunk-SAENRNBJ.cjs +52 -0
- package/dist/{chunk-LMX35GNQ.js → chunk-SMCANK3F.js} +5 -4
- package/dist/{chunk-IZQNUNSU.cjs → chunk-SX2PNKKT.cjs} +18 -17
- package/dist/{chunk-LRM6JXJA.cjs → chunk-TBDXTV22.cjs} +0 -37
- package/dist/chunk-VOKMAAJP.js +848 -0
- package/dist/chunk-XB53G2DK.js +25 -0
- package/dist/chunk-Z2Y65YOY.cjs +7 -0
- package/dist/codegen/index.cjs +9 -7
- package/dist/codegen/index.d.cts +2 -2
- package/dist/codegen/index.d.ts +2 -2
- package/dist/codegen/index.js +6 -5
- package/dist/file-BOoHZgoQ.d.cts +1557 -0
- package/dist/file-yuPCFU5b.d.ts +1557 -0
- package/dist/history/index.cjs +287 -0
- package/dist/history/index.d.cts +157 -0
- package/dist/history/index.d.ts +157 -0
- package/dist/history/index.js +5 -0
- package/dist/index.cjs +134 -36
- package/dist/index.d.cts +137 -9
- package/dist/index.d.ts +137 -9
- package/dist/index.js +8 -3
- package/dist/ir/index.cjs +161 -165
- package/dist/ir/index.d.cts +32 -12
- package/dist/ir/index.d.ts +32 -12
- package/dist/ir/index.js +54 -61
- package/dist/lower-BuSvAFqi.d.cts +129 -0
- package/dist/lower-C_Qv_34S.d.ts +129 -0
- package/dist/lower-types-nofRXw9c.d.cts +15 -0
- package/dist/lower-types-nofRXw9c.d.ts +15 -0
- package/dist/{manifest-Duf-gHdO.d.cts → manifest-0OLw0i7k.d.cts} +1 -1
- package/dist/{manifest-Bp9ZJlav.d.ts → manifest-C8N6HDYl.d.ts} +1 -1
- package/dist/node-evaluator-CJNP4GHX.js +12 -0
- package/dist/node-evaluator-DMKPKUWA.cjs +22 -0
- package/dist/quickjs/index.cjs +256 -78
- package/dist/quickjs/index.d.cts +48 -7
- package/dist/quickjs/index.d.ts +48 -7
- package/dist/quickjs/index.js +254 -79
- package/dist/roundtrip/index.cjs +404 -129
- package/dist/roundtrip/index.d.cts +43 -8
- package/dist/roundtrip/index.d.ts +43 -8
- package/dist/roundtrip/index.js +260 -19
- package/dist/runtime/index.cjs +90 -0
- package/dist/runtime/index.d.cts +297 -0
- package/dist/runtime/index.d.ts +297 -0
- package/dist/runtime/index.js +8 -0
- package/dist/testing/index.cjs +1057 -0
- package/dist/testing/index.d.cts +305 -0
- package/dist/testing/index.d.ts +305 -0
- package/dist/testing/index.js +1037 -0
- package/dist/{types-Dr2Fn1Ax.d.ts → types-BGoPzgcl.d.cts} +1 -1
- package/dist/{types-Dr2Fn1Ax.d.cts → types-BGoPzgcl.d.ts} +1 -1
- package/dist/types-CpBBjaGX.d.cts +380 -0
- package/dist/types-DV-HX_Gt.d.ts +380 -0
- package/dist/{assemble-DMOuaxRI.d.ts → workflow-Bpr3vnA_.d.ts} +60 -162
- package/dist/workflow-C2a05WUJ.d.ts +444 -0
- package/dist/{assemble-BJo9TECS.d.cts → workflow-FXUkpIBc.d.cts} +60 -162
- package/dist/workflow-J-yYixny.d.cts +444 -0
- package/fixtures/README.md +128 -0
- package/fixtures/histories/activity-failure-fails-run.history.json +163 -0
- package/fixtures/histories/activity-retry-then-success.history.json +147 -0
- package/fixtures/histories/cancel-activity-abandon.history.json +126 -0
- package/fixtures/histories/cancel-activity-compensate.history.json +307 -0
- package/fixtures/histories/cancel-concurrent-non-cancellable.history.json +234 -0
- package/fixtures/histories/cancel-concurrent-scope-timeout.history.json +184 -0
- package/fixtures/histories/cancel-condition-after-cancel.history.json +200 -0
- package/fixtures/histories/cancel-during-timer.history.json +123 -0
- package/fixtures/histories/cancel-saga-compensations.history.json +325 -0
- package/fixtures/histories/cancel-scope-timeout.history.json +148 -0
- package/fixtures/histories/child-abandon-outlives-parent.history.json +191 -0
- package/fixtures/histories/child-cancel-default.history.json +234 -0
- package/fixtures/histories/child-cancel-request.history.json +206 -0
- package/fixtures/histories/child-durable-child-side.history.json +124 -0
- package/fixtures/histories/child-durable-result.history.json +163 -0
- package/fixtures/histories/child-failure-caught.history.json +166 -0
- package/fixtures/histories/child-graph-by-key.history.json +138 -0
- package/fixtures/histories/child-terminated-by-parent-close.history.json +85 -0
- package/fixtures/histories/continue-as-new-first-run.history.json +146 -0
- package/fixtures/histories/continue-as-new-history-limit.history.json +489 -0
- package/fixtures/histories/continue-as-new-last-run.history.json +147 -0
- package/fixtures/histories/continue-as-new-suggested.history.json +352 -0
- package/fixtures/histories/details-and-context.history.json +176 -0
- package/fixtures/histories/deterministic-values.history.json +128 -0
- package/fixtures/histories/engine-builtins.history.json +172 -0
- package/fixtures/histories/gather-activities.history.json +291 -0
- package/fixtures/histories/gather-all-settled.history.json +219 -0
- package/fixtures/histories/gather-mixed.history.json +281 -0
- package/fixtures/histories/input-during-running-task.history.json +111 -0
- package/fixtures/histories/nondeterminism-reordered.history.json +218 -0
- package/fixtures/histories/patched-deprecated.history.json +271 -0
- package/fixtures/histories/patched-new-run.history.json +270 -0
- package/fixtures/histories/patched-old-history.history.json +190 -0
- package/fixtures/histories/race-activity-wins.history.json +152 -0
- package/fixtures/histories/race-signal-beats-child.history.json +161 -0
- package/fixtures/histories/race-timeout-wins.history.json +118 -0
- package/fixtures/histories/side-effect-recorded.history.json +153 -0
- package/fixtures/histories/signal-buffered-at-start.history.json +157 -0
- package/fixtures/histories/signal-default-handler.history.json +187 -0
- package/fixtures/histories/signal-handler.history.json +191 -0
- package/fixtures/histories/signal-parent-child-side.history.json +132 -0
- package/fixtures/histories/signal-parent.history.json +202 -0
- package/fixtures/histories/signal-run-delivered.history.json +128 -0
- package/fixtures/histories/signal-run-undelivered.history.json +134 -0
- package/fixtures/histories/signal-wait.history.json +111 -0
- package/fixtures/histories/task-failure-code-error.history.json +137 -0
- package/fixtures/histories/task-failure-then-transient-attempt.history.json +140 -0
- package/fixtures/histories/timer-condition-met.history.json +201 -0
- package/fixtures/histories/timer-condition-timeout.history.json +118 -0
- package/fixtures/histories/timer-sleep-once.history.json +118 -0
- package/fixtures/histories/timer-sleep-sequence.history.json +210 -0
- package/fixtures/histories/update-accepted-completed.history.json +149 -0
- package/fixtures/histories/update-with-start-rejected-validation.history.json +91 -0
- package/package.json +85 -20
- package/schema/history-file.schema.json +2544 -0
- package/schema/ir-v2.schema.json +16 -0
- package/schema/run-event.schema.json +2374 -0
- package/schema/workflow-command.schema.json +1095 -0
- package/schema/workflow-task.schema.json +3560 -0
- package/dist/chunk-265J2FCH.cjs +0 -33
- package/dist/chunk-LUXCXFOE.cjs +0 -269
- package/dist/chunk-S34NJE3A.js +0 -262
- package/dist/chunk-SRQRLWOS.js +0 -31
- package/dist/lower-DcOY8ux0.d.cts +0 -49
- package/dist/lower-Dw5grNrI.d.ts +0 -49
- package/dist/node-evaluator-2GTUZVPK.cjs +0 -17
- package/dist/node-evaluator-RMYEWCXZ.js +0 -8
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var chunkHR3BN4C4_cjs = require('./chunk-HR3BN4C4.cjs');
|
|
4
|
+
require('./chunk-2DP2Y6EU.cjs');
|
|
5
|
+
require('./chunk-CBL5JSCC.cjs');
|
|
6
|
+
require('./chunk-57MSZ24T.cjs');
|
|
7
|
+
require('./chunk-GBQ33SIZ.cjs');
|
|
8
|
+
require('./chunk-G4UEPUGO.cjs');
|
|
9
|
+
require('./chunk-GVTZMA5C.cjs');
|
|
10
|
+
require('./chunk-QKZL3ONM.cjs');
|
|
11
|
+
require('./chunk-TBDXTV22.cjs');
|
|
12
|
+
require('./chunk-SAENRNBJ.cjs');
|
|
13
|
+
require('./chunk-FQIHX7YI.cjs');
|
|
14
|
+
require('./chunk-2J6TF7YI.cjs');
|
|
15
|
+
require('./chunk-Z2Y65YOY.cjs');
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
Object.defineProperty(exports, "createNodeVmEvaluator", {
|
|
20
|
+
enumerable: true,
|
|
21
|
+
get: function () { return chunkHR3BN4C4_cjs.createNodeVmEvaluator; }
|
|
22
|
+
});
|
package/dist/quickjs/index.cjs
CHANGED
|
@@ -1,92 +1,270 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
4
|
-
require('../chunk-
|
|
5
|
-
require('../chunk-
|
|
3
|
+
var chunk2DP2Y6EU_cjs = require('../chunk-2DP2Y6EU.cjs');
|
|
4
|
+
require('../chunk-CBL5JSCC.cjs');
|
|
5
|
+
var chunkJD2VQIDZ_cjs = require('../chunk-JD2VQIDZ.cjs');
|
|
6
|
+
require('../chunk-57MSZ24T.cjs');
|
|
7
|
+
var chunkGBQ33SIZ_cjs = require('../chunk-GBQ33SIZ.cjs');
|
|
6
8
|
require('../chunk-G4UEPUGO.cjs');
|
|
7
|
-
require('../chunk-
|
|
8
|
-
require('../chunk-
|
|
9
|
-
require('../chunk-
|
|
10
|
-
var
|
|
9
|
+
require('../chunk-GVTZMA5C.cjs');
|
|
10
|
+
require('../chunk-QKZL3ONM.cjs');
|
|
11
|
+
require('../chunk-TBDXTV22.cjs');
|
|
12
|
+
var chunkSAENRNBJ_cjs = require('../chunk-SAENRNBJ.cjs');
|
|
13
|
+
require('../chunk-L24YIZY7.cjs');
|
|
14
|
+
require('../chunk-FQIHX7YI.cjs');
|
|
15
|
+
require('../chunk-623FVQSN.cjs');
|
|
16
|
+
require('../chunk-2J6TF7YI.cjs');
|
|
17
|
+
var chunkZ2Y65YOY_cjs = require('../chunk-Z2Y65YOY.cjs');
|
|
18
|
+
var module$1 = require('module');
|
|
19
|
+
var url = require('url');
|
|
20
|
+
var worker_threads = require('worker_threads');
|
|
11
21
|
|
|
12
|
-
|
|
13
|
-
var ENGINE_HEADROOM_BYTES = 32 * 1024 * 1024;
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
const dumped = ctx.dump(handle);
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
22
|
+
// src/generated/quickjs-worker-source.ts
|
|
23
|
+
var QUICKJS_WORKER_SOURCE = '"use strict";\n\nvar import_node_worker_threads = require("node:worker_threads");\n\nfunction isRecord(value) {\n return typeof value === "object" && value !== null && !Array.isArray(value);\n}\n\nvar DETERMINISM_VIOLATION = "DeterminismViolation";\nvar DETERMINISM_PRELUDE = `(() => {\n const NAME = ${JSON.stringify(DETERMINISM_VIOLATION)};\n const fail = (what) => {\n const error = new Error(\n what + " is not allowed in workflow code: lowering must give the same IR on every build. Read times and random values at run time instead (for example wf.now)."\n );\n error.name = NAME;\n throw error;\n };\n const lock = (target, key, value) =>\n Object.defineProperty(target, key, { value, writable: false, enumerable: false, configurable: false });\n const RealDate = Date;\n const LockedDate = function Date(...args) {\n if (new.target === undefined) return fail("Date()");\n if (args.length === 0) return fail("new Date()");\n return Reflect.construct(RealDate, args, new.target);\n };\n lock(LockedDate, "prototype", RealDate.prototype);\n lock(RealDate.prototype, "constructor", LockedDate);\n lock(LockedDate, "now", function now() { return fail("Date.now()"); });\n lock(LockedDate, "parse", RealDate.parse);\n lock(LockedDate, "UTC", RealDate.UTC);\n lock(globalThis, "Date", LockedDate);\n lock(Math, "random", function random() { return fail("Math.random()"); });\n const crypto = globalThis.crypto;\n if (crypto !== null && typeof crypto === "object") {\n for (const name of ["getRandomValues", "randomUUID"]) {\n if (typeof crypto[name] === "function") lock(crypto, name, function () { return fail("crypto." + name + "()"); });\n }\n }\n const DateTimeFormat = typeof Intl === "object" && Intl !== null ? Intl.DateTimeFormat : undefined;\n if (typeof DateTimeFormat === "function") {\n const proto = DateTimeFormat.prototype;\n const format = Object.getOwnPropertyDescriptor(proto, "format");\n if (format && typeof format.get === "function") {\n const get = format.get;\n Object.defineProperty(proto, "format", {\n get() {\n const bound = get.call(this);\n return (date) => (date === undefined ? fail("Intl.DateTimeFormat format()") : bound(date));\n },\n enumerable: false,\n configurable: false,\n });\n }\n const formatToParts = proto.formatToParts;\n if (typeof formatToParts === "function") {\n lock(proto, "formatToParts", function (date) {\n return date === undefined ? fail("Intl.DateTimeFormat formatToParts()") : formatToParts.call(this, date);\n });\n }\n }\n})();\n`;\nfunction failure(kind, message) {\n return { ok: false, failure: kind, message };\n}\nfunction failureForErrorName(name) {\n return name === DETERMINISM_VIOLATION ? "determinism" : "error";\n}\n\nfunction isQuickJSApi(value) {\n return isRecord(value) && typeof value["newQuickJSWASMModuleFromVariant"] === "function" && typeof value["newVariant"] === "function" && typeof value["shouldInterruptAfterDeadline"] === "function" && value["RELEASE_SYNC"] !== void 0;\n}\nvar WASM_PAGE_BYTES = 64 * 1024;\nvar ENGINE_HEADROOM_BYTES = 32 * 1024 * 1024;\nvar INITIAL_ENGINE_BYTES = 16 * 1024 * 1024;\nfunction describe(ctx, handle) {\n const dumped = ctx.dump(handle);\n if (isRecord(dumped)) {\n const name = typeof dumped["name"] === "string" ? dumped["name"] : "Error";\n const message = dumped["message"];\n return {\n name,\n message: typeof message === "string" ? message : message === void 0 ? JSON.stringify(dumped) : String(message)\n };\n }\n return { name: "Error", message: String(dumped) };\n}\nasync function evaluateInQuickJS(api, code, limits) {\n const maximum = Math.ceil((limits.memoryLimitBytes + ENGINE_HEADROOM_BYTES) / WASM_PAGE_BYTES);\n const initial = Math.min(maximum, INITIAL_ENGINE_BYTES / WASM_PAGE_BYTES);\n const engine = await api.newQuickJSWASMModuleFromVariant(\n api.newVariant(api.RELEASE_SYNC, { wasmMemory: new WebAssembly.Memory({ initial, maximum }) })\n );\n const runtime = engine.newRuntime();\n const deadline = Date.now() + limits.timeoutMs;\n runtime.setMemoryLimit(limits.memoryLimitBytes);\n runtime.setMaxStackSize(limits.maxStackSizeBytes);\n runtime.setInterruptHandler(api.shouldInterruptAfterDeadline(deadline));\n const ctx = runtime.newContext();\n const handles = [];\n const timedOut = () => failure("timeout", `Evaluating the workflow code timed out after ${limits.timeoutMs} ms`);\n const thrown = (handle) => {\n const { name, message } = describe(ctx, handle);\n handle.dispose();\n if (Date.now() > deadline && /interrupted/.test(message)) return timedOut();\n return failure(failureForErrorName(name), message);\n };\n try {\n const prelude = ctx.evalCode(DETERMINISM_PRELUDE, "determinism-prelude.js", { type: "global" });\n if (prelude.error) return thrown(prelude.error);\n prelude.value.dispose();\n const result = ctx.evalCode(code, "workflow-bundle.mjs", { type: "module" });\n if (result.error) return thrown(result.error);\n let namespace = result.value;\n handles.push(namespace);\n const state = ctx.getPromiseState(namespace);\n if (!(state.type === "fulfilled" && state.notAPromise === true)) {\n if (state.type === "fulfilled") state.value.dispose();\n else if (state.type === "rejected") state.error.dispose();\n while (runtime.hasPendingJob()) {\n if (Date.now() > deadline) return timedOut();\n const jobs = runtime.executePendingJobs();\n if (jobs.error) return thrown(jobs.error);\n }\n const settled = ctx.getPromiseState(namespace);\n if (settled.type === "rejected") return thrown(settled.error);\n if (settled.type === "pending")\n return failure("error", "The workflow module never finished evaluating");\n namespace = settled.value;\n handles.push(namespace);\n }\n const exported = ctx.getProp(namespace, "__fluidgrids");\n handles.push(exported);\n if (ctx.typeof(exported) !== "string")\n return failure("no-collection", "The bundle did not export a workflow collection");\n return { ok: true, value: ctx.getString(exported) };\n } catch (error) {\n return failure("error", error instanceof Error ? error.message : String(error));\n } finally {\n for (const handle of handles.reverse()) if (handle.alive) handle.dispose();\n ctx.dispose();\n runtime.dispose();\n }\n}\n\nprocess.on("unhandledRejection", () => void 0);\nasync function main(input) {\n if (!isRecord(input) || typeof input["code"] !== "string" || typeof input["moduleUrl"] !== "string" || !isRecord(input["limits"]))\n return failure("crashed", "The evaluation worker received no bundle");\n const { timeoutMs, memoryLimitBytes, maxStackSizeBytes } = input["limits"];\n if (typeof timeoutMs !== "number" || typeof memoryLimitBytes !== "number" || typeof maxStackSizeBytes !== "number")\n return failure("crashed", "The evaluation worker received no limits");\n const loaded = await import(input["moduleUrl"]);\n const api = isQuickJSApi(loaded) ? loaded : isRecord(loaded) && isQuickJSApi(loaded["default"]) ? loaded["default"] : void 0;\n if (!api) return failure("crashed", "quickjs-emscripten could not be loaded");\n return evaluateInQuickJS(api, input["code"], {\n timeoutMs,\n memoryLimitBytes,\n maxStackSizeBytes\n });\n}\nmain(import_node_worker_threads.workerData).then(\n (outcome) => import_node_worker_threads.parentPort?.postMessage(outcome),\n (error) => import_node_worker_threads.parentPort?.postMessage(\n failure("crashed", error instanceof Error ? error.message : String(error))\n )\n);\n';
|
|
24
|
+
|
|
25
|
+
// src/generated/quickjs-task-worker-source.ts
|
|
26
|
+
var QUICKJS_TASK_WORKER_SOURCE = '"use strict";\n\nvar import_node_worker_threads = require("node:worker_threads");\n\nfunction isRecord(value) {\n return typeof value === "object" && value !== null && !Array.isArray(value);\n}\n\nfunction isQuickJSApi(value) {\n return isRecord(value) && typeof value["newQuickJSWASMModuleFromVariant"] === "function" && typeof value["newVariant"] === "function" && typeof value["shouldInterruptAfterDeadline"] === "function" && value["RELEASE_SYNC"] !== void 0;\n}\nvar WASM_PAGE_BYTES = 64 * 1024;\nvar ENGINE_HEADROOM_BYTES = 32 * 1024 * 1024;\nvar INITIAL_ENGINE_BYTES = 16 * 1024 * 1024;\n\nvar HISTORY_PROTOCOL = 1;\nvar DEFAULT_HISTORY_LIMIT = { events: 1e4, bytes: 16 * 1024 * 1024 };\n\nvar SHIM_VIOLATION = "DeterminismViolation";\nvar SHIM_HOOK = "__fluidgridsShims";\nvar TASK_PRELUDE = `(() => {\n const NAME = ${JSON.stringify(SHIM_VIOLATION)};\n const fail = (what) => {\n const error = new Error(what + " is not allowed in workflow code: use ctx.now(), ctx.random(), ctx.sleep() or an activity.");\n error.name = NAME;\n throw error;\n };\n let hooks = null;\n const now = (what) => (hooks !== null ? hooks.now() : fail(what + " outside a workflow task"));\n const lock = (target, key, value) =>\n Object.defineProperty(target, key, { value, writable: false, enumerable: false, configurable: false });\n const RealDate = Date;\n // ---- Built-ins that differ between hosts and engines --------------------\n // Local time is UTC whatever the host\'s TZ, locale formatting is fixed\n // (en-US shapes, no ICU), Intl is absent and garbage collection cannot be\n // observed, so QuickJS and vm on any host run workflow code the same way.\n const proto = RealDate.prototype;\n const hostOffset = proto.getTimezoneOffset;\n const realParse = RealDate.parse;\n const isInvalid = (date) => Number.isNaN(proto.getTime.call(date));\n for (const unit of ["FullYear", "Month", "Date", "Day", "Hours", "Minutes", "Seconds", "Milliseconds"]) {\n lock(proto, "get" + unit, proto["getUTC" + unit]);\n if (unit !== "Day") lock(proto, "set" + unit, proto["setUTC" + unit]);\n }\n lock(proto, "getTimezoneOffset", function getTimezoneOffset() { return isInvalid(this) ? NaN : 0; });\n if (typeof proto.getYear === "function")\n lock(proto, "getYear", function getYear() { return isInvalid(this) ? NaN : this.getUTCFullYear() - 1900; });\n if (typeof proto.setYear === "function")\n lock(proto, "setYear", function setYear(value) {\n const year = Number(value);\n if (Number.isNaN(year)) return this.setTime(NaN);\n const whole = Math.trunc(year);\n const base = new RealDate(isInvalid(this) ? 0 : this.getTime());\n base.setUTCFullYear(whole >= 0 && whole <= 99 ? 1900 + whole : whole);\n return this.setTime(base.getTime());\n });\n const DAYS = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];\n const MONTHS = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];\n const pad = (value, width) => String(value).padStart(width, "0");\n const yearText = (year) => (year < 0 ? "-" + pad(-year, 6) : pad(year, 4));\n const dateText = (d) =>\n DAYS[d.getUTCDay()] + " " + MONTHS[d.getUTCMonth()] + " " + pad(d.getUTCDate(), 2) + " " + yearText(d.getUTCFullYear());\n const timeText = (d) =>\n pad(d.getUTCHours(), 2) + ":" + pad(d.getUTCMinutes(), 2) + ":" + pad(d.getUTCSeconds(), 2) + " GMT+0000 (Coordinated Universal Time)";\n const localeDate = (d) => d.getUTCMonth() + 1 + "/" + d.getUTCDate() + "/" + d.getUTCFullYear();\n const localeTime = (d) => {\n const hours = d.getUTCHours();\n return ((hours + 11) % 12) + 1 + ":" + pad(d.getUTCMinutes(), 2) + ":" + pad(d.getUTCSeconds(), 2) + (hours < 12 ? " AM" : " PM");\n };\n const formatter = (format) => function () { return isInvalid(this) ? "Invalid Date" : format(this); };\n lock(proto, "toString", formatter((d) => dateText(d) + " " + timeText(d)));\n lock(proto, "toDateString", formatter(dateText));\n lock(proto, "toTimeString", formatter(timeText));\n lock(proto, "toLocaleString", formatter((d) => localeDate(d) + ", " + localeTime(d)));\n lock(proto, "toLocaleDateString", formatter(localeDate));\n lock(proto, "toLocaleTimeString", formatter(localeTime));\n // A date-time without an offset is local time to the host\'s parser; read it as UTC.\n const DATE_ONLY = /^[+-]?\\\\d{4,6}(?:-\\\\d{2}(?:-\\\\d{2})?)?$/;\n const ZONE_AFTER_TIME = /\\\\d:\\\\d{2}(?::\\\\d{2}(?:[.,]\\\\d+)?)?\\\\s*(?:[AP]M\\\\s*)?(?:Z|[+-]\\\\d{2}(?::?\\\\d{2})?|[ECMP][SD]T)\\\\s*(?:\\\\([^)]*\\\\))?\\\\s*$/i;\n const NAMED_ZONE = /\\\\b(?:GMT|UTC|UT)\\\\b(?:\\\\s*[+-]\\\\d{2}:?\\\\d{2})?\\\\s*(?:\\\\([^)]*\\\\))?\\\\s*$/i;\n const parse = function parse(value) {\n const text = String(value);\n const time = realParse(text);\n if (Number.isNaN(time)) return time;\n const trimmed = text.trim();\n if (DATE_ONLY.test(trimmed) || ZONE_AFTER_TIME.test(trimmed) || NAMED_ZONE.test(trimmed)) return time;\n return time - hostOffset.call(new RealDate(time)) * 60000;\n };\n const toTimeValue = (value) => {\n if (value instanceof RealDate) return value.getTime();\n let primitive = value;\n if (typeof value === "object" && value !== null) {\n primitive = value.valueOf();\n if (typeof primitive === "object" && primitive !== null) primitive = String(value);\n }\n return typeof primitive === "string" ? parse(primitive) : primitive;\n };\n // ---- Number, string and array locale methods ----------------------------\n const group = (digits) => digits.replace(/\\\\B(?=(\\\\d{3})+(?!\\\\d))/g, ",");\n lock(Number.prototype, "toLocaleString", function toLocaleString() {\n const x = Number.prototype.valueOf.call(this);\n if (Number.isNaN(x)) return "NaN";\n const sign = x < 0 || Object.is(x, -0) ? "-" : "";\n const abs = Math.abs(x);\n if (abs === Infinity) return sign + "\\\\u221e";\n const fixed = abs < 1e21 ? abs.toFixed(3) : BigInt(abs).toString() + ".000";\n const [whole, fraction] = fixed.split(".");\n const kept = fraction.replace(/0+$/, "");\n return sign + group(whole) + (kept === "" ? "" : "." + kept);\n });\n if (typeof BigInt === "function")\n lock(BigInt.prototype, "toLocaleString", function toLocaleString() {\n const text = BigInt.prototype.toString.call(this);\n return text.startsWith("-") ? "-" + group(text.slice(1)) : group(text);\n });\n lock(String.prototype, "localeCompare", function localeCompare(that) {\n const a = String(this);\n const b = String(that);\n return a < b ? -1 : a > b ? 1 : 0;\n });\n lock(String.prototype, "toLocaleUpperCase", function toLocaleUpperCase() { return String(this).toUpperCase(); });\n lock(String.prototype, "toLocaleLowerCase", function toLocaleLowerCase() { return String(this).toLowerCase(); });\n const listLocale = function toLocaleString() {\n return Array.prototype.map.call(this, (item) => (item === null || item === undefined ? "" : item.toLocaleString())).join(",");\n };\n lock(Array.prototype, "toLocaleString", listLocale);\n lock(Object.getPrototypeOf(Uint8Array.prototype), "toLocaleString", listLocale);\n // ---- Absent or refused ---------------------------------------------------\n if (!Reflect.deleteProperty(globalThis, "Intl")) lock(globalThis, "Intl", undefined);\n for (const name of ["WeakRef", "FinalizationRegistry"]) {\n lock(globalThis, name, function () { return fail(name + " (garbage collection is not deterministic)"); });\n }\n const LockedDate = function Date(...args) {\n if (new.target === undefined) return new RealDate(now("Date()")).toString();\n if (args.length === 0) return Reflect.construct(RealDate, [now("new Date()")], new.target);\n if (args.length === 1) return Reflect.construct(RealDate, [toTimeValue(args[0])], new.target);\n return Reflect.construct(RealDate, [RealDate.UTC(...args)], new.target);\n };\n lock(LockedDate, "prototype", RealDate.prototype);\n lock(RealDate.prototype, "constructor", LockedDate);\n lock(LockedDate, "now", function now_() { return now("Date.now()"); });\n lock(LockedDate, "parse", parse);\n lock(LockedDate, "UTC", RealDate.UTC);\n lock(globalThis, "Date", LockedDate);\n lock(Math, "random", function random() {\n return hooks !== null ? hooks.random() : fail("Math.random() outside a workflow task");\n });\n const crypto = globalThis.crypto;\n if (crypto !== null && typeof crypto === "object") {\n if (typeof crypto.getRandomValues === "function")\n lock(crypto, "getRandomValues", function getRandomValues(array) {\n if (hooks === null) return fail("crypto.getRandomValues() outside a workflow task");\n for (let i = 0; i < array.length; i++) array[i] = Math.floor(hooks.random() * 256);\n return array;\n });\n if (typeof crypto.randomUUID === "function")\n lock(crypto, "randomUUID", function randomUUID() { return fail("crypto.randomUUID(): use ctx.uuid()"); });\n }\n for (const name of ["setTimeout", "setInterval", "setImmediate", "clearTimeout", "clearInterval", "clearImmediate"]) {\n lock(globalThis, name, function () { return fail(name + "(): use ctx.sleep()"); });\n }\n for (const name of ["fetch", "XMLHttpRequest", "WebSocket", "EventSource"]) {\n lock(globalThis, name, function () { return fail(name + ": do I/O in an activity (ctx.run)"); });\n }\n Object.defineProperty(globalThis, ${JSON.stringify(SHIM_HOOK)}, {\n value: Object.freeze({\n attach(next) { hooks = next; },\n detach() { hooks = null; },\n }),\n writable: false,\n enumerable: false,\n configurable: true,\n });\n})();\n`;\n\nvar WASM_PAGE_BYTES2 = 64 * 1024;\nvar HOST_STACK_OVERFLOW = /maximum call stack size exceeded|too much recursion/i;\nvar ENGINE_HEADROOM_BYTES2 = 32 * 1024 * 1024;\nvar INITIAL_ENGINE_BYTES2 = 16 * 1024 * 1024;\nasync function createTaskModule(api, memoryLimitBytes) {\n const maximum = Math.ceil((memoryLimitBytes + ENGINE_HEADROOM_BYTES2) / WASM_PAGE_BYTES2);\n const initial = Math.min(maximum, INITIAL_ENGINE_BYTES2 / WASM_PAGE_BYTES2);\n return api.newQuickJSWASMModuleFromVariant(\n api.newVariant(api.RELEASE_SYNC, { wasmMemory: new WebAssembly.Memory({ initial, maximum }) })\n );\n}\nfunction describe(ctx, handle) {\n const dumped = ctx.dump(handle);\n if (isRecord(dumped)) {\n const name = typeof dumped["name"] === "string" ? dumped["name"] : "Error";\n const message = typeof dumped["message"] === "string" ? dumped["message"] : JSON.stringify(dumped);\n return { name, message };\n }\n return { name: "Error", message: String(dumped) };\n}\nvar TaskError = class extends Error {\n constructor(cause, message, fatal = false) {\n super(message);\n this.cause = cause;\n this.fatal = fatal;\n }\n cause;\n fatal;\n};\nfunction runTaskInQuickJS(api, module2, code, requestJson, limits) {\n const disposed = { failed: false };\n const outcome = runTask(api, module2, code, requestJson, limits, disposed);\n return disposed.failed && outcome.fatal !== true ? { ...outcome, fatal: true } : outcome;\n}\nfunction runTask(api, module2, code, requestJson, limits, disposed) {\n let runtime;\n let ctx;\n const handles = [];\n const deadline = Date.now() + limits.timeoutMs;\n try {\n runtime = module2.newRuntime();\n runtime.setMemoryLimit(limits.memoryLimitBytes);\n runtime.setMaxStackSize(limits.maxStackSizeBytes);\n runtime.setInterruptHandler(api.shouldInterruptAfterDeadline(deadline));\n const rt = runtime;\n const context = rt.newContext();\n ctx = context;\n const fail = (handle, during) => {\n const { name, message } = describe(context, handle);\n handle.dispose();\n if (Date.now() > deadline && /interrupted/i.test(message))\n throw new TaskError(\n "TASK_TIMEOUT",\n `The workflow task ran past its ${limits.timeoutMs} ms budget`\n );\n if (/out of memory/i.test(message) || name === "InternalError" && /memory/i.test(message))\n throw new TaskError("ISOLATE_MEMORY", `The workflow task ran out of memory ${during}`);\n if (name === "DeterminismViolation") throw new TaskError("NON_DETERMINISM", message);\n throw new TaskError("WORKFLOW_CODE_ERROR", `${name}: ${message} (${during})`);\n };\n const drain = (during) => {\n while (rt.hasPendingJob()) {\n if (Date.now() > deadline)\n throw new TaskError(\n "TASK_TIMEOUT",\n `The workflow task ran past its ${limits.timeoutMs} ms budget`\n );\n const jobs = rt.executePendingJobs();\n if (jobs.error) fail(jobs.error, during);\n }\n };\n const prelude = context.evalCode(TASK_PRELUDE, "fluidgrids-task-prelude.js", {\n type: "global"\n });\n if (prelude.error) fail(prelude.error, "in the task prelude");\n else prelude.value.dispose();\n const evaluated = context.evalCode(code, "workflow-bundle.mjs", { type: "module" });\n if (evaluated.error) fail(evaluated.error, "while loading the bundle");\n else {\n handles.push(evaluated.value);\n drain("while loading the bundle");\n const state = context.getPromiseState(evaluated.value);\n if (state.type === "rejected") fail(state.error, "while loading the bundle");\n else if (state.type === "fulfilled" && state.notAPromise !== true) state.value.dispose();\n }\n const abi = context.getProp(context.global, "__fluidgridsRuntime");\n handles.push(abi);\n if (context.typeof(abi) !== "object")\n throw new TaskError(\n "INVALID_REQUEST",\n "The bundle has no workflow runtime (build it with @fluidgrids/workflows 2026.1028 or later)"\n );\n const protocol = context.getProp(abi, "protocol");\n const protocolValue = context.dump(protocol);\n protocol.dispose();\n if (protocolValue !== HISTORY_PROTOCOL)\n throw new TaskError(\n "PROTOCOL_MISMATCH",\n `The bundle speaks runtime protocol ${String(protocolValue)}; this host speaks ${HISTORY_PROTOCOL}`\n );\n const call = (name, args) => {\n const fn = context.getProp(abi, name);\n try {\n const result = context.callFunction(fn, abi, ...args);\n if (result.error) return fail(result.error, `in ${name}()`);\n return result.value;\n } finally {\n fn.dispose();\n }\n };\n const request = context.newString(requestJson);\n handles.push(request);\n call("start", [request]).dispose();\n drain("in the workflow code");\n for (; ; ) {\n const step = call("step", []);\n const value = context.dump(step);\n step.dispose();\n drain("in the workflow code");\n if (value !== "more") break;\n }\n const completed = call("complete", []);\n const resultValue = context.dump(completed);\n completed.dispose();\n if (typeof resultValue !== "string")\n throw new TaskError("INTERNAL", "The runtime returned no result");\n return { ok: true, resultJson: resultValue };\n } catch (error) {\n if (error instanceof TaskError)\n return {\n ok: false,\n cause: error.cause,\n message: error.message,\n ...error.fatal ? { fatal: true } : {}\n };\n const message = error instanceof Error ? error.message : String(error);\n if (HOST_STACK_OVERFLOW.test(message))\n return {\n ok: false,\n cause: "WORKFLOW_CODE_ERROR",\n message: `RangeError: stack overflow (the engine\'s host stack ran out: ${message})`,\n fatal: true\n };\n return {\n ok: false,\n cause: /memory|out of bounds|abort/i.test(message) ? "ISOLATE_MEMORY" : "INTERNAL",\n message,\n fatal: true\n };\n } finally {\n for (const handle of handles.reverse()) if (handle.alive) handle.dispose();\n try {\n ctx?.dispose();\n runtime?.dispose();\n } catch {\n disposed.failed = true;\n }\n }\n}\n\nprocess.on("unhandledRejection", () => void 0);\nasync function main(input) {\n const port = import_node_worker_threads.parentPort;\n if (!port) return;\n if (!isRecord(input) || typeof input["moduleUrl"] !== "string" || typeof input["memoryLimitBytes"] !== "number") {\n port.postMessage({ type: "fatal", message: "The task worker received no configuration" });\n return;\n }\n const loaded = await import(input["moduleUrl"]);\n const api = isQuickJSApi(loaded) ? loaded : isRecord(loaded) && isQuickJSApi(loaded["default"]) ? loaded["default"] : void 0;\n if (!api) {\n port.postMessage({ type: "fatal", message: "quickjs-emscripten could not be loaded" });\n return;\n }\n const module2 = await createTaskModule(api, input["memoryLimitBytes"]);\n port.on("message", (message) => {\n if (!isRecord(message) || message["type"] !== "task") return;\n const id = message["id"];\n const limits = message["limits"];\n let outcome;\n if (typeof message["code"] !== "string" || typeof message["requestJson"] !== "string" || !isRecord(limits) || typeof limits["timeoutMs"] !== "number" || typeof limits["memoryLimitBytes"] !== "number" || typeof limits["maxStackSizeBytes"] !== "number")\n outcome = {\n ok: false,\n cause: "INTERNAL",\n message: "The task worker received a malformed task"\n };\n else\n outcome = runTaskInQuickJS(api, module2, message["code"], message["requestJson"], {\n timeoutMs: limits["timeoutMs"],\n memoryLimitBytes: limits["memoryLimitBytes"],\n maxStackSizeBytes: limits["maxStackSizeBytes"]\n });\n port.postMessage({ type: "result", id, outcome });\n if (outcome.fatal === true) process.exit(1);\n });\n port.postMessage({ type: "ready" });\n}\nmain(import_node_worker_threads.workerData).catch((error) => {\n import_node_worker_threads.parentPort?.postMessage({\n type: "fatal",\n message: error instanceof Error ? error.message : String(error)\n });\n});\n';
|
|
27
|
+
|
|
28
|
+
// src/quickjs/task-runner.ts
|
|
29
|
+
var MAX_START_FAILURES = 3;
|
|
30
|
+
var DEFAULT_MAX_STACK_SIZE_BYTES = 256 * 1024;
|
|
31
|
+
function quickjsModuleUrl() {
|
|
32
|
+
return url.pathToFileURL(module$1.createRequire(chunkZ2Y65YOY_cjs.importMetaUrl).resolve("quickjs-emscripten")).href;
|
|
20
33
|
}
|
|
21
|
-
function
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
const
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
34
|
+
function parseResult(outcome) {
|
|
35
|
+
if (!chunkSAENRNBJ_cjs.isRecord(outcome))
|
|
36
|
+
return chunkJD2VQIDZ_cjs.failedTaskResult("INTERNAL", "The task worker returned no outcome");
|
|
37
|
+
const typed = outcome;
|
|
38
|
+
if (typed.ok === true && typeof typed.resultJson === "string") {
|
|
39
|
+
try {
|
|
40
|
+
const parsed = JSON.parse(typed.resultJson);
|
|
41
|
+
if (chunkSAENRNBJ_cjs.isRecord(parsed) && typeof parsed["outcome"] === "string" && Array.isArray(parsed["commands"]))
|
|
42
|
+
return parsed;
|
|
43
|
+
} catch {
|
|
44
|
+
}
|
|
45
|
+
return chunkJD2VQIDZ_cjs.failedTaskResult("INTERNAL", "The runtime returned an invalid result");
|
|
46
|
+
}
|
|
47
|
+
if (typed.ok === false && typeof typed.cause === "string")
|
|
48
|
+
return chunkJD2VQIDZ_cjs.failedTaskResult(typed.cause, String(typed.message));
|
|
49
|
+
return chunkJD2VQIDZ_cjs.failedTaskResult("INTERNAL", "The task worker returned an invalid outcome");
|
|
50
|
+
}
|
|
51
|
+
function createWorkflowTaskRunner(options = {}) {
|
|
52
|
+
const poolSize = Math.max(1, Math.floor(options.poolSize ?? 4));
|
|
53
|
+
const memoryLimitBytes = options.memoryLimitBytes ?? 128 * 1024 * 1024;
|
|
54
|
+
const maxStackSizeBytes = options.maxStackSizeBytes ?? DEFAULT_MAX_STACK_SIZE_BYTES;
|
|
55
|
+
const defaultTimeoutMs = options.timeoutMs ?? 1e4;
|
|
56
|
+
const cacheEntries = Math.max(1, options.bundleCacheEntries ?? 64);
|
|
57
|
+
const startupTimeoutMs = options.startupTimeoutMs ?? 15e3;
|
|
58
|
+
const verified = /* @__PURE__ */ new Map();
|
|
59
|
+
const queue = [];
|
|
60
|
+
const slots = [];
|
|
61
|
+
let closed = false;
|
|
62
|
+
let moduleUrl;
|
|
63
|
+
let nextJobId = 0;
|
|
64
|
+
let startFailures = 0;
|
|
65
|
+
const finish = (slot, result) => {
|
|
66
|
+
const job = slot.job;
|
|
67
|
+
slot.job = void 0;
|
|
68
|
+
if (slot.timer !== void 0) clearTimeout(slot.timer);
|
|
69
|
+
slot.timer = void 0;
|
|
70
|
+
job?.resolve(result);
|
|
71
|
+
};
|
|
72
|
+
const replace = (slot) => {
|
|
73
|
+
void slot.worker.terminate();
|
|
74
|
+
const index = slots.indexOf(slot);
|
|
75
|
+
if (index >= 0) slots.splice(index, 1);
|
|
76
|
+
if (!closed) spawn();
|
|
77
|
+
pump();
|
|
78
|
+
};
|
|
79
|
+
const startFailed = (slot, reason) => {
|
|
80
|
+
startFailures += 1;
|
|
81
|
+
if (startFailures < MAX_START_FAILURES) {
|
|
82
|
+
replace(slot);
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
startFailures = 0;
|
|
86
|
+
void slot.worker.terminate();
|
|
87
|
+
const index = slots.indexOf(slot);
|
|
88
|
+
if (index >= 0) slots.splice(index, 1);
|
|
89
|
+
if (slots.some((entry) => entry.ready)) return;
|
|
90
|
+
for (const job of queue.splice(0))
|
|
91
|
+
job.resolve(
|
|
92
|
+
chunkJD2VQIDZ_cjs.failedTaskResult("INTERNAL", `The workflow task threads could not start: ${reason}`)
|
|
32
93
|
);
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
}
|
|
63
|
-
const settled = ctx.getPromiseState(namespace);
|
|
64
|
-
if (settled.type === "rejected") {
|
|
65
|
-
const message = errorMessage(ctx, settled.error);
|
|
66
|
-
settled.error.dispose();
|
|
67
|
-
throw new chunkLUXCXFOE_cjs.LowerError(`Evaluating the workflow code failed: ${message}`);
|
|
68
|
-
}
|
|
69
|
-
if (settled.type === "pending")
|
|
70
|
-
throw new chunkLUXCXFOE_cjs.LowerError("The workflow module never finished evaluating");
|
|
71
|
-
namespace = settled.value;
|
|
72
|
-
handles.push(namespace);
|
|
94
|
+
};
|
|
95
|
+
const spawn = () => {
|
|
96
|
+
moduleUrl ??= quickjsModuleUrl();
|
|
97
|
+
const worker = new worker_threads.Worker(QUICKJS_TASK_WORKER_SOURCE, {
|
|
98
|
+
eval: true,
|
|
99
|
+
workerData: { moduleUrl, memoryLimitBytes }
|
|
100
|
+
});
|
|
101
|
+
const slot = { worker, ready: false, jobId: 0 };
|
|
102
|
+
slots.push(slot);
|
|
103
|
+
const startup = setTimeout(() => {
|
|
104
|
+
if (!slot.ready) startFailed(slot, `no thread was ready within ${startupTimeoutMs} ms`);
|
|
105
|
+
}, startupTimeoutMs);
|
|
106
|
+
worker.on("message", (message) => {
|
|
107
|
+
if (!chunkSAENRNBJ_cjs.isRecord(message)) return;
|
|
108
|
+
if (message["type"] === "ready") {
|
|
109
|
+
clearTimeout(startup);
|
|
110
|
+
slot.ready = true;
|
|
111
|
+
startFailures = 0;
|
|
112
|
+
pump();
|
|
113
|
+
} else if (message["type"] === "result" && message["id"] === slot.jobId && slot.job) {
|
|
114
|
+
const outcome = message["outcome"];
|
|
115
|
+
finish(slot, parseResult(outcome));
|
|
116
|
+
if (chunkSAENRNBJ_cjs.isRecord(outcome) && outcome["fatal"] === true) replace(slot);
|
|
117
|
+
else pump();
|
|
118
|
+
} else if (message["type"] === "fatal") {
|
|
119
|
+
clearTimeout(startup);
|
|
120
|
+
if (!slot.ready) {
|
|
121
|
+
startFailed(slot, String(message["message"]));
|
|
122
|
+
return;
|
|
73
123
|
}
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
124
|
+
if (slot.job) finish(slot, chunkJD2VQIDZ_cjs.failedTaskResult("INTERNAL", String(message["message"])));
|
|
125
|
+
replace(slot);
|
|
126
|
+
}
|
|
127
|
+
});
|
|
128
|
+
worker.on("error", (error) => {
|
|
129
|
+
clearTimeout(startup);
|
|
130
|
+
const outOfMemory = "code" in error && error.code === "ERR_WORKER_OUT_OF_MEMORY";
|
|
131
|
+
if (slot.job)
|
|
132
|
+
finish(
|
|
133
|
+
slot,
|
|
134
|
+
chunkJD2VQIDZ_cjs.failedTaskResult(
|
|
135
|
+
outOfMemory ? "ISOLATE_MEMORY" : "INTERNAL",
|
|
136
|
+
outOfMemory ? "The workflow task ran out of memory" : `The task thread failed: ${error.message}`
|
|
137
|
+
)
|
|
138
|
+
);
|
|
139
|
+
});
|
|
140
|
+
worker.on("exit", () => {
|
|
141
|
+
clearTimeout(startup);
|
|
142
|
+
if (!slots.includes(slot)) return;
|
|
143
|
+
if (!slot.ready) {
|
|
144
|
+
startFailed(slot, "the thread exited while starting");
|
|
145
|
+
return;
|
|
146
|
+
}
|
|
147
|
+
if (slot.job) finish(slot, chunkJD2VQIDZ_cjs.failedTaskResult("INTERNAL", "The task thread exited"));
|
|
148
|
+
replace(slot);
|
|
149
|
+
});
|
|
150
|
+
};
|
|
151
|
+
const pump = () => {
|
|
152
|
+
for (const slot of slots) {
|
|
153
|
+
if (!slot.ready || slot.job) continue;
|
|
154
|
+
const job = queue.shift();
|
|
155
|
+
if (!job) return;
|
|
156
|
+
nextJobId += 1;
|
|
157
|
+
slot.jobId = nextJobId;
|
|
158
|
+
slot.job = job;
|
|
159
|
+
slot.timer = setTimeout(() => {
|
|
160
|
+
finish(
|
|
161
|
+
slot,
|
|
162
|
+
chunkJD2VQIDZ_cjs.failedTaskResult(
|
|
163
|
+
"TASK_TIMEOUT",
|
|
164
|
+
`The workflow task ran past its ${job.timeoutMs} ms budget`
|
|
165
|
+
)
|
|
166
|
+
);
|
|
167
|
+
replace(slot);
|
|
168
|
+
}, job.timeoutMs + 250);
|
|
169
|
+
slot.worker.postMessage({
|
|
170
|
+
type: "task",
|
|
171
|
+
id: slot.jobId,
|
|
172
|
+
code: job.code,
|
|
173
|
+
requestJson: job.requestJson,
|
|
174
|
+
limits: { timeoutMs: job.timeoutMs, memoryLimitBytes, maxStackSizeBytes }
|
|
175
|
+
});
|
|
176
|
+
}
|
|
177
|
+
};
|
|
178
|
+
const verify = (code, buildId) => {
|
|
179
|
+
const known = verified.get(buildId);
|
|
180
|
+
if (known === code) {
|
|
181
|
+
verified.delete(buildId);
|
|
182
|
+
verified.set(buildId, code);
|
|
183
|
+
return true;
|
|
184
|
+
}
|
|
185
|
+
if (chunkGBQ33SIZ_cjs.buildIdOf(code) !== buildId) return false;
|
|
186
|
+
verified.delete(buildId);
|
|
187
|
+
verified.set(buildId, code);
|
|
188
|
+
while (verified.size > cacheEntries) {
|
|
189
|
+
const oldest = verified.keys().next().value;
|
|
190
|
+
if (oldest === void 0) break;
|
|
191
|
+
verified.delete(oldest);
|
|
192
|
+
}
|
|
193
|
+
return true;
|
|
194
|
+
};
|
|
195
|
+
return {
|
|
196
|
+
run(bundle, request, runOptions = {}) {
|
|
197
|
+
if (closed) return Promise.resolve(chunkJD2VQIDZ_cjs.failedTaskResult("INTERNAL", "The task runner is closed"));
|
|
198
|
+
const code = typeof bundle === "string" ? bundle : bundle.code;
|
|
199
|
+
const buildId = typeof bundle === "string" ? void 0 : bundle.buildId;
|
|
200
|
+
if (buildId !== void 0 && !verify(code, buildId))
|
|
201
|
+
return Promise.resolve(
|
|
202
|
+
chunkJD2VQIDZ_cjs.failedTaskResult("BUNDLE_INTEGRITY", `The bundle does not hash to ${buildId}`)
|
|
203
|
+
);
|
|
204
|
+
let requestJson;
|
|
205
|
+
try {
|
|
206
|
+
requestJson = JSON.stringify(request);
|
|
79
207
|
} catch (error) {
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
runtime.dispose();
|
|
208
|
+
return Promise.resolve(
|
|
209
|
+
chunkJD2VQIDZ_cjs.failedTaskResult(
|
|
210
|
+
"INVALID_REQUEST",
|
|
211
|
+
error instanceof Error ? error.message : String(error)
|
|
212
|
+
)
|
|
213
|
+
);
|
|
87
214
|
}
|
|
215
|
+
if (slots.length === 0) for (let index = 0; index < poolSize; index++) spawn();
|
|
216
|
+
return new Promise((resolve) => {
|
|
217
|
+
queue.push({
|
|
218
|
+
code,
|
|
219
|
+
requestJson,
|
|
220
|
+
timeoutMs: runOptions.timeoutMs ?? defaultTimeoutMs,
|
|
221
|
+
resolve
|
|
222
|
+
});
|
|
223
|
+
pump();
|
|
224
|
+
});
|
|
225
|
+
},
|
|
226
|
+
async close() {
|
|
227
|
+
closed = true;
|
|
228
|
+
for (const job of queue.splice(0))
|
|
229
|
+
job.resolve(chunkJD2VQIDZ_cjs.failedTaskResult("INTERNAL", "The task runner is closed"));
|
|
230
|
+
const all = slots.splice(0);
|
|
231
|
+
for (const slot of all)
|
|
232
|
+
if (slot.job) finish(slot, chunkJD2VQIDZ_cjs.failedTaskResult("INTERNAL", "The task runner is closed"));
|
|
233
|
+
await Promise.all(all.map((slot) => slot.worker.terminate()));
|
|
234
|
+
}
|
|
235
|
+
};
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
// src/quickjs/index.ts
|
|
239
|
+
function quickjsModuleUrl2() {
|
|
240
|
+
try {
|
|
241
|
+
return url.pathToFileURL(module$1.createRequire(chunkZ2Y65YOY_cjs.importMetaUrl).resolve("quickjs-emscripten")).href;
|
|
242
|
+
} catch (error) {
|
|
243
|
+
throw new chunk2DP2Y6EU_cjs.LowerError(
|
|
244
|
+
`quickjs-emscripten cannot be resolved: ${error instanceof Error ? error.message : String(error)}`,
|
|
245
|
+
"crashed"
|
|
246
|
+
);
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
function createQuickJSEvaluator(options = {}) {
|
|
250
|
+
const limits = {
|
|
251
|
+
timeoutMs: options.timeoutMs ?? 5e3,
|
|
252
|
+
memoryLimitBytes: options.memoryLimitBytes ?? 64 * 1024 * 1024,
|
|
253
|
+
maxStackSizeBytes: options.maxStackSizeBytes ?? 1024 * 1024
|
|
254
|
+
};
|
|
255
|
+
return {
|
|
256
|
+
format: "esm",
|
|
257
|
+
async evaluate(code) {
|
|
258
|
+
const outcome = await chunk2DP2Y6EU_cjs.runIsolateWorker({
|
|
259
|
+
source: QUICKJS_WORKER_SOURCE,
|
|
260
|
+
workerData: { code, limits, moduleUrl: quickjsModuleUrl2() },
|
|
261
|
+
timeoutMs: limits.timeoutMs
|
|
262
|
+
});
|
|
263
|
+
return chunk2DP2Y6EU_cjs.outcomeToCollection(outcome);
|
|
88
264
|
}
|
|
89
265
|
};
|
|
90
266
|
}
|
|
91
267
|
|
|
268
|
+
exports.DEFAULT_MAX_STACK_SIZE_BYTES = DEFAULT_MAX_STACK_SIZE_BYTES;
|
|
92
269
|
exports.createQuickJSEvaluator = createQuickJSEvaluator;
|
|
270
|
+
exports.createWorkflowTaskRunner = createWorkflowTaskRunner;
|
package/dist/quickjs/index.d.cts
CHANGED
|
@@ -1,18 +1,59 @@
|
|
|
1
|
-
import { E as Evaluator } from '../lower-
|
|
2
|
-
import '
|
|
1
|
+
import { E as Evaluator } from '../lower-BuSvAFqi.cjs';
|
|
2
|
+
import { a7 as WorkflowTaskRequest, a8 as WorkflowTaskResult } from '../types-CpBBjaGX.cjs';
|
|
3
3
|
import '../hash-CZkTXPCX.cjs';
|
|
4
|
-
import '../types-
|
|
5
|
-
import '../assemble-
|
|
4
|
+
import '../types-BGoPzgcl.cjs';
|
|
5
|
+
import '../assemble-BLqQ8lSu.cjs';
|
|
6
|
+
import '../workflow-FXUkpIBc.cjs';
|
|
7
|
+
import '../workflow-J-yYixny.cjs';
|
|
8
|
+
import '../lower-types-nofRXw9c.cjs';
|
|
9
|
+
import 'esbuild';
|
|
10
|
+
|
|
11
|
+
interface WorkflowTaskRunnerOptions {
|
|
12
|
+
/** Worker threads. Default 4. */
|
|
13
|
+
poolSize?: number;
|
|
14
|
+
/** Heap cap per task. Default 128 MiB. */
|
|
15
|
+
memoryLimitBytes?: number;
|
|
16
|
+
/**
|
|
17
|
+
* Stack cap per task. Default 256 KiB, about 1,300 plain JavaScript frames.
|
|
18
|
+
* QuickJS's C frames also use the host thread's native stack, which Bun
|
|
19
|
+
* does not let a worker enlarge; at 1 MiB ordinary recursion exhausted the
|
|
20
|
+
* host stack before QuickJS's own check fired. Native recursion (very deep
|
|
21
|
+
* JSON) can still hit the host stack; that task fails `WORKFLOW_CODE_ERROR`
|
|
22
|
+
* and its thread is replaced.
|
|
23
|
+
*/
|
|
24
|
+
maxStackSizeBytes?: number;
|
|
25
|
+
/** Wall-clock budget per task, including parsing the bundle. Default 10000 ms. */
|
|
26
|
+
timeoutMs?: number;
|
|
27
|
+
/** Verified build ids remembered. Default 64. */
|
|
28
|
+
bundleCacheEntries?: number;
|
|
29
|
+
/** How long a thread may take to start. Default 15000 ms. */
|
|
30
|
+
startupTimeoutMs?: number;
|
|
31
|
+
}
|
|
32
|
+
/** A bundle to run; with `buildId` it is integrity-checked (`sha256:<hex>` of the text). */
|
|
33
|
+
type WorkflowBundleInput = string | {
|
|
34
|
+
code: string;
|
|
35
|
+
buildId?: string;
|
|
36
|
+
};
|
|
37
|
+
interface WorkflowTaskRunner {
|
|
38
|
+
run(bundle: WorkflowBundleInput, request: WorkflowTaskRequest, options?: {
|
|
39
|
+
timeoutMs?: number;
|
|
40
|
+
}): Promise<WorkflowTaskResult>;
|
|
41
|
+
close(): Promise<void>;
|
|
42
|
+
}
|
|
43
|
+
/** See {@link WorkflowTaskRunnerOptions.maxStackSizeBytes}. */
|
|
44
|
+
declare const DEFAULT_MAX_STACK_SIZE_BYTES: number;
|
|
45
|
+
/** Create a pool of QuickJS workflow-task threads. */
|
|
46
|
+
declare function createWorkflowTaskRunner(options?: WorkflowTaskRunnerOptions): WorkflowTaskRunner;
|
|
6
47
|
|
|
7
48
|
interface QuickJSEvaluatorOptions {
|
|
8
|
-
/** Wall-clock budget. Default 5000 ms. */
|
|
49
|
+
/** Wall-clock budget, including parsing and compiling the bundle. Default 5000 ms. */
|
|
9
50
|
timeoutMs?: number;
|
|
10
51
|
/** Runtime heap cap. Default 64 MiB. */
|
|
11
52
|
memoryLimitBytes?: number;
|
|
12
53
|
/** Native stack cap. Default 1 MiB. */
|
|
13
54
|
maxStackSizeBytes?: number;
|
|
14
55
|
}
|
|
15
|
-
/** An {@link Evaluator} backed by a bounded QuickJS engine. */
|
|
56
|
+
/** An {@link Evaluator} backed by a bounded QuickJS engine in a worker thread. */
|
|
16
57
|
declare function createQuickJSEvaluator(options?: QuickJSEvaluatorOptions): Evaluator;
|
|
17
58
|
|
|
18
|
-
export { type QuickJSEvaluatorOptions, createQuickJSEvaluator };
|
|
59
|
+
export { DEFAULT_MAX_STACK_SIZE_BYTES, type QuickJSEvaluatorOptions, type WorkflowBundleInput, type WorkflowTaskRunner, type WorkflowTaskRunnerOptions, createQuickJSEvaluator, createWorkflowTaskRunner };
|
package/dist/quickjs/index.d.ts
CHANGED
|
@@ -1,18 +1,59 @@
|
|
|
1
|
-
import { E as Evaluator } from '../lower-
|
|
2
|
-
import '
|
|
1
|
+
import { E as Evaluator } from '../lower-C_Qv_34S.js';
|
|
2
|
+
import { a7 as WorkflowTaskRequest, a8 as WorkflowTaskResult } from '../types-DV-HX_Gt.js';
|
|
3
3
|
import '../hash-CZkTXPCX.js';
|
|
4
|
-
import '../types-
|
|
5
|
-
import '../assemble-
|
|
4
|
+
import '../types-BGoPzgcl.js';
|
|
5
|
+
import '../assemble-DWgaXHd-.js';
|
|
6
|
+
import '../workflow-Bpr3vnA_.js';
|
|
7
|
+
import '../workflow-C2a05WUJ.js';
|
|
8
|
+
import '../lower-types-nofRXw9c.js';
|
|
9
|
+
import 'esbuild';
|
|
10
|
+
|
|
11
|
+
interface WorkflowTaskRunnerOptions {
|
|
12
|
+
/** Worker threads. Default 4. */
|
|
13
|
+
poolSize?: number;
|
|
14
|
+
/** Heap cap per task. Default 128 MiB. */
|
|
15
|
+
memoryLimitBytes?: number;
|
|
16
|
+
/**
|
|
17
|
+
* Stack cap per task. Default 256 KiB, about 1,300 plain JavaScript frames.
|
|
18
|
+
* QuickJS's C frames also use the host thread's native stack, which Bun
|
|
19
|
+
* does not let a worker enlarge; at 1 MiB ordinary recursion exhausted the
|
|
20
|
+
* host stack before QuickJS's own check fired. Native recursion (very deep
|
|
21
|
+
* JSON) can still hit the host stack; that task fails `WORKFLOW_CODE_ERROR`
|
|
22
|
+
* and its thread is replaced.
|
|
23
|
+
*/
|
|
24
|
+
maxStackSizeBytes?: number;
|
|
25
|
+
/** Wall-clock budget per task, including parsing the bundle. Default 10000 ms. */
|
|
26
|
+
timeoutMs?: number;
|
|
27
|
+
/** Verified build ids remembered. Default 64. */
|
|
28
|
+
bundleCacheEntries?: number;
|
|
29
|
+
/** How long a thread may take to start. Default 15000 ms. */
|
|
30
|
+
startupTimeoutMs?: number;
|
|
31
|
+
}
|
|
32
|
+
/** A bundle to run; with `buildId` it is integrity-checked (`sha256:<hex>` of the text). */
|
|
33
|
+
type WorkflowBundleInput = string | {
|
|
34
|
+
code: string;
|
|
35
|
+
buildId?: string;
|
|
36
|
+
};
|
|
37
|
+
interface WorkflowTaskRunner {
|
|
38
|
+
run(bundle: WorkflowBundleInput, request: WorkflowTaskRequest, options?: {
|
|
39
|
+
timeoutMs?: number;
|
|
40
|
+
}): Promise<WorkflowTaskResult>;
|
|
41
|
+
close(): Promise<void>;
|
|
42
|
+
}
|
|
43
|
+
/** See {@link WorkflowTaskRunnerOptions.maxStackSizeBytes}. */
|
|
44
|
+
declare const DEFAULT_MAX_STACK_SIZE_BYTES: number;
|
|
45
|
+
/** Create a pool of QuickJS workflow-task threads. */
|
|
46
|
+
declare function createWorkflowTaskRunner(options?: WorkflowTaskRunnerOptions): WorkflowTaskRunner;
|
|
6
47
|
|
|
7
48
|
interface QuickJSEvaluatorOptions {
|
|
8
|
-
/** Wall-clock budget. Default 5000 ms. */
|
|
49
|
+
/** Wall-clock budget, including parsing and compiling the bundle. Default 5000 ms. */
|
|
9
50
|
timeoutMs?: number;
|
|
10
51
|
/** Runtime heap cap. Default 64 MiB. */
|
|
11
52
|
memoryLimitBytes?: number;
|
|
12
53
|
/** Native stack cap. Default 1 MiB. */
|
|
13
54
|
maxStackSizeBytes?: number;
|
|
14
55
|
}
|
|
15
|
-
/** An {@link Evaluator} backed by a bounded QuickJS engine. */
|
|
56
|
+
/** An {@link Evaluator} backed by a bounded QuickJS engine in a worker thread. */
|
|
16
57
|
declare function createQuickJSEvaluator(options?: QuickJSEvaluatorOptions): Evaluator;
|
|
17
58
|
|
|
18
|
-
export { type QuickJSEvaluatorOptions, createQuickJSEvaluator };
|
|
59
|
+
export { DEFAULT_MAX_STACK_SIZE_BYTES, type QuickJSEvaluatorOptions, type WorkflowBundleInput, type WorkflowTaskRunner, type WorkflowTaskRunnerOptions, createQuickJSEvaluator, createWorkflowTaskRunner };
|