knitting 0.1.55 → 0.1.60

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.
Files changed (157) hide show
  1. package/README.md +254 -40
  2. package/knitting.d.ts +7 -797
  3. package/knitting.js +6 -9780
  4. package/map.md +31 -15
  5. package/package.json +20 -6
  6. package/process-shared-buffer.d.ts +1 -0
  7. package/process-shared-buffer.js +1 -0
  8. package/scripts/build-compiled-worker.ts +276 -0
  9. package/scripts/compiled-worker/porffor.d.ts +5 -0
  10. package/scripts/compiled-worker/runtime.ts +529 -0
  11. package/scripts/compiled-worker/task-shim.ts +32 -0
  12. package/shared-memory.d.ts +1 -155
  13. package/shared-memory.js +1 -1342
  14. package/src/api.d.ts +92 -0
  15. package/src/api.js +798 -0
  16. package/src/common/envelope.d.ts +17 -0
  17. package/src/common/envelope.js +22 -0
  18. package/src/common/module-url.d.ts +2 -0
  19. package/src/common/module-url.js +52 -0
  20. package/src/common/node-compat.d.ts +22 -0
  21. package/src/common/node-compat.js +24 -0
  22. package/src/common/path-canonical.d.ts +6 -0
  23. package/src/common/path-canonical.js +55 -0
  24. package/src/common/runtime.d.ts +16 -0
  25. package/src/common/runtime.js +105 -0
  26. package/src/common/shared-buffer-region.d.ts +11 -0
  27. package/src/common/shared-buffer-region.js +21 -0
  28. package/src/common/shared-buffer-text.d.ts +16 -0
  29. package/src/common/shared-buffer-text.js +65 -0
  30. package/src/common/task-source.d.ts +5 -0
  31. package/src/common/task-source.js +100 -0
  32. package/src/common/task-symbol.d.ts +1 -0
  33. package/src/common/task-symbol.js +1 -0
  34. package/src/common/with-resolvers.d.ts +9 -0
  35. package/src/common/with-resolvers.js +23 -0
  36. package/src/common/worker-runtime.d.ts +42 -0
  37. package/src/common/worker-runtime.js +70 -0
  38. package/src/connections/buffer-reference-native.d.ts +56 -0
  39. package/src/connections/buffer-reference-native.js +241 -0
  40. package/src/connections/buffer-reference.d.ts +99 -0
  41. package/src/connections/buffer-reference.js +575 -0
  42. package/src/connections/bun.d.ts +22 -0
  43. package/src/connections/bun.js +225 -0
  44. package/src/connections/deno.d.ts +24 -0
  45. package/src/connections/deno.js +226 -0
  46. package/src/connections/external-array-buffer.d.ts +2 -0
  47. package/src/connections/external-array-buffer.js +33 -0
  48. package/src/connections/file-descriptor.d.ts +39 -0
  49. package/src/connections/file-descriptor.js +161 -0
  50. package/src/connections/index.d.ts +4 -0
  51. package/src/connections/index.js +4 -0
  52. package/src/connections/node-addons.d.ts +16 -0
  53. package/src/connections/node-addons.js +92 -0
  54. package/src/connections/node-buffer-pointer.d.ts +20 -0
  55. package/src/connections/node-buffer-pointer.js +16 -0
  56. package/src/connections/node-ffi-api.d.ts +19 -0
  57. package/src/connections/node-ffi-api.js +28 -0
  58. package/src/connections/node-ffi.d.ts +27 -0
  59. package/src/connections/node-ffi.js +262 -0
  60. package/src/connections/node.d.ts +30 -0
  61. package/src/connections/node.js +62 -0
  62. package/src/connections/numeric-array.d.ts +5 -0
  63. package/src/connections/numeric-array.js +17 -0
  64. package/src/connections/package-assets.d.ts +2 -0
  65. package/src/connections/package-assets.js +55 -0
  66. package/src/connections/posix.d.ts +74 -0
  67. package/src/connections/posix.js +178 -0
  68. package/src/connections/process-shared-buffer.d.ts +76 -0
  69. package/src/connections/process-shared-buffer.js +245 -0
  70. package/src/connections/shared-array-buffer-payload.d.ts +36 -0
  71. package/src/connections/shared-array-buffer-payload.js +235 -0
  72. package/src/connections/types.d.ts +54 -0
  73. package/src/connections/types.js +37 -0
  74. package/src/connections/windows.d.ts +37 -0
  75. package/src/connections/windows.js +245 -0
  76. package/src/debug/env-diff.d.ts +26 -0
  77. package/src/debug/env-diff.js +49 -0
  78. package/src/debug/gate.d.ts +18 -0
  79. package/src/debug/gate.js +69 -0
  80. package/src/debug/handle.d.ts +23 -0
  81. package/src/debug/handle.js +48 -0
  82. package/src/error.d.ts +14 -0
  83. package/src/error.js +50 -0
  84. package/src/ipc/tools/ring-queue.d.ts +33 -0
  85. package/src/ipc/tools/ring-queue.js +159 -0
  86. package/src/ipc/transport/shared-memory.d.ts +23 -0
  87. package/src/ipc/transport/shared-memory.js +35 -0
  88. package/src/memory/byte-carpet.d.ts +73 -0
  89. package/src/memory/byte-carpet.js +157 -0
  90. package/src/memory/lock.d.ts +213 -0
  91. package/src/memory/lock.js +760 -0
  92. package/src/memory/payload-config.d.ts +31 -0
  93. package/src/memory/payload-config.js +67 -0
  94. package/src/memory/payloadCodec.d.ts +55 -0
  95. package/src/memory/payloadCodec.js +1473 -0
  96. package/src/memory/regionRegistry.d.ts +17 -0
  97. package/src/memory/regionRegistry.js +285 -0
  98. package/src/memory/shared-buffer-io.d.ts +55 -0
  99. package/src/memory/shared-buffer-io.js +403 -0
  100. package/src/permission/compatibility.d.ts +28 -0
  101. package/src/permission/compatibility.js +239 -0
  102. package/src/permission/index.d.ts +4 -0
  103. package/src/permission/index.js +3 -0
  104. package/src/permission/protocol.d.ts +167 -0
  105. package/src/permission/protocol.js +690 -0
  106. package/src/runtime/balancer.d.ts +19 -0
  107. package/src/runtime/balancer.js +149 -0
  108. package/src/runtime/compiled-artifact.d.ts +21 -0
  109. package/src/runtime/compiled-artifact.js +260 -0
  110. package/src/runtime/compiled-builder.d.ts +8 -0
  111. package/src/runtime/compiled-builder.js +42 -0
  112. package/src/runtime/compiled-worker.d.ts +27 -0
  113. package/src/runtime/compiled-worker.js +562 -0
  114. package/src/runtime/dispatcher.d.ts +40 -0
  115. package/src/runtime/dispatcher.js +142 -0
  116. package/src/runtime/inline-executor.d.ts +10 -0
  117. package/src/runtime/inline-executor.js +294 -0
  118. package/src/runtime/pool.d.ts +44 -0
  119. package/src/runtime/pool.js +472 -0
  120. package/src/runtime/process-worker.d.ts +92 -0
  121. package/src/runtime/process-worker.js +713 -0
  122. package/src/runtime/tx-queue.d.ts +28 -0
  123. package/src/runtime/tx-queue.js +158 -0
  124. package/src/shared/abortSignal.d.ts +23 -0
  125. package/src/shared/abortSignal.js +134 -0
  126. package/src/types.d.ts +399 -0
  127. package/src/types.js +2 -0
  128. package/src/utils/http.d.ts +29 -0
  129. package/src/utils/http.js +100 -0
  130. package/src/worker/bootstrap.d.ts +5 -0
  131. package/src/worker/bootstrap.js +78 -0
  132. package/src/worker/composable-runners.d.ts +12 -0
  133. package/src/worker/composable-runners.js +98 -0
  134. package/src/worker/loop.d.ts +3 -0
  135. package/src/worker/loop.js +395 -0
  136. package/src/worker/process-worker-bootstrap.d.ts +8 -0
  137. package/src/worker/process-worker-bootstrap.js +160 -0
  138. package/src/worker/rx-queue.d.ts +25 -0
  139. package/src/worker/rx-queue.js +173 -0
  140. package/src/worker/safety/index.d.ts +4 -0
  141. package/src/worker/safety/index.js +4 -0
  142. package/src/worker/safety/performance.d.ts +1 -0
  143. package/src/worker/safety/performance.js +17 -0
  144. package/src/worker/safety/process.d.ts +2 -0
  145. package/src/worker/safety/process.js +79 -0
  146. package/src/worker/safety/startup.d.ts +16 -0
  147. package/src/worker/safety/startup.js +30 -0
  148. package/src/worker/safety/worker-data.d.ts +2 -0
  149. package/src/worker/safety/worker-data.js +36 -0
  150. package/src/worker/task-loader.d.ts +28 -0
  151. package/src/worker/task-loader.js +76 -0
  152. package/src/worker/timers.d.ts +18 -0
  153. package/src/worker/timers.js +118 -0
  154. package/unsafe.d.ts +1 -71
  155. package/unsafe.js +1 -878
  156. package/utils.d.ts +1 -31
  157. package/utils.js +1 -116
@@ -0,0 +1,149 @@
1
+ const selectStrategy = (contexts, handlers, strategy) => {
2
+ switch (strategy ?? "roundRobin") {
3
+ case "roundRobin":
4
+ case "robinRound": // legacy alias
5
+ return roundRobin(contexts)(handlers)(handlers.length);
6
+ case "firstIdle":
7
+ return firstIdle(contexts)(handlers)(handlers.length);
8
+ case "randomLane":
9
+ return randomLane(contexts)(handlers)(handlers.length);
10
+ case "firstIdleOrRandom":
11
+ return firstIdleRandom(contexts)(handlers)(handlers.length);
12
+ }
13
+ // Unreachable code, but guarded for safety.
14
+ throw new Error(`Unknown balancer: ${strategy}`);
15
+ };
16
+ export const managerMethod = ({ contexts, balancer, handlers, inlinerGate, }) => {
17
+ const strategy = typeof balancer === "object" && balancer != null
18
+ ? balancer.strategy
19
+ : balancer;
20
+ if (contexts.length < 2) {
21
+ throw new Error(contexts.length === 0
22
+ ? "No threads available."
23
+ : "Cannot rotate with a single thread.");
24
+ }
25
+ if (handlers.length === 0) {
26
+ throw new Error("No handlers provided.");
27
+ }
28
+ const allInvoker = selectStrategy(contexts, handlers, strategy);
29
+ if (!inlinerGate) {
30
+ return allInvoker;
31
+ }
32
+ const inlinerIndex = inlinerGate.index | 0;
33
+ const threshold = Number.isFinite(inlinerGate.threshold)
34
+ ? Math.max(1, Math.floor(inlinerGate.threshold))
35
+ : 1;
36
+ if (threshold <= 1 || inlinerIndex < 0 || inlinerIndex >= handlers.length) {
37
+ return allInvoker;
38
+ }
39
+ const workerLaneCount = handlers.length - 1;
40
+ if (workerLaneCount <= 0) {
41
+ return allInvoker;
42
+ }
43
+ const workerHandlers = new Array(workerLaneCount);
44
+ const workerContexts = new Array(workerLaneCount);
45
+ for (let source = 0, lane = 0; source < handlers.length; source += 1) {
46
+ if (source === inlinerIndex)
47
+ continue;
48
+ workerHandlers[lane] = handlers[source];
49
+ workerContexts[lane] = contexts[source];
50
+ lane += 1;
51
+ }
52
+ const workerOnlyInvoker = selectStrategy(workerContexts, workerHandlers, strategy);
53
+ let inFlight = 0;
54
+ const releaseResolved = (value) => {
55
+ inFlight -= 1;
56
+ return value;
57
+ };
58
+ const releaseRejected = (error) => {
59
+ inFlight -= 1;
60
+ throw error;
61
+ };
62
+ return (args) => {
63
+ inFlight += 1;
64
+ const invoker = inFlight >= threshold ? allInvoker : workerOnlyInvoker;
65
+ try {
66
+ return invoker(args).then(releaseResolved, releaseRejected);
67
+ }
68
+ catch (error) {
69
+ inFlight -= 1;
70
+ throw error;
71
+ }
72
+ };
73
+ };
74
+ export function roundRobin(_contexts) {
75
+ return (handlers) => {
76
+ return (max) => {
77
+ const top = Math.min(max, handlers.length);
78
+ if (top <= 1) {
79
+ return (args) => handlers[0](args);
80
+ }
81
+ let rrCursor = 0;
82
+ return (args) => {
83
+ const lane = rrCursor;
84
+ rrCursor += 1;
85
+ if (rrCursor === top)
86
+ rrCursor = 0;
87
+ return handlers[lane](args);
88
+ };
89
+ };
90
+ };
91
+ }
92
+ export function firstIdle(contexts) {
93
+ const isSolved = contexts.map((ctx) => ctx.txIdle);
94
+ return (handlers) => {
95
+ return (max) => {
96
+ const laneCount = Math.min(max, handlers.length);
97
+ if (laneCount <= 1) {
98
+ return (args) => handlers[0](args);
99
+ }
100
+ let rrCursor = 0;
101
+ return (args) => {
102
+ for (let lane = 0; lane < laneCount; lane += 1) {
103
+ if (isSolved[lane]()) {
104
+ return handlers[lane](args);
105
+ }
106
+ }
107
+ const fallback = rrCursor;
108
+ rrCursor += 1;
109
+ if (rrCursor === laneCount)
110
+ rrCursor = 0;
111
+ return handlers[fallback](args);
112
+ };
113
+ };
114
+ };
115
+ }
116
+ export const randomLane = (_) => {
117
+ return (handlers) => {
118
+ return (max) => {
119
+ const laneCount = Math.min(max, handlers.length);
120
+ if (laneCount <= 1) {
121
+ return (args) => handlers[0](args);
122
+ }
123
+ return (args) => {
124
+ const lane = (Math.random() * laneCount) | 0;
125
+ return handlers[lane](args);
126
+ };
127
+ };
128
+ };
129
+ };
130
+ export function firstIdleRandom(contexts) {
131
+ const isSolved = contexts.map((ctx) => ctx.txIdle);
132
+ return (handlers) => {
133
+ return (max) => {
134
+ const laneCount = Math.min(max, handlers.length);
135
+ if (laneCount <= 1) {
136
+ return (args) => handlers[0](args);
137
+ }
138
+ return (args) => {
139
+ for (let lane = 0; lane < laneCount; lane += 1) {
140
+ if (isSolved[lane]()) {
141
+ return handlers[lane](args);
142
+ }
143
+ }
144
+ const fallback = (Math.random() * laneCount) | 0;
145
+ return handlers[fallback](args);
146
+ };
147
+ };
148
+ };
149
+ }
@@ -0,0 +1,21 @@
1
+ import type { CompiledWorkerCheck, CompiledWorkerOptions } from "../types.js";
2
+ export declare const COMPILED_WORKER_FORMAT = "knitting-compiled-worker";
3
+ export declare const COMPILED_WORKER_FORMAT_VERSION = 1;
4
+ export declare const COMPILED_WORKER_PROTOCOL = "knitting-number-v1";
5
+ export declare const COMPILED_WORKER_JSON_PROTOCOL = "knitting-json-v1";
6
+ export declare const COMPILED_WORKER_EXTENSION = ".knt";
7
+ export type CompiledWorkerTask = {
8
+ index: number;
9
+ exportName: string;
10
+ };
11
+ export type ArtifactInspection = CompiledWorkerCheck & {
12
+ artifactHref: string;
13
+ manifestHref: string;
14
+ taskEntries?: CompiledWorkerTask[];
15
+ };
16
+ export declare const defaultCompiledWorkerArtifact: (source: string | URL) => string;
17
+ export declare const inspectCompiledWorkerArtifact: ({ source, options, requiredTasks, }: {
18
+ source: string | URL;
19
+ options?: CompiledWorkerOptions;
20
+ requiredTasks?: readonly string[];
21
+ }) => ArtifactInspection;
@@ -0,0 +1,260 @@
1
+ import { getNodeBuiltinModule, getNodeProcess } from "../common/node-compat.js";
2
+ import { toModuleUrl } from "../common/module-url.js";
3
+ export const COMPILED_WORKER_FORMAT = "knitting-compiled-worker";
4
+ export const COMPILED_WORKER_FORMAT_VERSION = 1;
5
+ export const COMPILED_WORKER_PROTOCOL = "knitting-number-v1";
6
+ export const COMPILED_WORKER_JSON_PROTOCOL = "knitting-json-v1";
7
+ export const COMPILED_WORKER_EXTENSION = ".knt";
8
+ const deno = globalThis.Deno;
9
+ const normalizeArch = (arch) => {
10
+ if (arch === "x86_64")
11
+ return "x64";
12
+ if (arch === "aarch64")
13
+ return "arm64";
14
+ return arch ?? "unknown";
15
+ };
16
+ const runtimeTarget = () => {
17
+ const process = getNodeProcess();
18
+ if (process !== undefined) {
19
+ return {
20
+ platform: process.platform ?? "unknown",
21
+ arch: normalizeArch(process.arch),
22
+ };
23
+ }
24
+ return {
25
+ platform: deno?.build?.os ?? "unknown",
26
+ arch: normalizeArch(deno?.build?.arch),
27
+ };
28
+ };
29
+ const normalizeSourceHref = (source) => source instanceof URL ? source.href : toModuleUrl(source);
30
+ const resolveHref = (value, base) => {
31
+ try {
32
+ return new URL(value).href;
33
+ }
34
+ catch {
35
+ return new URL(value, base).href;
36
+ }
37
+ };
38
+ export const defaultCompiledWorkerArtifact = (source) => {
39
+ const url = new URL(normalizeSourceHref(source));
40
+ url.search = "";
41
+ url.hash = "";
42
+ url.pathname = url.pathname.replace(/\.[^./]+$/, "") +
43
+ COMPILED_WORKER_EXTENSION;
44
+ return url.href;
45
+ };
46
+ const artifactHrefs = (source, options = {}) => {
47
+ const sourceHref = normalizeSourceHref(source);
48
+ const artifactHref = options.artifact === undefined
49
+ ? defaultCompiledWorkerArtifact(sourceHref)
50
+ : resolveHref(options.artifact, sourceHref);
51
+ const manifestHref = options.manifest === undefined
52
+ ? artifactHref + ".json"
53
+ : resolveHref(options.manifest, artifactHref);
54
+ return { artifactHref, manifestHref };
55
+ };
56
+ const filePath = (href) => {
57
+ const converter = getNodeBuiltinModule("node:url")?.fileURLToPath;
58
+ if (converter !== undefined)
59
+ return converter(href);
60
+ const url = new URL(href);
61
+ if (url.protocol !== "file:") {
62
+ throw new Error("Compiled worker artifact must use file:, got " + url.protocol);
63
+ }
64
+ return decodeURIComponent(url.pathname);
65
+ };
66
+ const readTextFile = (path) => {
67
+ const fs = getNodeBuiltinModule("node:fs");
68
+ if (fs !== undefined)
69
+ return fs.readFileSync(path, "utf8");
70
+ if (deno?.readTextFileSync !== undefined)
71
+ return deno.readTextFileSync(path);
72
+ throw new Error("Synchronous filesystem access is unavailable");
73
+ };
74
+ const inspectExecutable = (path) => {
75
+ try {
76
+ const fs = getNodeBuiltinModule("node:fs");
77
+ if (fs !== undefined) {
78
+ const stat = fs.statSync(path);
79
+ if (!stat.isFile())
80
+ return "artifact is not a file";
81
+ if (runtimeTarget().platform !== "win32" && (stat.mode & 0o111) === 0) {
82
+ return "artifact is not executable";
83
+ }
84
+ return undefined;
85
+ }
86
+ if (deno?.statSync !== undefined) {
87
+ const stat = deno.statSync(path);
88
+ if (!stat.isFile)
89
+ return "artifact is not a file";
90
+ if (stat.mode !== null && (stat.mode & 0o111) === 0) {
91
+ return "artifact is not executable";
92
+ }
93
+ return undefined;
94
+ }
95
+ return "filesystem metadata is unavailable";
96
+ }
97
+ catch (error) {
98
+ const message = String(error?.message ?? error);
99
+ return "artifact is unavailable: " + message;
100
+ }
101
+ };
102
+ const compilerLabel = (compiler) => {
103
+ if (typeof compiler === "string" && compiler.length > 0)
104
+ return compiler;
105
+ if (compiler !== null && typeof compiler === "object" &&
106
+ typeof compiler.name === "string" &&
107
+ compiler.name.length > 0 &&
108
+ typeof compiler.version === "string") {
109
+ const value = compiler;
110
+ return (value.name + " " + value.version).trim();
111
+ }
112
+ return undefined;
113
+ };
114
+ export const inspectCompiledWorkerArtifact = ({ source, options, requiredTasks, }) => {
115
+ const sourceHref = normalizeSourceHref(source);
116
+ const { artifactHref, manifestHref } = artifactHrefs(sourceHref, options);
117
+ let artifact;
118
+ let manifest;
119
+ try {
120
+ artifact = filePath(artifactHref);
121
+ manifest = filePath(manifestHref);
122
+ }
123
+ catch (error) {
124
+ const message = String(error?.message ?? error);
125
+ return {
126
+ compiled: false,
127
+ artifact: artifactHref,
128
+ manifest: manifestHref,
129
+ artifactHref,
130
+ manifestHref,
131
+ reason: message,
132
+ };
133
+ }
134
+ const base = {
135
+ compiled: false,
136
+ artifact,
137
+ manifest,
138
+ artifactHref,
139
+ manifestHref,
140
+ };
141
+ const executableProblem = inspectExecutable(artifact);
142
+ if (executableProblem !== undefined) {
143
+ return { ...base, reason: executableProblem };
144
+ }
145
+ let parsed;
146
+ try {
147
+ parsed = JSON.parse(readTextFile(manifest));
148
+ }
149
+ catch (error) {
150
+ const message = String(error?.message ?? error);
151
+ return {
152
+ ...base,
153
+ reason: "manifest is unavailable or invalid: " + message,
154
+ };
155
+ }
156
+ if (parsed === null || typeof parsed !== "object" || Array.isArray(parsed)) {
157
+ return { ...base, reason: "manifest root must be an object" };
158
+ }
159
+ const workerManifest = parsed;
160
+ const compiler = compilerLabel(workerManifest.compiler);
161
+ const details = {
162
+ compiler,
163
+ protocol: typeof workerManifest.protocol === "string"
164
+ ? workerManifest.protocol
165
+ : undefined,
166
+ };
167
+ if (workerManifest.format !== COMPILED_WORKER_FORMAT ||
168
+ workerManifest.version !== COMPILED_WORKER_FORMAT_VERSION) {
169
+ return { ...base, ...details, reason: "unsupported manifest format" };
170
+ }
171
+ if (workerManifest.protocol !== COMPILED_WORKER_PROTOCOL &&
172
+ workerManifest.protocol !== COMPILED_WORKER_JSON_PROTOCOL) {
173
+ return { ...base, ...details, reason: "unsupported worker protocol" };
174
+ }
175
+ if (compiler === undefined) {
176
+ return { ...base, ...details, reason: "manifest compiler is invalid" };
177
+ }
178
+ const target = runtimeTarget();
179
+ if (workerManifest.target?.platform !== target.platform ||
180
+ normalizeArch(workerManifest.target?.arch) !== target.arch) {
181
+ return {
182
+ ...base,
183
+ ...details,
184
+ reason: "artifact target " +
185
+ (workerManifest.target?.platform ?? "unknown") + "/" +
186
+ (workerManifest.target?.arch ?? "unknown") + " does not match " +
187
+ target.platform + "/" + target.arch,
188
+ };
189
+ }
190
+ if (!Array.isArray(workerManifest.tasks) || workerManifest.tasks.length === 0) {
191
+ return { ...base, ...details, reason: "manifest has no tasks" };
192
+ }
193
+ const indices = new Set();
194
+ const taskNames = new Set();
195
+ for (const task of workerManifest.tasks) {
196
+ if (!Number.isSafeInteger(task?.index) || task.index < 0 ||
197
+ task.index > 0x7fff_ffff ||
198
+ typeof task.exportName !== "string" || task.exportName.length === 0 ||
199
+ indices.has(task.index) || taskNames.has(task.exportName)) {
200
+ return { ...base, ...details, reason: "manifest task table is invalid" };
201
+ }
202
+ indices.add(task.index);
203
+ taskNames.add(task.exportName);
204
+ }
205
+ if (typeof workerManifest.source !== "string" ||
206
+ workerManifest.source.length === 0) {
207
+ return { ...base, ...details, reason: "manifest source is invalid" };
208
+ }
209
+ let manifestSource;
210
+ try {
211
+ manifestSource = resolveHref(workerManifest.source.replace(/\\/g, "/"), artifactHref);
212
+ }
213
+ catch {
214
+ return { ...base, ...details, reason: "manifest source is invalid" };
215
+ }
216
+ if (manifestSource !== sourceHref) {
217
+ return {
218
+ ...base,
219
+ ...details,
220
+ tasks: [...taskNames],
221
+ reason: "manifest was built for a different task module",
222
+ };
223
+ }
224
+ if (Number.isFinite(workerManifest.sourceMtimeMs)) {
225
+ try {
226
+ const sourcePath = filePath(sourceHref);
227
+ const fs = getNodeBuiltinModule("node:fs");
228
+ const currentMtime = fs?.statSync(sourcePath).mtimeMs ??
229
+ deno?.statSync?.(sourcePath).mtime?.getTime();
230
+ if (currentMtime !== undefined &&
231
+ currentMtime > workerManifest.sourceMtimeMs + 0.5) {
232
+ return {
233
+ ...base,
234
+ ...details,
235
+ tasks: [...taskNames],
236
+ reason: "task module changed after the artifact was built",
237
+ };
238
+ }
239
+ }
240
+ catch {
241
+ return { ...base, ...details, reason: "task module is unavailable" };
242
+ }
243
+ }
244
+ const missing = requiredTasks?.filter((name) => !taskNames.has(name)) ?? [];
245
+ if (missing.length > 0) {
246
+ return {
247
+ ...base,
248
+ ...details,
249
+ tasks: [...taskNames],
250
+ reason: "compiled artifact is missing tasks: " + missing.join(", "),
251
+ };
252
+ }
253
+ return {
254
+ ...base,
255
+ ...details,
256
+ compiled: true,
257
+ tasks: [...taskNames],
258
+ taskEntries: workerManifest.tasks,
259
+ };
260
+ };
@@ -0,0 +1,8 @@
1
+ import type { CompiledWorkerOptions } from "../types.js";
2
+ import type { ArtifactInspection } from "./compiled-artifact.js";
3
+ export declare const buildCompiledWorkerArtifact: ({ inspection, source, tasks, options, }: {
4
+ inspection: ArtifactInspection;
5
+ source: string;
6
+ tasks: readonly string[];
7
+ options?: CompiledWorkerOptions;
8
+ }) => void;
@@ -0,0 +1,42 @@
1
+ import { getNodeBuiltinModule, getNodeProcess } from "../common/node-compat.js";
2
+ const filePath = (href) => {
3
+ const converter = getNodeBuiltinModule("node:url")?.fileURLToPath;
4
+ if (converter !== undefined)
5
+ return converter(href);
6
+ return decodeURIComponent(new URL(href).pathname);
7
+ };
8
+ const runtimeExecutable = () => {
9
+ const process = getNodeProcess();
10
+ return process?.versions?.bun !== undefined && process.execPath !== undefined
11
+ ? process.execPath
12
+ : "bun";
13
+ };
14
+ export const buildCompiledWorkerArtifact = ({ inspection, source, tasks, options, }) => {
15
+ const childProcess = getNodeBuiltinModule("node:child_process");
16
+ if (childProcess === undefined) {
17
+ throw new Error("automatic compilation requires Bun or Node child processes");
18
+ }
19
+ const builder = filePath(new URL("../../scripts/build-compiled-worker.ts", import.meta.url).href);
20
+ const args = [
21
+ builder,
22
+ "--module",
23
+ filePath(source),
24
+ "--out",
25
+ filePath(inspection.artifactHref),
26
+ "--manifest",
27
+ filePath(inspection.manifestHref),
28
+ "--tasks",
29
+ tasks.join(","),
30
+ ];
31
+ if (options?.compiler !== undefined) {
32
+ args.push("--porf", options.compiler);
33
+ }
34
+ const result = childProcess.spawnSync(runtimeExecutable(), args, {
35
+ stdio: "inherit",
36
+ });
37
+ if (result.error !== undefined)
38
+ throw result.error;
39
+ if (result.status !== 0) {
40
+ throw new Error("compiled worker build exited with code " + result.status);
41
+ }
42
+ };
@@ -0,0 +1,27 @@
1
+ import { type SignalAbortStore } from "../shared/abortSignal.js";
2
+ import type { WorkerContext, WorkerSettings } from "../types.js";
3
+ type CompiledAbortChannel = SignalAbortStore & {
4
+ /** Passed to the child so it can map the same bitmap. */
5
+ environment: Record<string, string>;
6
+ close: () => void;
7
+ };
8
+ /**
9
+ * Host half of the abort bitmap. Slot bookkeeping is the same allocator every
10
+ * other lane uses; only the backing store differs, because a compiled child is
11
+ * a separate process and reads the words through named POSIX shared memory.
12
+ */
13
+ export declare const createCompiledAbortChannel: (requestedMax?: number) => CompiledAbortChannel;
14
+ type CompiledWorkerContext = WorkerContext & {
15
+ dispatcherCheck?: never;
16
+ laneWake?: never;
17
+ bindSend?: never;
18
+ };
19
+ export declare const spawnCompiledWorkerContext: ({ list, names, workerOptions, hostDebug, abortSignalCapacity, usesAbortSignal, }: {
20
+ list: string[];
21
+ names: string[];
22
+ workerOptions: WorkerSettings;
23
+ hostDebug?: (message: string) => void;
24
+ abortSignalCapacity?: number;
25
+ usesAbortSignal?: boolean;
26
+ }) => CompiledWorkerContext;
27
+ export {};