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
package/map.md CHANGED
@@ -20,6 +20,8 @@ The core flow is:
20
20
  `importTask`, `isMain`, `Envelope`, and `workerMainLoop`.
21
21
  - `shared-memory.ts`: Secondary public export for process-safe shared-memory
22
22
  helpers.
23
+ - `process-shared-buffer.ts`: Backward-compatible alias for the shared-memory
24
+ public export.
23
25
  - `unsafe.ts`: Public export for experimental lower-level capabilities such as
24
26
  `BufferReference`.
25
27
  - `utils.ts`: Public export for request/response buffer conversion helpers.
@@ -34,11 +36,13 @@ The core flow is:
34
36
 
35
37
  ## Build And Scripts
36
38
 
37
- - `build.ts`: Bundles each public entry to one root `.js` file with Bun for a
38
- Node ESM target.
39
- - `tsconfig.npm.json`: TypeScript config used by npm declaration bundling.
40
- - `scripts/build-declarations.mjs`: Bundles each public entry to one root
41
- `.d.ts` file for npm consumers.
39
+ - `build.ts`: Runs the generated-output cleaner, then compiles public entries
40
+ and `src/**/*.ts` to `.js` and `.d.ts` files with TypeScript.
41
+ - `scripts/clean-generated.ts`: Removes npm-generated root entry files and
42
+ generated `.js`/`.d.ts` files under `src/`; exposed as `npm run clean`.
43
+ - `tsconfig.npm.json`: TypeScript config used by the npm release build.
44
+ - `scripts/rewrite-declaration-imports.mjs`: Rewrites generated declaration
45
+ imports from `.ts` to `.js` so npm consumers resolve the compiled files.
42
46
  - `scripts/build-native-addons.ts`: Compiles the native Node addons into
43
47
  `build/Release/` on Linux, macOS, and Windows. It finds Node headers/libs,
44
48
  splits user flags, builds the shared-memory and futex addons, and emits the
@@ -63,8 +67,8 @@ The core flow is:
63
67
  - `docs/AGENTS.md`: Agent/contributor orientation, invariants, and workflow
64
68
  notes.
65
69
  - `docs/CLAUDE.md`: Pointer to the shared agent guidance.
66
- - `docs/buffer-reference-ownership-move.md`: Design record for
67
- `BufferReference` ownership transfer.
70
+ - `docs/buffer-reference-ownership-move.md`: Design record for `BufferReference`
71
+ ownership transfer.
68
72
  - `docs/knitting.pdf`: Longer-form project design/theory document.
69
73
 
70
74
  ## Public API Layer
@@ -118,6 +122,12 @@ The core flow is:
118
122
  - `src/runtime/process-worker.ts`: Process-worker spawning, command/runtime
119
123
  selection, process shared-memory layout, inherited/named mapping metadata, and
120
124
  child boot payload construction.
125
+ - `src/runtime/compiled-artifact.ts`: Resolves `.knt` executables and validates
126
+ their versioned manifests, source/task identity, target platform, and execute
127
+ permission without launching them.
128
+ - `src/runtime/compiled-worker.ts`: Experimental host adapter for compiled
129
+ worker executables. Spawns the artifact and maps pool calls onto the current
130
+ numeric framed-pipe protocol.
121
131
 
122
132
  ## Worker Side
123
133
 
@@ -194,14 +204,16 @@ The core flow is:
194
204
  parsing, mapping support, and descriptor lifecycle helpers.
195
205
  - `src/connections/node-addons.ts`: Native addon specifier resolution for
196
206
  committed Node ABI prebuilds with `build/Release` fallback loading.
197
- - `src/connections/node.ts`: Loads POSIX Node native addons and exposes Node
198
- shared memory, mapping, unlink, and futex primitives.
207
+ - `src/connections/node.ts`: Selects the Node 22/24 addon backend or the Node 26
208
+ FFI backend and exposes shared-memory and futex primitives.
209
+ - `src/connections/node-ffi.ts`: Node 26 `node:ffi` implementation for POSIX
210
+ shared-memory creation, mapping, cleanup, and buffer-pointer aliases.
199
211
  - `src/connections/bun.ts`: Bun FFI implementation for POSIX shared memory.
200
212
  - `src/connections/deno.ts`: Deno FFI implementation for POSIX shared memory.
201
213
  - `src/connections/posix.ts`: POSIX constants, shared-memory naming, libc path
202
214
  detection, and close-on-exec helpers.
203
215
  - `src/connections/windows.ts`: Windows FFI loader and named file-mapping
204
- primitives used by Deno and Bun.
216
+ primitives used by Node 26, Deno, and Bun.
205
217
  - `src/knitting_shared_memory.cc`: Native Node addon for shared-memory create,
206
218
  map, unlink, and descriptor operations, including Windows named mappings.
207
219
  - `src/knitting_shm.cc`: Native Node addon for futex/wait helpers used by parked
@@ -211,8 +223,8 @@ The core flow is:
211
223
  FFI runtimes.
212
224
  - `prebuilds/*/*.node`: Tracked Node native-addon prebuilds for supported
213
225
  platform/Node ABI combinations.
214
- - `prebuilds/win32-x64/*.dll`: Tracked Windows FFI DLL prebuild used by Bun and
215
- Deno shared-memory primitives on Windows.
226
+ - `prebuilds/win32-x64/*.dll`: Tracked Windows FFI DLL prebuild used by Node 26,
227
+ Bun, and Deno shared-memory primitives on Windows.
216
228
 
217
229
  ## Permissions
218
230
 
@@ -269,6 +281,8 @@ The core flow is:
269
281
  - `test/_runner.ts`: Runtime-neutral test runner shim used by the test suite.
270
282
  - `test/abortSignal.test.ts`: Shared abort bitset behavior.
271
283
  - `test/api-cap.test.ts`: API limits such as maximum task id count.
284
+ - `test/compiled-worker.test.ts`: Compiled-artifact validation, public pool
285
+ integration, source-derived `.knt` paths, and unsupported-feature guards.
272
286
  - `test/shared-buffer-io.test.ts`: Shared-buffer IO read/write behavior.
273
287
  - `test/file-descriptor.test.ts`: File descriptor metadata and mapping behavior.
274
288
  - `test/inliner.test.ts`: Inline executor behavior and thresholds.
@@ -309,9 +323,11 @@ The core flow is:
309
323
 
310
324
  - `build/Release/*.node`: Native addon output produced by
311
325
  `scripts/build-native-addons.ts`.
312
- - `knitting.js`, `knitting.d.ts`, `shared-memory.js`, `shared-memory.d.ts`,
313
- `unsafe.js`, `unsafe.d.ts`, `utils.js`, and `utils.d.ts`: npm release build
314
- artifacts produced by `build.ts` and `scripts/build-declarations.mjs`.
326
+ - `knitting.js`, `knitting.d.ts`, `process-shared-buffer.js`,
327
+ `process-shared-buffer.d.ts`, `shared-memory.js`, `shared-memory.d.ts`,
328
+ `unsafe.js`, `unsafe.d.ts`, `utils.js`, `utils.d.ts`, and generated
329
+ `src/**/*.js`/`src/**/*.d.ts`: npm release build artifacts produced by
330
+ `build.ts` and `scripts/rewrite-declaration-imports.mjs`.
315
331
  - `results/`: Benchmark output produced by `run.sh`.
316
332
  - `log/`, `logs`, and `*.log`: Local runtime/log output.
317
333
  - `node_modules/`: Installed dependencies. Not part of the source map.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "knitting",
3
- "version": "0.1.55",
3
+ "version": "0.1.60",
4
4
  "description": "Shared-memory IPC runtime for Node.js, Deno, and Bun.",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {
@@ -20,6 +20,10 @@
20
20
  "types": "./knitting.d.ts",
21
21
  "default": "./knitting.js"
22
22
  },
23
+ "./process-shared-buffer": {
24
+ "types": "./process-shared-buffer.d.ts",
25
+ "default": "./process-shared-buffer.js"
26
+ },
23
27
  "./shared-memory": {
24
28
  "types": "./shared-memory.d.ts",
25
29
  "default": "./shared-memory.js"
@@ -40,9 +44,16 @@
40
44
  "prebuilds/**/*.node",
41
45
  "prebuilds/**/*.dll",
42
46
  "scripts/build-native-addons.ts",
47
+ "scripts/build-compiled-worker.ts",
48
+ "scripts/compiled-worker/**/*.ts",
49
+ "scripts/compiled-worker/**/*.d.ts",
43
50
  "src/**/*.cc",
51
+ "src/**/*.d.ts",
52
+ "src/**/*.js",
44
53
  "knitting.d.ts",
45
54
  "knitting.js",
55
+ "process-shared-buffer.d.ts",
56
+ "process-shared-buffer.js",
46
57
  "shared-memory.d.ts",
47
58
  "shared-memory.js",
48
59
  "unsafe.d.ts",
@@ -51,19 +62,22 @@
51
62
  "utils.js"
52
63
  ],
53
64
  "scripts": {
54
- "build": "bun run build.ts && node scripts/build-declarations.mjs",
55
- "build:js": "bun run build.ts",
56
- "build:types": "node scripts/build-declarations.mjs",
57
- "build:npm": "npm run build",
65
+ "clean": "bun run scripts/clean-generated.ts",
66
+ "build": "bun run build.ts && node scripts/rewrite-declaration-imports.mjs",
67
+ "build:js": "bun run build.ts && node scripts/rewrite-declaration-imports.mjs",
68
+ "build:types": "bun run build.ts && node scripts/rewrite-declaration-imports.mjs",
69
+ "build:npm": "bun run build.ts && node scripts/rewrite-declaration-imports.mjs",
58
70
  "build:native": "bun run scripts/build-native-addons.ts",
71
+ "build:compiled": "bun run scripts/build-compiled-worker.ts",
59
72
  "build:release": "bun run build:native && npm run build",
60
- "build:node": "npm run build:js",
73
+ "build:node": "bun run build.ts && node scripts/rewrite-declaration-imports.mjs",
61
74
  "prepack": "npm run build",
62
75
  "release:npm": "npm run test:all && npm publish",
63
76
  "release:npm:dry-run": "npm publish --dry-run",
64
77
  "test": "npm run test:deno",
65
78
  "test:deno": "deno test -A --ignore=test/runtime.node.test.ts --ignore=test/runtime.process.test.ts",
66
79
  "test:node": "node --no-warnings --experimental-transform-types --test \"./test/*.test.ts\"",
80
+ "test:node:26": "node --no-warnings --experimental-ffi test/node26-ffi.integration.mjs",
67
81
  "test:bun": "bun test ./test/*.test.ts --path-ignore-patterns=**/tx-queue.test.ts",
68
82
  "test:runtimes": "npm run test:node && npm run test:bun",
69
83
  "test:all": "npm run test:deno && npm run test:runtimes",
@@ -0,0 +1 @@
1
+ export { getDefaultProcessSharedBufferPrimitives, parseProcessSharedBufferMetadata, PROCESS_SHARED_BUFFER_BRAND, ProcessSharedBuffer, setDefaultProcessSharedBufferPrimitives, type ProcessSharedBufferCreator, type ProcessSharedBufferMapper, type ProcessSharedBufferMetadata, type ProcessSharedBufferPrimitives, type ProcessSharedBufferRange, type ProcessSharedBufferView, type ProcessSharedBufferViewConstructor, } from "./src/connections/process-shared-buffer.js";
@@ -0,0 +1 @@
1
+ export { getDefaultProcessSharedBufferPrimitives, parseProcessSharedBufferMetadata, PROCESS_SHARED_BUFFER_BRAND, ProcessSharedBuffer, setDefaultProcessSharedBufferPrimitives, } from "./src/connections/process-shared-buffer.js";
@@ -0,0 +1,276 @@
1
+ #!/usr/bin/env bun
2
+ /// <reference types="bun" />
3
+
4
+ import {
5
+ chmodSync,
6
+ existsSync,
7
+ mkdirSync,
8
+ renameSync,
9
+ rmSync,
10
+ statSync,
11
+ } from "node:fs";
12
+ import { dirname, isAbsolute, join, relative, resolve } from "node:path";
13
+ import { homedir } from "node:os";
14
+ import { fileURLToPath } from "node:url";
15
+
16
+ type Options = {
17
+ modulePath: string;
18
+ outputPath: string;
19
+ manifestPath: string;
20
+ tasks: string[];
21
+ compiler?: string;
22
+ };
23
+
24
+ const here = dirname(fileURLToPath(import.meta.url));
25
+ const runtime = resolve(here, "compiled-worker/runtime.ts");
26
+ const taskShim = resolve(here, "compiled-worker/task-shim.ts");
27
+ const repositoryEntry = resolve(here, "../knitting.ts");
28
+ const PORFFOR_REPOSITORY = "https://github.com/CanadaHonk/porffor.git";
29
+ const PORFFOR_REVISION = "747d551844750fc5ed32cf88cdf0b3854aee267e";
30
+
31
+ const usage = (): never => {
32
+ console.error(
33
+ "Usage: bun scripts/build-compiled-worker.ts --module tasks.ts " +
34
+ "--out tasks.knt --tasks taskA,taskB [--porf /path/to/porf]",
35
+ );
36
+ process.exit(2);
37
+ };
38
+
39
+ const readOptions = (): Options => {
40
+ const args = process.argv.slice(2);
41
+ let modulePath: string | undefined;
42
+ let outputPath: string | undefined;
43
+ let manifestPath: string | undefined;
44
+ let tasks: string[] | undefined;
45
+ let compiler: string | undefined;
46
+ for (let index = 0; index < args.length; index++) {
47
+ const argument = args[index]!;
48
+ const value = args[index + 1];
49
+ if (value === undefined) usage();
50
+ if (argument === "--module") modulePath = value;
51
+ else if (argument === "--out") outputPath = value;
52
+ else if (argument === "--manifest") manifestPath = value;
53
+ else if (argument === "--tasks") tasks = value.split(",").filter(Boolean);
54
+ else if (argument === "--porf") compiler = value;
55
+ else usage();
56
+ index++;
57
+ }
58
+ if (modulePath === undefined || outputPath === undefined || !tasks?.length) {
59
+ usage();
60
+ }
61
+ for (const name of tasks) {
62
+ if (!/^[$A-Z_a-z][$\w]*$/.test(name) && name !== "default") {
63
+ throw new Error("Compiled task name is not an export identifier: " + name);
64
+ }
65
+ }
66
+ return {
67
+ modulePath: resolve(modulePath),
68
+ outputPath: resolve(outputPath),
69
+ manifestPath: manifestPath === undefined
70
+ ? resolve(outputPath) + ".json"
71
+ : resolve(manifestPath),
72
+ tasks,
73
+ compiler,
74
+ };
75
+ };
76
+
77
+ const commandWorks = (command: string): boolean => {
78
+ try {
79
+ const result = Bun.spawnSync([command, "--version"], {
80
+ stdout: "pipe",
81
+ stderr: "pipe",
82
+ });
83
+ return result.exitCode === 0 &&
84
+ new TextDecoder().decode(result.stdout).startsWith("alpha ");
85
+ } catch {
86
+ return false;
87
+ }
88
+ };
89
+
90
+ const compilerPath = (input: string): string => {
91
+ const decoded = input.startsWith("file:") ? fileURLToPath(input) : input;
92
+ const path = decoded.includes("/") || decoded.includes("\\")
93
+ ? resolve(decoded)
94
+ : decoded;
95
+ return existsSync(path) && statSync(path).isDirectory()
96
+ ? join(path, "porf")
97
+ : path;
98
+ };
99
+
100
+ const installCompiler = (): string => {
101
+ const cacheRoot = process.env.XDG_CACHE_HOME ?? join(homedir(), ".cache");
102
+ const cache = join(
103
+ cacheRoot,
104
+ "knitting",
105
+ "porffor-" + PORFFOR_REVISION.slice(0, 12),
106
+ );
107
+ const executable = join(cache, "porf");
108
+ if (commandWorks(executable)) return executable;
109
+
110
+ const temporary = cache + ".tmp-" + process.pid;
111
+ rmSync(temporary, { recursive: true, force: true });
112
+ mkdirSync(temporary, { recursive: true });
113
+ const commands = [
114
+ ["git", "-C", temporary, "init", "--quiet"],
115
+ ["git", "-C", temporary, "remote", "add", "origin", PORFFOR_REPOSITORY],
116
+ [
117
+ "git",
118
+ "-C",
119
+ temporary,
120
+ "fetch",
121
+ "--quiet",
122
+ "--depth",
123
+ "1",
124
+ "origin",
125
+ PORFFOR_REVISION,
126
+ ],
127
+ ["git", "-C", temporary, "checkout", "--quiet", "--detach", "FETCH_HEAD"],
128
+ ];
129
+ console.error("Knitting: downloading the pinned Porffor compiler (first run only)");
130
+ try {
131
+ for (const command of commands) {
132
+ const result = Bun.spawnSync(command, { stdout: "inherit", stderr: "inherit" });
133
+ if (result.exitCode !== 0) {
134
+ throw new Error(command[0] + " exited with code " + result.exitCode);
135
+ }
136
+ }
137
+ rmSync(cache, { recursive: true, force: true });
138
+ renameSync(temporary, cache);
139
+ } catch (error) {
140
+ rmSync(temporary, { recursive: true, force: true });
141
+ throw error;
142
+ }
143
+ if (!commandWorks(executable)) {
144
+ throw new Error("Downloaded Porffor compiler is unavailable");
145
+ }
146
+ return executable;
147
+ };
148
+
149
+ const resolveCompiler = (options: Options): string => {
150
+ const configured = options.compiler ?? process.env.PORFFOR_MAIN ??
151
+ process.env.PORF;
152
+ if (configured !== undefined) {
153
+ const candidate = compilerPath(configured);
154
+ if (!commandWorks(candidate)) {
155
+ throw new Error("Porffor main compiler is unavailable: " + candidate);
156
+ }
157
+ return candidate;
158
+ }
159
+ if (commandWorks("porf")) return "porf";
160
+ return installCompiler();
161
+ };
162
+
163
+ const quote = (value: string): string => JSON.stringify(value);
164
+
165
+ const makeEntry = (modulePath: string, tasks: string[]): string => {
166
+ const imports = tasks.map((name, index) =>
167
+ name === "default"
168
+ ? `import __knitExport${index} from ${quote(modulePath)};`
169
+ : `import { ${name} as __knitExport${index} } from ${quote(modulePath)};`
170
+ );
171
+ const functions = tasks.map((_, index) =>
172
+ `typeof __knitExport${index} === "function" ` +
173
+ `? __knitExport${index} : __knitExport${index}.f`
174
+ );
175
+ return [
176
+ ...imports,
177
+ `import { runJsonWorker } from ${quote(runtime)};`,
178
+ `runJsonWorker([${functions.join(", ")}]);`,
179
+ "",
180
+ ].join("\n");
181
+ };
182
+
183
+ const resolvesToKnitting = (specifier: string, resolveDir: string): boolean => {
184
+ if (specifier === "knitting" || specifier === "@vixeny/knitting") return true;
185
+ if (!specifier.startsWith(".") && !isAbsolute(specifier)) return false;
186
+ const candidate = resolve(resolveDir, specifier).replace(/\.(?:js|ts)$/, "");
187
+ return candidate === repositoryEntry.replace(/\.ts$/, "");
188
+ };
189
+
190
+ const run = async (): Promise<void> => {
191
+ const options = readOptions();
192
+ const outputDirectory = dirname(options.outputPath);
193
+ const workDirectory = join(outputDirectory, ".knitting-compiled");
194
+ const entryPath = join(workDirectory, "entry.ts");
195
+ const bundlePath = join(workDirectory, "worker.bundle.js");
196
+ mkdirSync(workDirectory, { recursive: true });
197
+ mkdirSync(dirname(options.manifestPath), { recursive: true });
198
+ await Bun.write(entryPath, makeEntry(options.modulePath, options.tasks));
199
+
200
+ const build = await Bun.build({
201
+ entrypoints: [entryPath],
202
+ format: "esm",
203
+ target: "browser",
204
+ minify: { syntax: true, whitespace: false, identifiers: false },
205
+ plugins: [{
206
+ name: "knitting-compiled-worker-api",
207
+ setup(builder) {
208
+ builder.onResolve({ filter: /.*/ }, (args) =>
209
+ resolvesToKnitting(args.path, args.resolveDir)
210
+ ? { path: taskShim }
211
+ : undefined
212
+ );
213
+ },
214
+ }],
215
+ });
216
+ if (!build.success || build.outputs[0] === undefined) {
217
+ for (const log of build.logs) console.error(log);
218
+ throw new Error("Bun could not bundle the compiled worker");
219
+ }
220
+ await Bun.write(bundlePath, build.outputs[0]);
221
+
222
+ const porf = resolveCompiler(options);
223
+ const versionResult = Bun.spawnSync([porf, "--version"], {
224
+ stdout: "pipe",
225
+ stderr: "pipe",
226
+ });
227
+ const version = new TextDecoder().decode(versionResult.stdout).trim();
228
+ console.error("Knitting: compiling " + relative(process.cwd(), options.modulePath));
229
+ const compilerEnvironment = { ...process.env };
230
+ if (process.platform === "linux" && compilerEnvironment.CC === undefined) {
231
+ compilerEnvironment.CC = "cc -Wno-stringop-overflow";
232
+ }
233
+ const compile = Bun.spawnSync([
234
+ porf,
235
+ "native",
236
+ "--module",
237
+ "--quiet",
238
+ "-O3",
239
+ "--flto=auto",
240
+ bundlePath,
241
+ "-o",
242
+ options.outputPath,
243
+ ], {
244
+ stdout: "inherit",
245
+ stderr: "inherit",
246
+ env: compilerEnvironment,
247
+ });
248
+ if (compile.exitCode !== 0) {
249
+ throw new Error("Porffor exited with code " + compile.exitCode);
250
+ }
251
+ chmodSync(options.outputPath, 0o755);
252
+
253
+ await Bun.write(
254
+ options.manifestPath,
255
+ JSON.stringify({
256
+ format: "knitting-compiled-worker",
257
+ version: 1,
258
+ protocol: "knitting-json-v1",
259
+ compiler: { name: "porffor", version },
260
+ target: { platform: process.platform, arch: process.arch },
261
+ source: relative(outputDirectory, options.modulePath).replaceAll("\\", "/"),
262
+ sourceMtimeMs: statSync(options.modulePath).mtimeMs,
263
+ capabilities: {
264
+ input: "json",
265
+ output: "json",
266
+ async: false,
267
+ abortSignal: true,
268
+ binaryValues: true,
269
+ },
270
+ tasks: options.tasks.map((exportName, index) => ({ index, exportName })),
271
+ }, null, 2) + "\n",
272
+ );
273
+ rmSync(workDirectory, { recursive: true, force: true });
274
+ };
275
+
276
+ await run();
@@ -0,0 +1,5 @@
1
+ declare namespace Porffor {
2
+ function c(strings: TemplateStringsArray, ...values: unknown[]): void;
3
+ }
4
+
5
+ type i32 = number;