@sproutboat/toolchain 0.4.14 → 0.4.16

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/CHANGELOG.md CHANGED
@@ -1,5 +1,17 @@
1
1
  # @sproutboat/toolchain
2
2
 
3
+ ## 0.4.16
4
+
5
+ ### Patch Changes
6
+
7
+ - 7bab275: Pin and vendor Porffor alpha-13 (`547c781`). Alpha-11 to alpha-13 bring array, typed array and module codegen fixes, a basic `RegExp` search, a `String.prototype.normalize` stub and lowercase JSON hex escapes. Every Sproutboat patch applies unchanged, uWebSockets stays on the same commit, and the compatibility suite is unchanged at 30/32.
8
+
9
+ ## 0.4.15
10
+
11
+ ### Patch Changes
12
+
13
+ - c9f84ac: Raise Porffor's per-coroutine fiber stack from 256 KiB to 8 MiB. A large async handler compiled at -O0 (`sproutboat dev`) overflowed it within a few nested awaits and died with SIGBUS on its first request (baronunread/sproutboat#178). Only touched pages cost memory.
14
+
3
15
  ## 0.4.14
4
16
 
5
17
  ### Patch Changes
@@ -0,0 +1,9 @@
1
+ # Porffor alpha-13 upgrade audit
2
+
3
+ The source pin moves from alpha-10 (`08ac7ee`) to the [alpha-13 release](https://github.com/CanadaHonk/porffor/releases/tag/alpha-13), commit `547c7815125b6f02474591950f8b0dd7031a03f0`, published September 30, 2026. The vendored codeload archive has SHA-256 `d0ff4bf7778f85445ff99bb8f6b2e07f2b83a33a109612f9eba6f2e5cba291b5`.
4
+
5
+ Alpha-11 brings array and typed array fast paths (merge sort, `shift`, same-type `set`) and codegen fixes for closures in loops and function literals. Alpha-12 fixes module handling (reassigned exports, strict-mode analysis, module-init closures). Alpha-13 adds a basic `RegExp` search, a `String.prototype.normalize` stub, more reserved C keywords and lowercase JSON hex escapes. Its `compiler/uwebsockets.js` still pins `360c276d609d59af56ae6932adb95154ace9f15f`, so the CLI's vendored uWebSockets archive does not change. All 28 Sproutboat patches apply without changing their anchors or markers. `PORF_CORO_STACK_SIZE` is still 256 KiB upstream, so the #178 patch still applies and still matters.
6
+
7
+ The native package suite passed 152 tests, plus the native crypto vectors. Linked to this toolchain, the CLI passed 103 tests (`SURFACE.md` only needs the new provenance stamp), 28 broker checks, 30 standalone checks and all 21 examples. The platform's 32-handler comparison compiled all 32 and matched Bun on 30, unchanged from alpha-10. The remaining two failures are non-ISO date parsing in `15-date-iso.js` and `16-date-parts.js`. See [the scorecard](PORFFOR_SCORECARD.md) for the exact results.
8
+
9
+ The open runtime bugs reproduce unchanged: baronunread/sproutboat#168 (an async chain using `new Date().toISOString()` flips to permanent 500s after 5 to 12 requests) and the read half of #189 (non-ASCII D1 and KV values come back as Latin-1 bytes).
@@ -1,29 +1,29 @@
1
1
  # Porffor pin scorecard
2
2
 
3
- Pin: alpha-10 (08ac7ee1077c05da2bec18dcca15197051e87b62). Compatibility report: 2026-09-28T07:08:44.821Z.
3
+ Pin: alpha-13 (547c7815125b6f02474591950f8b0dd7031a03f0). Compatibility report: 2026-10-01T10:57:31.463Z.
4
4
 
5
5
  | Measure | Result |
6
6
  | --- | ---: |
7
7
  | Fixtures compiled | 32/32 |
8
8
  | Behavior matches | 30/32 |
9
- | Median / p95 compile, ms | 4468 / 7436 |
10
- | Median / p95 binary, bytes | 983392 / 1016464 |
11
- | Patch markers | 27 |
9
+ | Median / p95 compile, ms | 3212 / 4703 |
10
+ | Median / p95 binary, bytes | 966864 / 999936 |
11
+ | Patch markers | 28 |
12
12
  | Upstream files written | 6 |
13
13
  | Fresh patch application | pass |
14
14
 
15
- Previous snapshot: alpha-9-de4eb58.json. Matches 30/32 to 30/32; patch markers 27 to 27.
15
+ Previous snapshot: alpha-10-08ac7ee.json. Matches 30/32 to 30/32; patch markers 27 to 28.
16
16
 
17
17
  ## Patch inventory
18
18
 
19
- - `compiler/render.js`: PORT_MARKER, CONSOLE_MARKER, BYTESTRING_MARKER, READ_RAW_MARKER
19
+ - `compiler/render.js`: PORT_MARKER, CONSOLE_MARKER, BYTESTRING_MARKER, READ_RAW_MARKER, CORO_STACK_MARKER
20
20
  - `compiler/index.js`: LINK_MARKER, CFLAGS_MARKER
21
21
  - `compiler/builtins/typedarray.js`: TYPED_ARRAY_FROM_MARKER
22
22
  - `compiler/builtins/date.ts`: DATE_PARSER_MARKER
23
23
  - `compiler/uwebsockets.js`: BODY_MARKER, STATUS_SIG_MARKER, STATUS_303_MARKER, STATUS_DEFAULT_MARKER, HDR_SIG_MARKER, HDR_CALL_MARKER, HDR_CAP_MARKER, HDR_SKIP_MARKER, HDR_APPEND_MARKER, READ_RAW_DECL_MARKER, FORBIDDEN_HDR_MARKER, WRITE_RESPONSE_MARKER, R2_TRANSFER_MARKER, R2_TRANSFER_CALL_MARKER, R2_DOWNLOAD_CACHE_MARKER, R2_RANGE_CACHE_MARKER, R2_CONDITIONAL_CACHE_MARKER, R2_STREAMING_CACHE_MARKER, R2_RANGE_HEADER_CACHE_MARKER
24
24
  - `compiler/builtins_precompiled.js`: regenerated builtin table
25
25
 
26
- Patch source SHA-256: `edf60b7104e2d0b8efb64e38459fd2d5616ccdf24995ad1d4ca07fa232db4eaf`.
26
+ Patch source SHA-256: `6f607ac6b66fc4a51c2bf9e9525d0ab7f4e9b9dd3f942a820bbad46b7e3dbf56`.
27
27
 
28
28
  ## Known behavior gaps
29
29
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sproutboat/toolchain",
3
- "version": "0.4.14",
3
+ "version": "0.4.16",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "repository": {
@@ -0,0 +1,59 @@
1
+ {
2
+ "pin": "alpha-13 (547c7815125b6f02474591950f8b0dd7031a03f0)",
3
+ "reportGeneratedAt": "2026-10-01T10:57:31.463Z",
4
+ "fixtures": 32,
5
+ "compiled": 32,
6
+ "matched": 30,
7
+ "medianCompileMs": 3212,
8
+ "p95CompileMs": 4703,
9
+ "medianBinaryBytes": 966864,
10
+ "p95BinaryBytes": 999936,
11
+ "patchSourceSha256": "6f607ac6b66fc4a51c2bf9e9525d0ab7f4e9b9dd3f942a820bbad46b7e3dbf56",
12
+ "patchMarkerCount": 28,
13
+ "patchTargets": {
14
+ "compiler/render.js": [
15
+ "PORT_MARKER",
16
+ "CONSOLE_MARKER",
17
+ "BYTESTRING_MARKER",
18
+ "READ_RAW_MARKER",
19
+ "CORO_STACK_MARKER"
20
+ ],
21
+ "compiler/index.js": [
22
+ "LINK_MARKER",
23
+ "CFLAGS_MARKER"
24
+ ],
25
+ "compiler/builtins/typedarray.js": [
26
+ "TYPED_ARRAY_FROM_MARKER"
27
+ ],
28
+ "compiler/builtins/date.ts": [
29
+ "DATE_PARSER_MARKER"
30
+ ],
31
+ "compiler/uwebsockets.js": [
32
+ "BODY_MARKER",
33
+ "STATUS_SIG_MARKER",
34
+ "STATUS_303_MARKER",
35
+ "STATUS_DEFAULT_MARKER",
36
+ "HDR_SIG_MARKER",
37
+ "HDR_CALL_MARKER",
38
+ "HDR_CAP_MARKER",
39
+ "HDR_SKIP_MARKER",
40
+ "HDR_APPEND_MARKER",
41
+ "READ_RAW_DECL_MARKER",
42
+ "FORBIDDEN_HDR_MARKER",
43
+ "WRITE_RESPONSE_MARKER",
44
+ "R2_TRANSFER_MARKER",
45
+ "R2_TRANSFER_CALL_MARKER",
46
+ "R2_DOWNLOAD_CACHE_MARKER",
47
+ "R2_RANGE_CACHE_MARKER",
48
+ "R2_CONDITIONAL_CACHE_MARKER",
49
+ "R2_STREAMING_CACHE_MARKER",
50
+ "R2_RANGE_HEADER_CACHE_MARKER"
51
+ ],
52
+ "compiler/builtins_precompiled.js": []
53
+ },
54
+ "patchApplication": "pass",
55
+ "mismatches": [
56
+ "15-date-iso.js: request 3 mismatch: expected {\"status\":200,\"body\":\"2008-03-04T23:00:00.000Z\",\"content-type\":null}, got {\"status\":200,\"body\":\"0003-05-08T00:00:00.000Z\",\"content-type\":null}",
57
+ "16-date-parts.js: request 3 mismatch: expected {\"status\":200,\"body\":\"{\\\"year\\\":2008,\\\"month\\\":3,\\\"day\\\":4}\",\"content-type\":\"application/json;charset=utf-8\"}, got {\"status\":200,\"body\":\"{\\\"year\\\":3,\\\"month\\\":5,\\\"day\\\":8}\",\"content-type\":\"application/json;charset=utf-8\"}"
58
+ ]
59
+ }
@@ -27,7 +27,8 @@ async function fixture(): Promise<{ archive: string; sha256: string }> {
27
27
  " return 0;\n" +
28
28
  " }\n" +
29
29
  " return -1;\n" +
30
- "}\n",
30
+ "}\n" +
31
+ "#define PORF_CORO_STACK_SIZE (256u * 1024u)\n",
31
32
  "compiler/index.js": " ...darwinReleaseCompileArgs,\n uSocketsArchive,\n '-lm'\n",
32
33
  "compiler/precompile.js":
33
34
  "const fs = require('node:fs');\n" +
package/src/acquire.ts CHANGED
@@ -5,7 +5,7 @@ import { homedir } from "node:os";
5
5
  import { resolve } from "node:path";
6
6
  // @ts-expect-error Bun's file loader supplies a path; see the pinned-commit
7
7
  // check below for why this is safe to trust unconditionally.
8
- import vendoredPorfforArchive from "../vendor/porffor-08ac7ee.tar.gz" with { type: "file" };
8
+ import vendoredPorfforArchive from "../vendor/porffor-547c781.tar.gz" with { type: "file" };
9
9
  import { ensurePorfforPatched } from "./patch";
10
10
  import { PORFFOR_ARCHIVE_SHA256, PORFFOR_ARCHIVE_URL, PORFFOR_COMMIT_FULL } from "./pin";
11
11
  // Folded into the cache manifest below so a toolchain release that changes
package/src/patch.test.ts CHANGED
@@ -35,6 +35,9 @@ int porf_native_fetch_read_value(jsval value, const char** out_buf, size_t* out_
35
35
 
36
36
  return -1;
37
37
  }
38
+
39
+ #define PORF_CORO_STACK_SIZE (256u * 1024u)
40
+ #define PORF_CORO_MAX 16384
38
41
  `;
39
42
 
40
43
  // Porffor's compiler/uwebsockets.js, trimmed to the parts the patch touches:
@@ -289,6 +292,10 @@ test("#165: render.js routes console output to stderr, unbuffered, idempotently"
289
292
  "int porf_native_fetch_read_value(jsval value, const char** out_buf, size_t* out_len, char** out_owned) {",
290
293
  );
291
294
 
295
+ // #178: fiber stacks big enough for -O0 frames in a few nested awaits.
296
+ expect(once).toContain("#define PORF_CORO_STACK_SIZE (8u * 1024u * 1024u)");
297
+ expect(once).not.toContain("(256u * 1024u)");
298
+
292
299
  await patchRenderJs(root);
293
300
  expect(await readFile(join(root, "compiler/render.js"), "utf8")).toBe(once);
294
301
  } finally {
package/src/patch.ts CHANGED
@@ -131,6 +131,25 @@ const READ_RAW_INJECT =
131
131
  READ_RAW_ANCHOR;
132
132
  const READ_RAW_MARKER = "porf_native_fetch_read_raw_bytes(jsval value";
133
133
 
134
+ /**
135
+ * baronunread/sproutboat#178: every async function runs on its own fiber
136
+ * stack, and Porffor (alpha-10 through alpha-13) fixes those at 256 KiB. A
137
+ * large handler compiled at -O0 (what `sproutboat dev` builds) spends ~40 KiB
138
+ * of stack per call into the biggest generated functions, so a few nested
139
+ * awaits run off the end into the guard page and the sprout dies with SIGBUS
140
+ * on its first request, no log.
141
+ * -O3 frames are smaller, which only raises the threshold: a deep enough
142
+ * async chain hits it in a release build too.
143
+ *
144
+ * Match a thread's usual 8 MiB. The reservation is MAP_NORESERVE with a guard
145
+ * page, so only touched pages cost memory and a shallow handler pays nothing.
146
+ */
147
+ const CORO_STACK_ANCHOR = "#define PORF_CORO_STACK_SIZE (256u * 1024u)";
148
+ const CORO_STACK_INJECT =
149
+ "// sproutboat #178: 256 KiB overflows -O0 frames in a few nested awaits.\n" +
150
+ "#define PORF_CORO_STACK_SIZE (8u * 1024u * 1024u)";
151
+ const CORO_STACK_MARKER = "sproutboat #178";
152
+
134
153
  /**
135
154
  * render.js full-block replacements: `[marker, anchor, inject, what]`, each a
136
155
  * complete swap of the matched region (unlike `RENDER_EDITS`, which only ever
@@ -139,6 +158,7 @@ const READ_RAW_MARKER = "porf_native_fetch_read_raw_bytes(jsval value";
139
158
  const RENDER_REPLACEMENTS = [
140
159
  [BYTESTRING_MARKER, BYTESTRING_ANCHOR, BYTESTRING_INJECT, "bytestring UTF-8 encoding (#172)"],
141
160
  [READ_RAW_MARKER, READ_RAW_ANCHOR, READ_RAW_INJECT, "raw bytestring passthrough function (#176)"],
161
+ [CORO_STACK_MARKER, CORO_STACK_ANCHOR, CORO_STACK_INJECT, "coroutine stack size (#178)"],
142
162
  ] as const;
143
163
 
144
164
  // #15 — no `--port` flag: Porffor's native-fetch entry point calls
package/src/pin.ts CHANGED
@@ -11,14 +11,14 @@
11
11
  * uWebSockets archive in `sproutboat-cli/vendor/` — then run both repos'
12
12
  * test + conformance suites. See sproutboat-cli/MIGRATION.md.
13
13
  */
14
- export const PORFFOR_CHANNEL = "alpha-10";
15
- export const PORFFOR_COMMIT_FULL = "08ac7ee1077c05da2bec18dcca15197051e87b62";
14
+ export const PORFFOR_CHANNEL = "alpha-13";
15
+ export const PORFFOR_COMMIT_FULL = "547c7815125b6f02474591950f8b0dd7031a03f0";
16
16
  export const PORFFOR_COMMIT = PORFFOR_COMMIT_FULL.slice(0, 7);
17
17
  export const PORFFOR_ARCHIVE_SHA256 =
18
- "d49ce6724efde555b4cdeea0d2610baddd4310153956c79b352d86ba9cf0f60f";
18
+ "d0ff4bf7778f85445ff99bb8f6b2e07f2b83a33a109612f9eba6f2e5cba291b5";
19
19
  export const PORFFOR_ARCHIVE_URL = `https://codeload.github.com/CanadaHonk/porffor/tar.gz/${PORFFOR_COMMIT_FULL}`;
20
20
 
21
- /** A compact identity string for a manifest / report (`alpha-10 (08ac7ee)`). */
21
+ /** A compact identity string for a manifest / report (`alpha-13 (547c781)`). */
22
22
  export function porfforVersion(): string {
23
23
  return process.env.PORFFOR_VERSION || `${PORFFOR_CHANNEL} (${PORFFOR_COMMIT})`;
24
24
  }
Binary file
Binary file