@sproutboat/runtime 0.6.0 → 0.6.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/CHANGELOG.md CHANGED
@@ -1,5 +1,37 @@
1
1
  # @sproutboat/runtime
2
2
 
3
+ ## 0.6.1
4
+
5
+ ### Patch Changes
6
+
7
+ - 806c21e: Fix (baronunread/sproutboat#176): #172's bytestring UTF-8 encoding fix broke
8
+ the assets binding, which reads a file's bytes off disk into a `bytestring`
9
+ specifically so they pass through the wire untouched — a `bytestring`
10
+ carrying real text a handler built and one carrying opaque file bytes are the
11
+ same type with no way to tell them apart, so #172's blanket encoding also
12
+ re-encoded already-finished bytes, corrupting any binary asset (and any
13
+ proxied `fetch()`/service-binding response body).
14
+
15
+ Adds a second, dedicated `porf_native_fetch_read_raw_bytes` (zero-copy,
16
+ bytestring-only, no encoding, ever) alongside the untouched original —
17
+ `porf_native_fetch_read_value` is called from ~30 places across sproutboat's
18
+ own inline C, all genuine text, so its signature and behavior stay exactly as
19
+ #172 left them. `write_response_value` picks between the two based on a new
20
+ reserved `x-sb-raw-body` response header (same pattern as #163's
21
+ `x-sb-remote-addr`), which the assets binding, outbound `fetch()`, and
22
+ service-binding `fetch()` now set — the three places sproutboat's own
23
+ prelude constructs a Response from wire bytes rather than a string a handler
24
+ built. Verified end-to-end: a 256-byte all-values fixture now round-trips
25
+ byte-for-byte through a real standalone build's assets binding, and #172's
26
+ original UTF-8 fix still holds for genuine text.
27
+
28
+ Not fixed here: `env.<R2>.get()`'s `.body` is exposed directly to handler
29
+ code, which then constructs its own `new Response(obj.body)` — no
30
+ sproutboat-owned call site to attach the marker to, so R2 binary objects
31
+ served this way carry the same corruption. Needs either a real binary body
32
+ type upstream in Porffor or a different API shape; tracked as a known gap on
33
+ #176, not resolved by this fix.
34
+
3
35
  ## 0.6.0
4
36
 
5
37
  ### Minor Changes
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sproutboat/runtime",
3
- "version": "0.6.0",
3
+ "version": "0.6.1",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "main": "./src/index.ts",
@@ -1140,6 +1140,11 @@ globalThis.__sbInstallBindings = function (target, bindings) {
1140
1140
  const headers = {};
1141
1141
  if (r.type) headers["content-type"] = r.type;
1142
1142
  if (r.found) headers["etag"] = '"' + r.hash + '"';
1143
+ // #176: these bytes came off disk already-finished (UTF-8 text or
1144
+ // binary, doesn't matter which) -- the reserved x-sb-raw-body header
1145
+ // tells the C write path to pass them through untouched instead of
1146
+ // re-encoding as if this were a JS string a handler built.
1147
+ if (r.body != null) headers["x-sb-raw-body"] = "1";
1143
1148
  return new Response(r.body == null ? "" : r.body, { status: r.status || (r.found ? 200 : 404), headers });
1144
1149
  },
1145
1150
  };
@@ -1168,6 +1173,10 @@ globalThis.__sbInstallBindings = function (target, bindings) {
1168
1173
  });
1169
1174
  const respHeaders = new Headers();
1170
1175
  for (let j = 0; j < (r.headers || []).length; j++) respHeaders.set(r.headers[j][0], r.headers[j][1]);
1176
+ // #176: wire bytes from another deployment, not a string this handler
1177
+ // built -- must not be re-encoded if the handler proxies it straight
1178
+ // through (see the assets binding for the same reasoning).
1179
+ if (r.body != null) respHeaders.set("x-sb-raw-body", "1");
1171
1180
  return new Response(r.body == null ? "" : r.body, { status: r.status || 502, headers: respHeaders });
1172
1181
  },
1173
1182
  };
@@ -1190,6 +1199,10 @@ globalThis.__sbInstallBindings = function (target, bindings) {
1190
1199
  });
1191
1200
  const respHeaders = new Headers();
1192
1201
  for (let j = 0; j < (r.headers || []).length; j++) respHeaders.set(r.headers[j][0], r.headers[j][1]);
1202
+ // #176: bytes from an outbound HTTP response, not a string this handler
1203
+ // built -- must not be re-encoded if the handler proxies it straight
1204
+ // through (see the assets binding for the same reasoning).
1205
+ if (r.body != null) respHeaders.set("x-sb-raw-body", "1");
1193
1206
  return new Response(r.body == null ? "" : r.body, { status: r.status || 502, headers: respHeaders });
1194
1207
  };
1195
1208
  }