@fluidgrids/workflows 2026.1028.2 → 2026.1030.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 +181 -11
- package/dist/{activation-BBh1p82z.d.cts → activation-DqUfpHzk.d.cts} +1 -1
- package/dist/{activation-DnhG7SmF.d.ts → activation-xpx1oWuo.d.ts} +1 -1
- package/dist/{chunk-VRHHBPT6.js → chunk-2D3MYIIF.js} +1212 -128
- package/dist/chunk-3U2NU7YC.cjs +124 -0
- package/dist/{chunk-NEIUQASE.cjs → chunk-4QKB4ARC.cjs} +3 -3
- package/dist/{chunk-GBQ33SIZ.cjs → chunk-54FLQNUM.cjs} +12 -1
- package/dist/chunk-5HIVIV53.js +330 -0
- package/dist/chunk-5MFVJM76.js +1222 -0
- package/dist/{chunk-JD2VQIDZ.cjs → chunk-672KMMBK.cjs} +2 -2
- package/dist/{chunk-C5OLWZ42.js → chunk-6A2FGSUS.js} +22 -14
- package/dist/{chunk-XKJA7KX3.js → chunk-6OLN6BMB.js} +52 -3
- package/dist/{chunk-6FSHT5IL.js → chunk-7EZIANC7.js} +1 -1
- package/dist/{chunk-2J6TF7YI.cjs → chunk-A5SXCA62.cjs} +10 -3
- package/dist/{chunk-BO6OVILK.js → chunk-AC6ZEXVR.js} +10 -4
- package/dist/{chunk-ABFZWYHT.js → chunk-AE5Q6ZAJ.js} +315 -50
- package/dist/chunk-C4F5KJTI.js +293 -0
- package/dist/{chunk-IISBRUWJ.js → chunk-G5H32GIG.js} +1 -1
- package/dist/chunk-GEQDGUGB.cjs +2719 -0
- package/dist/{chunk-XHXIDVEC.js → chunk-HCM7ZC7Q.js} +1 -1
- package/dist/chunk-HMZUGSMU.cjs +1554 -0
- package/dist/{chunk-SAOBPYYJ.cjs → chunk-IQPXHQQQ.cjs} +8 -4
- package/dist/{chunk-P6TA5EZT.cjs → chunk-ISOIA7NV.cjs} +335 -58
- package/dist/chunk-JSC75O5C.cjs +167 -0
- package/dist/chunk-M272AHEX.js +25 -0
- package/dist/{chunk-BD7ZPG53.js → chunk-NWQ5WRLE.js} +10 -2
- package/dist/chunk-ODZ2IAR2.cjs +1247 -0
- package/dist/chunk-Q4MWQNJK.cjs +28 -0
- package/dist/{chunk-HWJZVOG7.js → chunk-SR7TR5KX.js} +6 -2
- package/dist/{chunk-FEW3JBYA.cjs → chunk-TCTE7DX5.cjs} +3 -3
- package/dist/{chunk-623FVQSN.cjs → chunk-TYF56RGB.cjs} +123 -0
- package/dist/chunk-VA4OFR72.cjs +324 -0
- package/dist/chunk-VU5S5A7V.js +150 -0
- package/dist/chunk-YEHR4NNE.js +1522 -0
- package/dist/{chunk-FMSW2HDF.cjs → chunk-ZCGKGDCL.cjs} +23 -15
- package/dist/codegen/index.d.cts +2 -2
- package/dist/codegen/index.d.ts +2 -2
- package/dist/collect-6NIEufHd.d.ts +103 -0
- package/dist/collect-CcTCKqx6.d.cts +103 -0
- package/dist/{file-BOoHZgoQ.d.cts → file-BxYpwjRQ.d.cts} +1007 -21
- package/dist/{file-yuPCFU5b.d.ts → file-CFdPQJI9.d.ts} +1007 -21
- package/dist/history/index.cjs +375 -86
- package/dist/history/index.d.cts +590 -12
- package/dist/history/index.d.ts +590 -12
- package/dist/history/index.js +50 -4
- package/dist/index.cjs +156 -50
- package/dist/index.d.cts +38 -58
- package/dist/index.d.ts +38 -58
- package/dist/index.js +6 -4
- package/dist/interceptors-CNcr2dlk.d.ts +159 -0
- package/dist/interceptors-CqkNZVfI.d.cts +159 -0
- package/dist/ir/index.cjs +362 -38
- package/dist/ir/index.d.cts +282 -7
- package/dist/ir/index.d.ts +282 -7
- package/dist/ir/index.js +329 -23
- package/dist/{lower-BzmUz0sq.d.cts → lower-BtRfIW2A.d.cts} +56 -8
- package/dist/{lower-_-iT4HYs.d.ts → lower-CpsMFOFX.d.ts} +56 -8
- package/dist/{manifest-C8N6HDYl.d.ts → manifest-D-I_twys.d.ts} +1 -1
- package/dist/{manifest-0OLw0i7k.d.cts → manifest-DahBQVM8.d.cts} +1 -1
- package/dist/node-evaluator-DGQDPSPI.cjs +24 -0
- package/dist/node-evaluator-LEEVD7H7.js +14 -0
- package/dist/payload-fields-BVRQn2yH.d.cts +122 -0
- package/dist/payload-fields-oOBWxDiG.d.ts +122 -0
- package/dist/quickjs/index.cjs +28 -27
- package/dist/quickjs/index.d.cts +6 -6
- package/dist/quickjs/index.d.ts +6 -6
- package/dist/quickjs/index.js +10 -9
- package/dist/roundtrip/index.cjs +259 -51
- package/dist/roundtrip/index.d.cts +100 -9
- package/dist/roundtrip/index.d.ts +100 -9
- package/dist/roundtrip/index.js +177 -11
- package/dist/runtime/index.cjs +21 -20
- package/dist/runtime/index.d.cts +184 -15
- package/dist/runtime/index.d.ts +184 -15
- package/dist/runtime/index.js +8 -7
- package/dist/testing/index.cjs +1122 -115
- package/dist/testing/index.d.cts +294 -13
- package/dist/testing/index.d.ts +294 -13
- package/dist/testing/index.js +1086 -84
- package/dist/{types-DV-HX_Gt.d.ts → types-Bv2i4cBX.d.cts} +244 -33
- package/dist/{types-CpBBjaGX.d.cts → types-DGx-b9eq.d.ts} +244 -33
- package/dist/{types-BGoPzgcl.d.ts → types-V7jEEUaL.d.cts} +20 -1
- package/dist/{types-BGoPzgcl.d.cts → types-V7jEEUaL.d.ts} +20 -1
- package/dist/{workflow-Bpr3vnA_.d.ts → workflow-B18OeF7g.d.ts} +2 -2
- package/dist/workflow-BGnv8SS6.d.ts +803 -0
- package/dist/{workflow-FXUkpIBc.d.cts → workflow-BJPFv3cp.d.cts} +2 -2
- package/dist/workflow-DS32Gtws.d.cts +803 -0
- package/fixtures/histories/activity-options-updated.history.json +159 -0
- package/fixtures/histories/activity-paused-unpaused.history.json +160 -0
- package/fixtures/histories/auto-upgrade-patched.history.json +276 -0
- package/fixtures/histories/benign-failure.history.json +146 -0
- package/fixtures/histories/cancel-activity-try-cancel.history.json +150 -0
- package/fixtures/histories/child-cancel-wait-requested.history.json +217 -0
- package/fixtures/histories/child-options-roundtrip.history.json +192 -0
- package/fixtures/histories/codec-opaque.history.json +229 -0
- package/fixtures/histories/continue-as-new-last-result.history.json +86 -0
- package/fixtures/histories/continue-as-new-options.history.json +99 -0
- package/fixtures/histories/continue-as-new-r1-long-task-queue.history.json +78 -0
- package/fixtures/histories/continue-as-new-r1-retry-options.history.json +83 -0
- package/fixtures/histories/dynamic-workflow.history.json +150 -0
- package/fixtures/histories/execution-timeout-chain.history.json +98 -0
- package/fixtures/histories/external-cancel-resolved.history.json +123 -0
- package/fixtures/histories/external-cancel-unknown-target.history.json +127 -0
- package/fixtures/histories/failure-error-types-fails-run.history.json +144 -0
- package/fixtures/histories/handler-drain-warn.history.json +222 -0
- package/fixtures/histories/heartbeat-details-on-retry.history.json +145 -0
- package/fixtures/histories/interceptor-headers.history.json +339 -0
- package/fixtures/histories/local-activity-abandoned-at-completion.history.json +73 -0
- package/fixtures/histories/local-activity-cancelled-in-scope.history.json +118 -0
- package/fixtures/histories/local-activity-completed.history.json +157 -0
- package/fixtures/histories/local-activity-failed.history.json +93 -0
- package/fixtures/histories/local-activity-retry-in-task.history.json +88 -0
- package/fixtures/histories/query-custom.history.json +213 -0
- package/fixtures/histories/query-default-handler.history.json +120 -0
- package/fixtures/histories/reset-forked-reapplied-signals.history.json +239 -0
- package/fixtures/histories/reset-reapplied-update-admitted.history.json +228 -0
- package/fixtures/histories/run-retry-last-failure.history.json +90 -0
- package/fixtures/histories/run-timeout.history.json +159 -0
- package/fixtures/histories/schedule-to-start-timeout.history.json +132 -0
- package/fixtures/histories/search-attributes-upserted.history.json +177 -0
- package/fixtures/histories/start-delay-signal-ends-delay.history.json +155 -0
- package/fixtures/histories/typeerror-task-retry-100.history.json +137 -0
- package/fixtures/histories/update-accepted-completed.history.json +45 -30
- package/fixtures/histories/update-default-handler.history.json +246 -0
- package/fixtures/histories/update-handler-awaits-activity.history.json +196 -0
- package/fixtures/histories/update-not-handled.history.json +138 -0
- package/fixtures/histories/update-rejected-no-event.history.json +190 -0
- package/fixtures/histories/update-with-start-admitted.history.json +150 -0
- package/fixtures/histories/user-activity-cancel.history.json +149 -0
- package/fixtures/histories/user-activity-retry.history.json +143 -0
- package/fixtures/histories/user-activity.history.json +149 -0
- package/package.json +1 -1
- package/schema/bridge-v2.schema.json +1062 -0
- package/schema/history-file.schema.json +538 -83
- package/schema/ir-v2.schema.json +290 -0
- package/schema/payload-fields.json +162 -0
- package/schema/run-event.schema.json +503 -82
- package/schema/workflow-command.schema.json +372 -69
- package/schema/workflow-task.schema.json +924 -171
- package/dist/assemble-BLqQ8lSu.d.cts +0 -39
- package/dist/assemble-DWgaXHd-.d.ts +0 -39
- package/dist/chunk-DHTLALBL.cjs +0 -80
- package/dist/chunk-DJYMDLV5.js +0 -227
- package/dist/chunk-I5LR3D2K.js +0 -869
- package/dist/chunk-M4BBAERY.cjs +0 -1635
- package/dist/chunk-N23SKIG4.js +0 -73
- package/dist/chunk-PZCVF76Q.cjs +0 -868
- package/dist/chunk-QQ6ULXHI.cjs +0 -885
- package/dist/chunk-UK3WM7YZ.cjs +0 -75
- package/dist/chunk-VOKMAAJP.js +0 -848
- package/dist/node-evaluator-4MSDKWOG.cjs +0 -22
- package/dist/node-evaluator-SX4LEYQC.js +0 -12
- package/dist/workflow-C2a05WUJ.d.ts +0 -444
- package/dist/workflow-J-yYixny.d.cts +0 -444
package/dist/quickjs/index.cjs
CHANGED
|
@@ -1,19 +1,20 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
4
|
-
require('../chunk-
|
|
5
|
-
var
|
|
6
|
-
require('../chunk-
|
|
7
|
-
var
|
|
3
|
+
var chunkODZ2IAR2_cjs = require('../chunk-ODZ2IAR2.cjs');
|
|
4
|
+
require('../chunk-3U2NU7YC.cjs');
|
|
5
|
+
var chunk672KMMBK_cjs = require('../chunk-672KMMBK.cjs');
|
|
6
|
+
require('../chunk-IQPXHQQQ.cjs');
|
|
7
|
+
var chunk54FLQNUM_cjs = require('../chunk-54FLQNUM.cjs');
|
|
8
8
|
require('../chunk-G4UEPUGO.cjs');
|
|
9
9
|
require('../chunk-GVTZMA5C.cjs');
|
|
10
10
|
require('../chunk-QKZL3ONM.cjs');
|
|
11
11
|
require('../chunk-TBDXTV22.cjs');
|
|
12
12
|
var chunkSAENRNBJ_cjs = require('../chunk-SAENRNBJ.cjs');
|
|
13
13
|
require('../chunk-L24YIZY7.cjs');
|
|
14
|
-
require('../chunk-
|
|
15
|
-
require('../chunk-
|
|
16
|
-
require('../chunk-
|
|
14
|
+
require('../chunk-VA4OFR72.cjs');
|
|
15
|
+
require('../chunk-FR7KYWRO.cjs');
|
|
16
|
+
require('../chunk-A5SXCA62.cjs');
|
|
17
|
+
require('../chunk-TYF56RGB.cjs');
|
|
17
18
|
var chunkZ2Y65YOY_cjs = require('../chunk-Z2Y65YOY.cjs');
|
|
18
19
|
var module$1 = require('module');
|
|
19
20
|
var url = require('url');
|
|
@@ -23,7 +24,7 @@ var worker_threads = require('worker_threads');
|
|
|
23
24
|
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
|
|
|
25
26
|
// 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
|
+
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 MAX_HEADERS_BYTES = 16 * 1024;\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
|
|
|
28
29
|
// src/quickjs/task-runner.ts
|
|
29
30
|
var MAX_START_FAILURES = 3;
|
|
@@ -33,7 +34,7 @@ function quickjsModuleUrl() {
|
|
|
33
34
|
}
|
|
34
35
|
function parseResult(outcome) {
|
|
35
36
|
if (!chunkSAENRNBJ_cjs.isRecord(outcome))
|
|
36
|
-
return
|
|
37
|
+
return chunk672KMMBK_cjs.failedTaskResult("INTERNAL", "The task worker returned no outcome");
|
|
37
38
|
const typed = outcome;
|
|
38
39
|
if (typed.ok === true && typeof typed.resultJson === "string") {
|
|
39
40
|
try {
|
|
@@ -42,11 +43,11 @@ function parseResult(outcome) {
|
|
|
42
43
|
return parsed;
|
|
43
44
|
} catch {
|
|
44
45
|
}
|
|
45
|
-
return
|
|
46
|
+
return chunk672KMMBK_cjs.failedTaskResult("INTERNAL", "The runtime returned an invalid result");
|
|
46
47
|
}
|
|
47
48
|
if (typed.ok === false && typeof typed.cause === "string")
|
|
48
|
-
return
|
|
49
|
-
return
|
|
49
|
+
return chunk672KMMBK_cjs.failedTaskResult(typed.cause, String(typed.message));
|
|
50
|
+
return chunk672KMMBK_cjs.failedTaskResult("INTERNAL", "The task worker returned an invalid outcome");
|
|
50
51
|
}
|
|
51
52
|
function createWorkflowTaskRunner(options = {}) {
|
|
52
53
|
const poolSize = Math.max(1, Math.floor(options.poolSize ?? 4));
|
|
@@ -89,7 +90,7 @@ function createWorkflowTaskRunner(options = {}) {
|
|
|
89
90
|
if (slots.some((entry) => entry.ready)) return;
|
|
90
91
|
for (const job of queue.splice(0))
|
|
91
92
|
job.resolve(
|
|
92
|
-
|
|
93
|
+
chunk672KMMBK_cjs.failedTaskResult("INTERNAL", `The workflow task threads could not start: ${reason}`)
|
|
93
94
|
);
|
|
94
95
|
};
|
|
95
96
|
const spawn = () => {
|
|
@@ -121,7 +122,7 @@ function createWorkflowTaskRunner(options = {}) {
|
|
|
121
122
|
startFailed(slot, String(message["message"]));
|
|
122
123
|
return;
|
|
123
124
|
}
|
|
124
|
-
if (slot.job) finish(slot,
|
|
125
|
+
if (slot.job) finish(slot, chunk672KMMBK_cjs.failedTaskResult("INTERNAL", String(message["message"])));
|
|
125
126
|
replace(slot);
|
|
126
127
|
}
|
|
127
128
|
});
|
|
@@ -131,7 +132,7 @@ function createWorkflowTaskRunner(options = {}) {
|
|
|
131
132
|
if (slot.job)
|
|
132
133
|
finish(
|
|
133
134
|
slot,
|
|
134
|
-
|
|
135
|
+
chunk672KMMBK_cjs.failedTaskResult(
|
|
135
136
|
outOfMemory ? "ISOLATE_MEMORY" : "INTERNAL",
|
|
136
137
|
outOfMemory ? "The workflow task ran out of memory" : `The task thread failed: ${error.message}`
|
|
137
138
|
)
|
|
@@ -144,7 +145,7 @@ function createWorkflowTaskRunner(options = {}) {
|
|
|
144
145
|
startFailed(slot, "the thread exited while starting");
|
|
145
146
|
return;
|
|
146
147
|
}
|
|
147
|
-
if (slot.job) finish(slot,
|
|
148
|
+
if (slot.job) finish(slot, chunk672KMMBK_cjs.failedTaskResult("INTERNAL", "The task thread exited"));
|
|
148
149
|
replace(slot);
|
|
149
150
|
});
|
|
150
151
|
};
|
|
@@ -159,7 +160,7 @@ function createWorkflowTaskRunner(options = {}) {
|
|
|
159
160
|
slot.timer = setTimeout(() => {
|
|
160
161
|
finish(
|
|
161
162
|
slot,
|
|
162
|
-
|
|
163
|
+
chunk672KMMBK_cjs.failedTaskResult(
|
|
163
164
|
"TASK_TIMEOUT",
|
|
164
165
|
`The workflow task ran past its ${job.timeoutMs} ms budget`
|
|
165
166
|
)
|
|
@@ -182,7 +183,7 @@ function createWorkflowTaskRunner(options = {}) {
|
|
|
182
183
|
verified.set(buildId, code);
|
|
183
184
|
return true;
|
|
184
185
|
}
|
|
185
|
-
if (
|
|
186
|
+
if (chunk54FLQNUM_cjs.buildIdOf(code) !== buildId) return false;
|
|
186
187
|
verified.delete(buildId);
|
|
187
188
|
verified.set(buildId, code);
|
|
188
189
|
while (verified.size > cacheEntries) {
|
|
@@ -194,19 +195,19 @@ function createWorkflowTaskRunner(options = {}) {
|
|
|
194
195
|
};
|
|
195
196
|
return {
|
|
196
197
|
run(bundle, request, runOptions = {}) {
|
|
197
|
-
if (closed) return Promise.resolve(
|
|
198
|
+
if (closed) return Promise.resolve(chunk672KMMBK_cjs.failedTaskResult("INTERNAL", "The task runner is closed"));
|
|
198
199
|
const code = typeof bundle === "string" ? bundle : bundle.code;
|
|
199
200
|
const buildId = typeof bundle === "string" ? void 0 : bundle.buildId;
|
|
200
201
|
if (buildId !== void 0 && !verify(code, buildId))
|
|
201
202
|
return Promise.resolve(
|
|
202
|
-
|
|
203
|
+
chunk672KMMBK_cjs.failedTaskResult("BUNDLE_INTEGRITY", `The bundle does not hash to ${buildId}`)
|
|
203
204
|
);
|
|
204
205
|
let requestJson;
|
|
205
206
|
try {
|
|
206
207
|
requestJson = JSON.stringify(request);
|
|
207
208
|
} catch (error) {
|
|
208
209
|
return Promise.resolve(
|
|
209
|
-
|
|
210
|
+
chunk672KMMBK_cjs.failedTaskResult(
|
|
210
211
|
"INVALID_REQUEST",
|
|
211
212
|
error instanceof Error ? error.message : String(error)
|
|
212
213
|
)
|
|
@@ -226,10 +227,10 @@ function createWorkflowTaskRunner(options = {}) {
|
|
|
226
227
|
async close() {
|
|
227
228
|
closed = true;
|
|
228
229
|
for (const job of queue.splice(0))
|
|
229
|
-
job.resolve(
|
|
230
|
+
job.resolve(chunk672KMMBK_cjs.failedTaskResult("INTERNAL", "The task runner is closed"));
|
|
230
231
|
const all = slots.splice(0);
|
|
231
232
|
for (const slot of all)
|
|
232
|
-
if (slot.job) finish(slot,
|
|
233
|
+
if (slot.job) finish(slot, chunk672KMMBK_cjs.failedTaskResult("INTERNAL", "The task runner is closed"));
|
|
233
234
|
await Promise.all(all.map((slot) => slot.worker.terminate()));
|
|
234
235
|
}
|
|
235
236
|
};
|
|
@@ -240,7 +241,7 @@ function quickjsModuleUrl2() {
|
|
|
240
241
|
try {
|
|
241
242
|
return url.pathToFileURL(module$1.createRequire(chunkZ2Y65YOY_cjs.importMetaUrl).resolve("quickjs-emscripten")).href;
|
|
242
243
|
} catch (error) {
|
|
243
|
-
throw new
|
|
244
|
+
throw new chunkODZ2IAR2_cjs.LowerError(
|
|
244
245
|
`quickjs-emscripten cannot be resolved: ${error instanceof Error ? error.message : String(error)}`,
|
|
245
246
|
"crashed"
|
|
246
247
|
);
|
|
@@ -255,12 +256,12 @@ function createQuickJSEvaluator(options = {}) {
|
|
|
255
256
|
return {
|
|
256
257
|
format: "esm",
|
|
257
258
|
async evaluate(code) {
|
|
258
|
-
const outcome = await
|
|
259
|
+
const outcome = await chunkODZ2IAR2_cjs.runIsolateWorker({
|
|
259
260
|
source: QUICKJS_WORKER_SOURCE,
|
|
260
261
|
workerData: { code, limits, moduleUrl: quickjsModuleUrl2() },
|
|
261
262
|
timeoutMs: limits.timeoutMs
|
|
262
263
|
});
|
|
263
|
-
return
|
|
264
|
+
return chunkODZ2IAR2_cjs.outcomeToCollection(outcome);
|
|
264
265
|
}
|
|
265
266
|
};
|
|
266
267
|
}
|
package/dist/quickjs/index.d.cts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { E as Evaluator } from '../lower-
|
|
2
|
-
import {
|
|
1
|
+
import { E as Evaluator } from '../lower-BtRfIW2A.cjs';
|
|
2
|
+
import { az as WorkflowTaskRequest, aA as WorkflowTaskResult } from '../types-Bv2i4cBX.cjs';
|
|
3
3
|
import '../hash-CZkTXPCX.cjs';
|
|
4
|
-
import '../types-
|
|
5
|
-
import '../
|
|
6
|
-
import '../workflow-
|
|
7
|
-
import '../workflow-
|
|
4
|
+
import '../types-V7jEEUaL.cjs';
|
|
5
|
+
import '../collect-CcTCKqx6.cjs';
|
|
6
|
+
import '../workflow-BJPFv3cp.cjs';
|
|
7
|
+
import '../workflow-DS32Gtws.cjs';
|
|
8
8
|
import '../lower-types-DQNBfWQn.cjs';
|
|
9
9
|
import 'esbuild';
|
|
10
10
|
|
package/dist/quickjs/index.d.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { E as Evaluator } from '../lower-
|
|
2
|
-
import {
|
|
1
|
+
import { E as Evaluator } from '../lower-CpsMFOFX.js';
|
|
2
|
+
import { az as WorkflowTaskRequest, aA as WorkflowTaskResult } from '../types-DGx-b9eq.js';
|
|
3
3
|
import '../hash-CZkTXPCX.js';
|
|
4
|
-
import '../types-
|
|
5
|
-
import '../
|
|
6
|
-
import '../workflow-
|
|
7
|
-
import '../workflow-
|
|
4
|
+
import '../types-V7jEEUaL.js';
|
|
5
|
+
import '../collect-6NIEufHd.js';
|
|
6
|
+
import '../workflow-B18OeF7g.js';
|
|
7
|
+
import '../workflow-BGnv8SS6.js';
|
|
8
8
|
import '../lower-types-DQNBfWQn.js';
|
|
9
9
|
import 'esbuild';
|
|
10
10
|
|
package/dist/quickjs/index.js
CHANGED
|
@@ -1,17 +1,18 @@
|
|
|
1
|
-
import { runIsolateWorker, outcomeToCollection, LowerError } from '../chunk-
|
|
2
|
-
import '../chunk-
|
|
3
|
-
import { failedTaskResult } from '../chunk-
|
|
4
|
-
import '../chunk-
|
|
5
|
-
import { buildIdOf } from '../chunk-
|
|
1
|
+
import { runIsolateWorker, outcomeToCollection, LowerError } from '../chunk-5MFVJM76.js';
|
|
2
|
+
import '../chunk-6OLN6BMB.js';
|
|
3
|
+
import { failedTaskResult } from '../chunk-G5H32GIG.js';
|
|
4
|
+
import '../chunk-SR7TR5KX.js';
|
|
5
|
+
import { buildIdOf } from '../chunk-NWQ5WRLE.js';
|
|
6
6
|
import '../chunk-5LUIDMF4.js';
|
|
7
7
|
import '../chunk-JZ4TOOLN.js';
|
|
8
8
|
import '../chunk-E2VK7J2C.js';
|
|
9
9
|
import '../chunk-7AAZGVKD.js';
|
|
10
10
|
import { isRecord } from '../chunk-PMCM2OH4.js';
|
|
11
11
|
import '../chunk-4LYSEANA.js';
|
|
12
|
-
import '../chunk-
|
|
13
|
-
import '../chunk-
|
|
14
|
-
import '../chunk-
|
|
12
|
+
import '../chunk-C4F5KJTI.js';
|
|
13
|
+
import '../chunk-LNUQE6D6.js';
|
|
14
|
+
import '../chunk-AC6ZEXVR.js';
|
|
15
|
+
import '../chunk-5HIVIV53.js';
|
|
15
16
|
import { createRequire } from 'module';
|
|
16
17
|
import { pathToFileURL } from 'url';
|
|
17
18
|
import { Worker } from 'worker_threads';
|
|
@@ -20,7 +21,7 @@ import { Worker } from 'worker_threads';
|
|
|
20
21
|
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';
|
|
21
22
|
|
|
22
23
|
// src/generated/quickjs-task-worker-source.ts
|
|
23
|
-
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';
|
|
24
|
+
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 MAX_HEADERS_BYTES = 16 * 1024;\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';
|
|
24
25
|
|
|
25
26
|
// src/quickjs/task-runner.ts
|
|
26
27
|
var MAX_START_FAILURES = 3;
|