@sproutboat/runtime 0.42.2 → 0.43.0
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 +6 -0
- package/package.json +1 -1
- package/src/native-fetch-prelude.js +137 -14
- package/test/native-base64.ts +12 -26
- package/test/native-bodies.ts +19 -26
- package/test/native-byte-text.ts +3 -19
- package/test/native-compile.ts +163 -0
- package/test/native-cpu-requests.ts +3 -20
- package/test/native-cpu-stamp.ts +3 -20
- package/test/native-crypto.ts +3 -22
- package/test/native-domexception.ts +3 -21
- package/test/native-errors.ts +12 -24
- package/test/native-events.ts +21 -25
- package/test/native-fetch-request.ts +11 -20
- package/test/native-getrandomvalues.ts +3 -21
- package/test/native-headers.ts +3 -21
- package/test/native-http.ts +10 -20
- package/test/native-iterators.ts +24 -27
- package/test/native-json-strings.ts +3 -21
- package/test/native-json.ts +15 -25
- package/test/native-jwt.ts +3 -22
- package/test/native-model-resolver.ts +5 -24
- package/test/native-raw-body.ts +7 -53
- package/test/native-request-log.ts +197 -0
- package/test/native-request-streaming.ts +3 -19
- package/test/native-request.ts +24 -26
- package/test/native-response-defaults.ts +4 -22
- package/test/native-service-bindings.ts +53 -27
- package/test/native-sockets-broker.ts +3 -20
- package/test/native-streaming.ts +4 -22
- package/test/native-streams.ts +22 -25
- package/test/native-subtle.ts +3 -21
- package/test/native-textdecoder-encodings.ts +3 -21
- package/test/native-timers.ts +4 -22
- package/test/native-unhandled-rejection.ts +3 -20
- package/test/native-url.ts +15 -25
- package/test/native-utf8.ts +15 -21
- package/test/native-waituntil.ts +7 -23
- package/test/native-web-apis.ts +3 -22
- package/test/native-websockets.ts +3 -19
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import assert from "node:assert/strict";
|
|
2
2
|
import { mkdtemp, readFile, rm, writeFile } from "node:fs/promises";
|
|
3
3
|
import { tmpdir } from "node:os";
|
|
4
|
-
import { join
|
|
5
|
-
import {
|
|
4
|
+
import { join } from "node:path";
|
|
5
|
+
import { compileNative } from "./native-compile";
|
|
6
6
|
import { createBroker, listen } from "../../wire/src/broker";
|
|
7
7
|
import { EMPTY_BINDINGS, preludePath, TRANSPORT_MARKER, transportPath, wrapNativeFetchHandler } from "../src/wrap";
|
|
8
8
|
|
|
@@ -182,7 +182,11 @@ const edge = Bun.serve({
|
|
|
182
182
|
});
|
|
183
183
|
}
|
|
184
184
|
if (url.pathname === "/typed") {
|
|
185
|
-
return Response.json({
|
|
185
|
+
return Response.json({
|
|
186
|
+
method: request.method,
|
|
187
|
+
type: request.headers.get("content-type"),
|
|
188
|
+
body: await request.text(),
|
|
189
|
+
});
|
|
186
190
|
}
|
|
187
191
|
if (url.pathname === "/redirect") {
|
|
188
192
|
const status = Number(url.searchParams.get("status"));
|
|
@@ -246,9 +250,6 @@ const get = async (path: string) => {
|
|
|
246
250
|
return { status: res.status, text: await res.text(), ms: performance.now() - t0 };
|
|
247
251
|
};
|
|
248
252
|
try {
|
|
249
|
-
const porffor = await ensurePorffor({ cacheRoot: workdir });
|
|
250
|
-
const node = Bun.which("node");
|
|
251
|
-
if (!node) throw new Error("native service-binding test needs node on PATH");
|
|
252
253
|
const [core, transport] = await Promise.all([
|
|
253
254
|
readFile(preludePath, "utf8"),
|
|
254
255
|
readFile(transportPath("broker"), "utf8"),
|
|
@@ -256,20 +257,12 @@ try {
|
|
|
256
257
|
assert(core.includes(TRANSPORT_MARKER), "runtime prelude is missing its transport marker");
|
|
257
258
|
const generated = join(workdir, "services.generated.js");
|
|
258
259
|
const binary = join(workdir, "services-native");
|
|
259
|
-
await writeFile(
|
|
260
|
+
await writeFile(
|
|
261
|
+
generated,
|
|
262
|
+
wrapNativeFetchHandler(handler, core.replace(TRANSPORT_MARKER, transport), {}, bindings, undefined, "2026-10-22"),
|
|
263
|
+
);
|
|
260
264
|
|
|
261
|
-
|
|
262
|
-
cwd: workdir,
|
|
263
|
-
env: process.env,
|
|
264
|
-
stdout: "pipe",
|
|
265
|
-
stderr: "pipe",
|
|
266
|
-
});
|
|
267
|
-
const [exitCode, stdout, stderr] = await Promise.all([
|
|
268
|
-
compile.exited,
|
|
269
|
-
new Response(compile.stdout).text(),
|
|
270
|
-
new Response(compile.stderr).text(),
|
|
271
|
-
]);
|
|
272
|
-
assert.equal(exitCode, 0, `Porffor native compile failed:\n${stderr}\n${stdout}`);
|
|
265
|
+
await compileNative({ generated, binary, dir: workdir, cacheRoot: workdir });
|
|
273
266
|
|
|
274
267
|
server = Bun.spawn([binary], {
|
|
275
268
|
cwd: workdir,
|
|
@@ -329,7 +322,10 @@ try {
|
|
|
329
322
|
const t0 = performance.now();
|
|
330
323
|
const all = await Promise.all(Array.from({ length: 8 }, () => get("/slow?ms=500")));
|
|
331
324
|
const total = performance.now() - t0;
|
|
332
|
-
assert(
|
|
325
|
+
assert(
|
|
326
|
+
all.every((r) => r.text === "slow done"),
|
|
327
|
+
JSON.stringify(all),
|
|
328
|
+
);
|
|
333
329
|
assert(total < 1500, `8 concurrent 500 ms calls took ${Math.round(total)} ms`);
|
|
334
330
|
|
|
335
331
|
// Cancellation: an aborted signal rejects at once, and the abort reaches the upstream
|
|
@@ -337,7 +333,11 @@ try {
|
|
|
337
333
|
const abandonedBefore = slowAbandoned;
|
|
338
334
|
const aborts = await get("/abort");
|
|
339
335
|
assert.equal(aborts.status, 200, aborts.text);
|
|
340
|
-
assert.deepEqual(JSON.parse(aborts.text), {
|
|
336
|
+
assert.deepEqual(JSON.parse(aborts.text), {
|
|
337
|
+
aborted: "AbortError fast",
|
|
338
|
+
timedOut: "TimeoutError fast",
|
|
339
|
+
already: "AbortError fast",
|
|
340
|
+
});
|
|
341
341
|
await Bun.sleep(300);
|
|
342
342
|
assert.equal(slowAbandoned - abandonedBefore, 2, "both in-flight calls were stopped upstream");
|
|
343
343
|
|
|
@@ -375,7 +375,11 @@ try {
|
|
|
375
375
|
context: { env: true, waitUntil: true },
|
|
376
376
|
});
|
|
377
377
|
// A client cannot call a method: without the edge's vouching, x-sb-rpc is just a header.
|
|
378
|
-
const forgedRpc = await fetch(`http://127.0.0.1:${port}/ping`, {
|
|
378
|
+
const forgedRpc = await fetch(`http://127.0.0.1:${port}/ping`, {
|
|
379
|
+
method: "POST",
|
|
380
|
+
headers: { "x-sb-rpc": "fail" },
|
|
381
|
+
body: '["x"]',
|
|
382
|
+
});
|
|
379
383
|
assert.equal(await forgedRpc.text(), "pong");
|
|
380
384
|
|
|
381
385
|
// A deployment calling itself, 30 levels deep: every level waits on the next at once.
|
|
@@ -394,19 +398,41 @@ export default {
|
|
|
394
398
|
const legacyPort = freePort();
|
|
395
399
|
const legacySource = join(workdir, "legacy.generated.js");
|
|
396
400
|
const legacyBinary = join(workdir, "legacy-native");
|
|
397
|
-
await writeFile(
|
|
398
|
-
|
|
399
|
-
|
|
401
|
+
await writeFile(
|
|
402
|
+
legacySource,
|
|
403
|
+
wrapNativeFetchHandler(
|
|
404
|
+
legacyHandler,
|
|
405
|
+
core.replace(TRANSPORT_MARKER, transport),
|
|
406
|
+
{},
|
|
407
|
+
bindings,
|
|
408
|
+
undefined,
|
|
409
|
+
"2026-10-21",
|
|
410
|
+
),
|
|
411
|
+
);
|
|
412
|
+
await compileNative({
|
|
413
|
+
generated: legacySource,
|
|
414
|
+
binary: legacyBinary,
|
|
415
|
+
dir: workdir,
|
|
416
|
+
cacheRoot: workdir,
|
|
417
|
+
failure: "legacy compile failed",
|
|
418
|
+
});
|
|
400
419
|
legacy = Bun.spawn([legacyBinary], {
|
|
401
420
|
cwd: workdir,
|
|
402
|
-
env: {
|
|
421
|
+
env: {
|
|
422
|
+
...process.env,
|
|
423
|
+
PORT: String(legacyPort),
|
|
424
|
+
SB_BROKER_PORT: String(brokerServer.port),
|
|
425
|
+
SB_BROKER_TOKEN: "native-services",
|
|
426
|
+
},
|
|
403
427
|
stdout: "ignore",
|
|
404
428
|
stderr: "inherit",
|
|
405
429
|
});
|
|
406
430
|
let legacyText = "";
|
|
407
431
|
for (let attempt = 0; attempt < 50 && !legacyText; attempt++) {
|
|
408
432
|
try {
|
|
409
|
-
legacyText = await (
|
|
433
|
+
legacyText = await (
|
|
434
|
+
await fetch(`http://127.0.0.1:${legacyPort}/`, { signal: AbortSignal.timeout(20_000) })
|
|
435
|
+
).text();
|
|
410
436
|
} catch {
|
|
411
437
|
await Bun.sleep(100);
|
|
412
438
|
}
|
|
@@ -2,10 +2,10 @@ import assert from "node:assert/strict";
|
|
|
2
2
|
import { mkdtemp, readFile, rm, writeFile } from "node:fs/promises";
|
|
3
3
|
import net from "node:net";
|
|
4
4
|
import { tmpdir } from "node:os";
|
|
5
|
-
import { join
|
|
5
|
+
import { join } from "node:path";
|
|
6
6
|
import { Duplex } from "node:stream";
|
|
7
7
|
import tls from "node:tls";
|
|
8
|
-
import {
|
|
8
|
+
import { compileNative } from "./native-compile";
|
|
9
9
|
import { createBroker, listen } from "../../wire/src/broker";
|
|
10
10
|
import { EMPTY_BINDINGS, preludePath, TRANSPORT_MARKER, transportPath, wrapNativeFetchHandler } from "../src/wrap";
|
|
11
11
|
|
|
@@ -364,9 +364,6 @@ const get = async (path: string, base = port) => {
|
|
|
364
364
|
};
|
|
365
365
|
|
|
366
366
|
try {
|
|
367
|
-
const porffor = await ensurePorffor({ cacheRoot: workdir });
|
|
368
|
-
const node = Bun.which("node");
|
|
369
|
-
if (!node) throw new Error("native sockets test needs node on PATH");
|
|
370
367
|
const [core, transport] = await Promise.all([
|
|
371
368
|
readFile(preludePath, "utf8"),
|
|
372
369
|
readFile(transportPath("broker"), "utf8"),
|
|
@@ -385,21 +382,7 @@ try {
|
|
|
385
382
|
"2026-11-17",
|
|
386
383
|
),
|
|
387
384
|
);
|
|
388
|
-
|
|
389
|
-
[node, resolve(porffor, "runtime/index.js"), "native", generated, "-o", binary, "-s", "-O0"],
|
|
390
|
-
{
|
|
391
|
-
cwd: workdir,
|
|
392
|
-
env: process.env,
|
|
393
|
-
stdout: "pipe",
|
|
394
|
-
stderr: "pipe",
|
|
395
|
-
},
|
|
396
|
-
);
|
|
397
|
-
const [exitCode, stdout, stderr] = await Promise.all([
|
|
398
|
-
compile.exited,
|
|
399
|
-
new Response(compile.stdout).text(),
|
|
400
|
-
new Response(compile.stderr).text(),
|
|
401
|
-
]);
|
|
402
|
-
assert.equal(exitCode, 0, `Porffor native compile failed:\n${stderr}\n${stdout}`);
|
|
385
|
+
await compileNative({ generated, binary, dir: workdir, cacheRoot: workdir });
|
|
403
386
|
|
|
404
387
|
const start = async (listening: number, brokerPort: number) => {
|
|
405
388
|
const child = Bun.spawn([binary], {
|
package/test/native-streaming.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import assert from "node:assert/strict";
|
|
2
2
|
import { mkdtemp, readFile, rm, writeFile } from "node:fs/promises";
|
|
3
3
|
import { tmpdir } from "node:os";
|
|
4
|
-
import { join
|
|
5
|
-
import {
|
|
4
|
+
import { join } from "node:path";
|
|
5
|
+
import { compileNative } from "./native-compile";
|
|
6
6
|
import { preludePath, TRANSPORT_MARKER, transportPath, wrapNativeFetchHandler } from "../src/wrap";
|
|
7
7
|
|
|
8
8
|
// A ReadableStream response body is streamed (B19): each chunk reaches the client when the
|
|
@@ -36,14 +36,7 @@ function freePort(): number {
|
|
|
36
36
|
const workdir = await mkdtemp(join(tmpdir(), "sb-native-streaming-"));
|
|
37
37
|
let server: ReturnType<typeof Bun.spawn> | undefined;
|
|
38
38
|
try {
|
|
39
|
-
const
|
|
40
|
-
const node = Bun.which("node");
|
|
41
|
-
if (!node) throw new Error("native streaming test needs node on PATH");
|
|
42
|
-
|
|
43
|
-
const [core, broker] = await Promise.all([
|
|
44
|
-
readFile(preludePath, "utf8"),
|
|
45
|
-
readFile(transportPath("broker"), "utf8"),
|
|
46
|
-
]);
|
|
39
|
+
const [core, broker] = await Promise.all([readFile(preludePath, "utf8"), readFile(transportPath("broker"), "utf8")]);
|
|
47
40
|
assert(core.includes(TRANSPORT_MARKER), "runtime prelude is missing its transport marker");
|
|
48
41
|
const prelude = core.replace(TRANSPORT_MARKER, broker);
|
|
49
42
|
const generated = join(workdir, "streaming.generated.js");
|
|
@@ -51,18 +44,7 @@ try {
|
|
|
51
44
|
await writeFile(generated, wrapNativeFetchHandler(handler, prelude, undefined, undefined, undefined, "2026-10-01"));
|
|
52
45
|
await rm(binary, { force: true });
|
|
53
46
|
|
|
54
|
-
|
|
55
|
-
cwd: workdir,
|
|
56
|
-
env: process.env,
|
|
57
|
-
stdout: "pipe",
|
|
58
|
-
stderr: "pipe",
|
|
59
|
-
});
|
|
60
|
-
const [exitCode, stdout, stderr] = await Promise.all([
|
|
61
|
-
compile.exited,
|
|
62
|
-
new Response(compile.stdout).text(),
|
|
63
|
-
new Response(compile.stderr).text(),
|
|
64
|
-
]);
|
|
65
|
-
assert.equal(exitCode, 0, `Porffor native compile failed:\n${stderr}\n${stdout}`);
|
|
47
|
+
await compileNative({ generated, binary, dir: workdir });
|
|
66
48
|
|
|
67
49
|
const port = freePort();
|
|
68
50
|
server = Bun.spawn([binary], {
|
package/test/native-streams.ts
CHANGED
|
@@ -1,13 +1,28 @@
|
|
|
1
1
|
import assert from "node:assert/strict";
|
|
2
2
|
import { mkdtemp, readFile, rm, writeFile } from "node:fs/promises";
|
|
3
3
|
import { tmpdir } from "node:os";
|
|
4
|
-
import { join
|
|
5
|
-
import {
|
|
4
|
+
import { join } from "node:path";
|
|
5
|
+
import { compileNative } from "./native-compile";
|
|
6
6
|
import { preludePath, TRANSPORT_MARKER, transportPath, wrapNativeFetchHandler } from "../src/wrap";
|
|
7
7
|
|
|
8
|
-
const expected = {
|
|
9
|
-
|
|
10
|
-
|
|
8
|
+
const expected = {
|
|
9
|
+
chunks: ["a", "b"],
|
|
10
|
+
transformed: ["X", "Y"],
|
|
11
|
+
first: { value: "hello", done: false },
|
|
12
|
+
done: true,
|
|
13
|
+
locked: false,
|
|
14
|
+
lockError: true,
|
|
15
|
+
cancelReason: "stop",
|
|
16
|
+
error: "broken",
|
|
17
|
+
tee: [
|
|
18
|
+
[1, 2],
|
|
19
|
+
[1, 2],
|
|
20
|
+
],
|
|
21
|
+
pulled: [3, 4],
|
|
22
|
+
pending: "later",
|
|
23
|
+
bytes: [7, 8],
|
|
24
|
+
byob: [9, 10],
|
|
25
|
+
};
|
|
11
26
|
const handler = `export default { async fetch(request) {
|
|
12
27
|
if (new URL(request.url).pathname === "/null") return new Response(null);
|
|
13
28
|
const stream = new ReadableStream({start(c){c.enqueue("hello");c.close();}});
|
|
@@ -46,14 +61,7 @@ function freePort(): number {
|
|
|
46
61
|
const workdir = await mkdtemp(join(tmpdir(), "sb-native-streams-"));
|
|
47
62
|
let server: ReturnType<typeof Bun.spawn> | undefined;
|
|
48
63
|
try {
|
|
49
|
-
const
|
|
50
|
-
const node = Bun.which("node");
|
|
51
|
-
if (!node) throw new Error("native streams test needs node on PATH");
|
|
52
|
-
|
|
53
|
-
const [core, broker] = await Promise.all([
|
|
54
|
-
readFile(preludePath, "utf8"),
|
|
55
|
-
readFile(transportPath("broker"), "utf8"),
|
|
56
|
-
]);
|
|
64
|
+
const [core, broker] = await Promise.all([readFile(preludePath, "utf8"), readFile(transportPath("broker"), "utf8")]);
|
|
57
65
|
assert(core.includes(TRANSPORT_MARKER), "runtime prelude is missing its transport marker");
|
|
58
66
|
const prelude = core.replace(TRANSPORT_MARKER, broker);
|
|
59
67
|
const generated = join(workdir, "streams.generated.js");
|
|
@@ -61,18 +69,7 @@ try {
|
|
|
61
69
|
await writeFile(generated, wrapNativeFetchHandler(handler, prelude));
|
|
62
70
|
await rm(binary, { force: true });
|
|
63
71
|
|
|
64
|
-
|
|
65
|
-
cwd: workdir,
|
|
66
|
-
env: process.env,
|
|
67
|
-
stdout: "pipe",
|
|
68
|
-
stderr: "pipe",
|
|
69
|
-
});
|
|
70
|
-
const [exitCode, stdout, stderr] = await Promise.all([
|
|
71
|
-
compile.exited,
|
|
72
|
-
new Response(compile.stdout).text(),
|
|
73
|
-
new Response(compile.stderr).text(),
|
|
74
|
-
]);
|
|
75
|
-
assert.equal(exitCode, 0, `Porffor native compile failed:\n${stderr}\n${stdout}`);
|
|
72
|
+
await compileNative({ generated, binary, dir: workdir });
|
|
76
73
|
|
|
77
74
|
const port = freePort();
|
|
78
75
|
server = Bun.spawn([binary], {
|
package/test/native-subtle.ts
CHANGED
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import assert from "node:assert/strict";
|
|
2
2
|
import { mkdtemp, readFile, rm, writeFile } from "node:fs/promises";
|
|
3
3
|
import { tmpdir } from "node:os";
|
|
4
|
-
import { join
|
|
5
|
-
import {
|
|
6
|
-
import { ensurePorffor } from "../../toolchain/src/acquire";
|
|
4
|
+
import { join } from "node:path";
|
|
5
|
+
import { compileNative } from "./native-compile";
|
|
7
6
|
import { jsonObject, parseJsonValue, type JsonObject, type JsonValue } from "../../wire/src/json";
|
|
8
7
|
import { SUBTLE_DATE } from "../src/subtle-date";
|
|
9
8
|
import { preludePath, TRANSPORT_MARKER, transportPath, wrapNativeFetchHandler } from "../src/wrap";
|
|
@@ -109,9 +108,6 @@ async function run(date: string): Promise<JsonObject> {
|
|
|
109
108
|
const workdir = await mkdtemp(join(tmpdir(), "sb-native-subtle-"));
|
|
110
109
|
let server: ReturnType<typeof Bun.spawn> | undefined;
|
|
111
110
|
try {
|
|
112
|
-
const porffor = await ensurePorffor();
|
|
113
|
-
const node = Bun.which("node");
|
|
114
|
-
if (!node) throw new Error("native subtle test needs node on PATH");
|
|
115
111
|
const [core, broker] = await Promise.all([
|
|
116
112
|
readFile(preludePath, "utf8"),
|
|
117
113
|
readFile(transportPath("broker"), "utf8"),
|
|
@@ -123,21 +119,7 @@ async function run(date: string): Promise<JsonObject> {
|
|
|
123
119
|
generated,
|
|
124
120
|
wrapNativeFetchHandler(handler, core.replace(TRANSPORT_MARKER, broker), undefined, undefined, undefined, date),
|
|
125
121
|
);
|
|
126
|
-
|
|
127
|
-
[node, resolve(porffor, "runtime/index.js"), "native", generated, "-o", binary, "-s", "-O0"],
|
|
128
|
-
{
|
|
129
|
-
cwd: workdir,
|
|
130
|
-
env: { ...process.env, ...(await bearsslEnv()) },
|
|
131
|
-
stdout: "pipe",
|
|
132
|
-
stderr: "pipe",
|
|
133
|
-
},
|
|
134
|
-
);
|
|
135
|
-
const [exitCode, stdout, stderr] = await Promise.all([
|
|
136
|
-
compile.exited,
|
|
137
|
-
new Response(compile.stdout).text(),
|
|
138
|
-
new Response(compile.stderr).text(),
|
|
139
|
-
]);
|
|
140
|
-
assert.equal(exitCode, 0, `Porffor native compile failed:\n${stderr}\n${stdout}`);
|
|
122
|
+
await compileNative({ generated, binary, dir: workdir, bearssl: true });
|
|
141
123
|
const port = freePort();
|
|
142
124
|
server = Bun.spawn([binary], {
|
|
143
125
|
cwd: workdir,
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import assert from "node:assert/strict";
|
|
2
2
|
import { mkdtemp, readFile, rm, writeFile } from "node:fs/promises";
|
|
3
3
|
import { tmpdir } from "node:os";
|
|
4
|
-
import { join
|
|
5
|
-
import {
|
|
4
|
+
import { join } from "node:path";
|
|
5
|
+
import { compileNative } from "./native-compile";
|
|
6
6
|
import { preludePath, TRANSPORT_MARKER, transportPath, wrapNativeFetchHandler } from "../src/wrap";
|
|
7
7
|
|
|
8
8
|
// TextDecoder encodings (UTF-16LE/BE, windows-1252), Blob.stream and Response.url in a compiled handler, compared with Bun
|
|
@@ -56,10 +56,6 @@ function freePort(): number {
|
|
|
56
56
|
const workdir = await mkdtemp(join(tmpdir(), "sb-native-textdecoder-encodings-"));
|
|
57
57
|
let server: ReturnType<typeof Bun.spawn> | undefined;
|
|
58
58
|
try {
|
|
59
|
-
const porffor = await ensurePorffor();
|
|
60
|
-
const node = Bun.which("node");
|
|
61
|
-
if (!node) throw new Error("native streams test needs node on PATH");
|
|
62
|
-
|
|
63
59
|
const [core, broker] = await Promise.all([readFile(preludePath, "utf8"), readFile(transportPath("broker"), "utf8")]);
|
|
64
60
|
assert(core.includes(TRANSPORT_MARKER), "runtime prelude is missing its transport marker");
|
|
65
61
|
const prelude = core.replace(TRANSPORT_MARKER, broker);
|
|
@@ -68,21 +64,7 @@ try {
|
|
|
68
64
|
await writeFile(generated, wrapNativeFetchHandler(handler, prelude));
|
|
69
65
|
await rm(binary, { force: true });
|
|
70
66
|
|
|
71
|
-
|
|
72
|
-
[node, resolve(porffor, "runtime/index.js"), "native", generated, "-o", binary, "-s", "-O0"],
|
|
73
|
-
{
|
|
74
|
-
cwd: workdir,
|
|
75
|
-
env: process.env,
|
|
76
|
-
stdout: "pipe",
|
|
77
|
-
stderr: "pipe",
|
|
78
|
-
},
|
|
79
|
-
);
|
|
80
|
-
const [exitCode, stdout, stderr] = await Promise.all([
|
|
81
|
-
compile.exited,
|
|
82
|
-
new Response(compile.stdout).text(),
|
|
83
|
-
new Response(compile.stderr).text(),
|
|
84
|
-
]);
|
|
85
|
-
assert.equal(exitCode, 0, `Porffor native compile failed:\n${stderr}\n${stdout}`);
|
|
67
|
+
await compileNative({ generated, binary, dir: workdir });
|
|
86
68
|
|
|
87
69
|
const port = freePort();
|
|
88
70
|
server = Bun.spawn([binary], {
|
package/test/native-timers.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import assert from "node:assert/strict";
|
|
2
2
|
import { mkdtemp, readFile, rm, writeFile } from "node:fs/promises";
|
|
3
3
|
import { tmpdir } from "node:os";
|
|
4
|
-
import { join
|
|
5
|
-
import {
|
|
4
|
+
import { join } from "node:path";
|
|
5
|
+
import { compileNative } from "./native-compile";
|
|
6
6
|
import { preludePath, TRANSPORT_MARKER, transportPath, wrapNativeFetchHandler } from "../src/wrap";
|
|
7
7
|
|
|
8
8
|
const expected = { fired: 7, cancelled: false, ticks: 2 };
|
|
@@ -31,14 +31,7 @@ function freePort(): number {
|
|
|
31
31
|
const workdir = await mkdtemp(join(tmpdir(), "sb-native-timers-"));
|
|
32
32
|
let server: ReturnType<typeof Bun.spawn> | undefined;
|
|
33
33
|
try {
|
|
34
|
-
const
|
|
35
|
-
const node = Bun.which("node");
|
|
36
|
-
if (!node) throw new Error("native timers test needs node on PATH");
|
|
37
|
-
|
|
38
|
-
const [core, broker] = await Promise.all([
|
|
39
|
-
readFile(preludePath, "utf8"),
|
|
40
|
-
readFile(transportPath("broker"), "utf8"),
|
|
41
|
-
]);
|
|
34
|
+
const [core, broker] = await Promise.all([readFile(preludePath, "utf8"), readFile(transportPath("broker"), "utf8")]);
|
|
42
35
|
assert(core.includes(TRANSPORT_MARKER), "runtime prelude is missing its transport marker");
|
|
43
36
|
const prelude = core.replace(TRANSPORT_MARKER, broker);
|
|
44
37
|
const generated = join(workdir, "timers.generated.js");
|
|
@@ -46,18 +39,7 @@ try {
|
|
|
46
39
|
await writeFile(generated, wrapNativeFetchHandler(handler, prelude));
|
|
47
40
|
await rm(binary, { force: true });
|
|
48
41
|
|
|
49
|
-
|
|
50
|
-
cwd: workdir,
|
|
51
|
-
env: process.env,
|
|
52
|
-
stdout: "pipe",
|
|
53
|
-
stderr: "pipe",
|
|
54
|
-
});
|
|
55
|
-
const [exitCode, stdout, stderr] = await Promise.all([
|
|
56
|
-
compile.exited,
|
|
57
|
-
new Response(compile.stdout).text(),
|
|
58
|
-
new Response(compile.stderr).text(),
|
|
59
|
-
]);
|
|
60
|
-
assert.equal(exitCode, 0, `Porffor native compile failed:\n${stderr}\n${stdout}`);
|
|
42
|
+
await compileNative({ generated, binary, dir: workdir });
|
|
61
43
|
|
|
62
44
|
const port = freePort();
|
|
63
45
|
server = Bun.spawn([binary], {
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import assert from "node:assert/strict";
|
|
2
2
|
import { mkdtemp, readFile, rm, writeFile } from "node:fs/promises";
|
|
3
3
|
import { tmpdir } from "node:os";
|
|
4
|
-
import { join
|
|
5
|
-
import {
|
|
4
|
+
import { join } from "node:path";
|
|
5
|
+
import { compileNative } from "./native-compile";
|
|
6
6
|
import { preludePath, TRANSPORT_MARKER, transportPath, wrapNativeFetchHandler } from "../src/wrap";
|
|
7
7
|
|
|
8
8
|
// A promise that rejects with nobody waiting on it (a binding call that failed and was never
|
|
@@ -50,9 +50,6 @@ for (const date of ["2026-09-28", "2026-10-24"]) {
|
|
|
50
50
|
const workdir = await mkdtemp(join(tmpdir(), "sb-native-unhandled-"));
|
|
51
51
|
let server: ReturnType<typeof Bun.spawn> | undefined;
|
|
52
52
|
try {
|
|
53
|
-
const porffor = await ensurePorffor();
|
|
54
|
-
const node = Bun.which("node");
|
|
55
|
-
if (!node) throw new Error("native unhandled rejection test needs node on PATH");
|
|
56
53
|
const [core, broker] = await Promise.all([
|
|
57
54
|
readFile(preludePath, "utf8"),
|
|
58
55
|
readFile(transportPath("broker"), "utf8"),
|
|
@@ -64,21 +61,7 @@ for (const date of ["2026-09-28", "2026-10-24"]) {
|
|
|
64
61
|
generated,
|
|
65
62
|
wrapNativeFetchHandler(handler, core.replace(TRANSPORT_MARKER, broker), undefined, undefined, undefined, date),
|
|
66
63
|
);
|
|
67
|
-
|
|
68
|
-
[node, resolve(porffor, "runtime/index.js"), "native", generated, "-o", binary, "-s", "-O0"],
|
|
69
|
-
{
|
|
70
|
-
cwd: workdir,
|
|
71
|
-
env: process.env,
|
|
72
|
-
stdout: "pipe",
|
|
73
|
-
stderr: "pipe",
|
|
74
|
-
},
|
|
75
|
-
);
|
|
76
|
-
const [exitCode, stdout, stderr] = await Promise.all([
|
|
77
|
-
compile.exited,
|
|
78
|
-
new Response(compile.stdout).text(),
|
|
79
|
-
new Response(compile.stderr).text(),
|
|
80
|
-
]);
|
|
81
|
-
assert.equal(exitCode, 0, `Porffor native compile failed:\n${stderr}\n${stdout}`);
|
|
64
|
+
await compileNative({ generated, binary, dir: workdir });
|
|
82
65
|
|
|
83
66
|
const port = freePort();
|
|
84
67
|
server = Bun.spawn([binary], {
|
package/test/native-url.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import assert from "node:assert/strict";
|
|
2
2
|
import { mkdtemp, readFile, rm, writeFile } from "node:fs/promises";
|
|
3
3
|
import { tmpdir } from "node:os";
|
|
4
|
-
import { join
|
|
5
|
-
import {
|
|
4
|
+
import { join } from "node:path";
|
|
5
|
+
import { compileNative } from "./native-compile";
|
|
6
6
|
import { preludePath, TRANSPORT_MARKER, transportPath, wrapNativeFetchHandler } from "../src/wrap";
|
|
7
7
|
|
|
8
8
|
// URL as WHATWG defines it (Bun's URL is the reference): base URLs, setters on every
|
|
@@ -84,14 +84,7 @@ function freePort(): number {
|
|
|
84
84
|
const workdir = await mkdtemp(join(tmpdir(), "sb-native-url-"));
|
|
85
85
|
let server: ReturnType<typeof Bun.spawn> | undefined;
|
|
86
86
|
try {
|
|
87
|
-
const
|
|
88
|
-
const node = Bun.which("node");
|
|
89
|
-
if (!node) throw new Error("native streams test needs node on PATH");
|
|
90
|
-
|
|
91
|
-
const [core, broker] = await Promise.all([
|
|
92
|
-
readFile(preludePath, "utf8"),
|
|
93
|
-
readFile(transportPath("broker"), "utf8"),
|
|
94
|
-
]);
|
|
87
|
+
const [core, broker] = await Promise.all([readFile(preludePath, "utf8"), readFile(transportPath("broker"), "utf8")]);
|
|
95
88
|
assert(core.includes(TRANSPORT_MARKER), "runtime prelude is missing its transport marker");
|
|
96
89
|
const prelude = core.replace(TRANSPORT_MARKER, broker);
|
|
97
90
|
const generated = join(workdir, "url.generated.js");
|
|
@@ -99,18 +92,7 @@ try {
|
|
|
99
92
|
await writeFile(generated, wrapNativeFetchHandler(handler, prelude));
|
|
100
93
|
await rm(binary, { force: true });
|
|
101
94
|
|
|
102
|
-
|
|
103
|
-
cwd: workdir,
|
|
104
|
-
env: process.env,
|
|
105
|
-
stdout: "pipe",
|
|
106
|
-
stderr: "pipe",
|
|
107
|
-
});
|
|
108
|
-
const [exitCode, stdout, stderr] = await Promise.all([
|
|
109
|
-
compile.exited,
|
|
110
|
-
new Response(compile.stdout).text(),
|
|
111
|
-
new Response(compile.stderr).text(),
|
|
112
|
-
]);
|
|
113
|
-
assert.equal(exitCode, 0, `Porffor native compile failed:\n${stderr}\n${stdout}`);
|
|
95
|
+
await compileNative({ generated, binary, dir: workdir });
|
|
114
96
|
|
|
115
97
|
const port = freePort();
|
|
116
98
|
server = Bun.spawn([binary], {
|
|
@@ -133,9 +115,17 @@ try {
|
|
|
133
115
|
// SAFETY: the handler above is the only producer of this body: a JSON array with one
|
|
134
116
|
// string per case; the comparison below reports any entry that differs.
|
|
135
117
|
const got = JSON.parse(await (await fetch(`http://127.0.0.1:${port}/`)).text()) as string[];
|
|
136
|
-
const diffs = CASES.flatMap((c, i) =>
|
|
137
|
-
|
|
138
|
-
|
|
118
|
+
const diffs = CASES.flatMap((c, i) =>
|
|
119
|
+
got[i] === want[i] ? [] : [`${c}\n want ${JSON.stringify(want[i])}\n got ${JSON.stringify(got[i])}`],
|
|
120
|
+
);
|
|
121
|
+
assert.deepEqual(
|
|
122
|
+
diffs,
|
|
123
|
+
[],
|
|
124
|
+
`URL differs from WHATWG in ${diffs.length} of ${CASES.length} cases:\n${diffs.join("\n")}`,
|
|
125
|
+
);
|
|
126
|
+
console.log(
|
|
127
|
+
`Native URL matches WHATWG URL in all ${CASES.length} cases: base URLs, setters, hash, ports, dot segments, encoding, searchParams`,
|
|
128
|
+
);
|
|
139
129
|
} finally {
|
|
140
130
|
if (server) {
|
|
141
131
|
server.kill(9);
|
package/test/native-utf8.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import assert from "node:assert/strict";
|
|
2
2
|
import { mkdtemp, readFile, rm, writeFile } from "node:fs/promises";
|
|
3
3
|
import { tmpdir } from "node:os";
|
|
4
|
-
import { join
|
|
5
|
-
import {
|
|
4
|
+
import { join } from "node:path";
|
|
5
|
+
import { compileNative } from "./native-compile";
|
|
6
6
|
import { createBroker, listen } from "../../wire/src/broker";
|
|
7
7
|
import { EMPTY_BINDINGS, preludePath, TRANSPORT_MARKER, transportPath, wrapNativeFetchHandler } from "../src/wrap";
|
|
8
8
|
|
|
@@ -54,10 +54,6 @@ const broker = createBroker({
|
|
|
54
54
|
const brokerServer = listen(broker, "127.0.0.1", 0);
|
|
55
55
|
let server: ReturnType<typeof Bun.spawn> | undefined;
|
|
56
56
|
try {
|
|
57
|
-
const porffor = await ensurePorffor({ cacheRoot: workdir });
|
|
58
|
-
const node = Bun.which("node");
|
|
59
|
-
if (!node) throw new Error("native UTF-8 test needs node on PATH");
|
|
60
|
-
|
|
61
57
|
const [core, transport] = await Promise.all([
|
|
62
58
|
readFile(preludePath, "utf8"),
|
|
63
59
|
readFile(transportPath("broker"), "utf8"),
|
|
@@ -65,20 +61,12 @@ try {
|
|
|
65
61
|
assert(core.includes(TRANSPORT_MARKER), "runtime prelude is missing its transport marker");
|
|
66
62
|
const generated = join(workdir, "utf8.generated.js");
|
|
67
63
|
const binary = join(workdir, "utf8-native");
|
|
68
|
-
await writeFile(
|
|
64
|
+
await writeFile(
|
|
65
|
+
generated,
|
|
66
|
+
wrapNativeFetchHandler(handler, core.replace(TRANSPORT_MARKER, transport), {}, bindings, undefined, "2026-10-21"),
|
|
67
|
+
);
|
|
69
68
|
|
|
70
|
-
|
|
71
|
-
cwd: workdir,
|
|
72
|
-
env: process.env,
|
|
73
|
-
stdout: "pipe",
|
|
74
|
-
stderr: "pipe",
|
|
75
|
-
});
|
|
76
|
-
const [exitCode, stdout, stderr] = await Promise.all([
|
|
77
|
-
compile.exited,
|
|
78
|
-
new Response(compile.stdout).text(),
|
|
79
|
-
new Response(compile.stderr).text(),
|
|
80
|
-
]);
|
|
81
|
-
assert.equal(exitCode, 0, `Porffor native compile failed:\n${stderr}\n${stdout}`);
|
|
69
|
+
await compileNative({ generated, binary, dir: workdir, cacheRoot: workdir });
|
|
82
70
|
|
|
83
71
|
const port = freePort();
|
|
84
72
|
server = Bun.spawn([binary], {
|
|
@@ -121,8 +109,14 @@ try {
|
|
|
121
109
|
assert.match(body.error, /tabellà/);
|
|
122
110
|
assert.equal(body.url, "shadowed");
|
|
123
111
|
const stored = await (await fetch(`http://127.0.0.1:${port}/`, { method: "POST", body: "uploaded é" })).json();
|
|
124
|
-
assert.deepEqual(
|
|
125
|
-
|
|
112
|
+
assert.deepEqual(
|
|
113
|
+
stored,
|
|
114
|
+
{ r2: "uploaded é", kv: "uploaded é", stream: "uploaded é" },
|
|
115
|
+
"put(key, request.body) stores the request body, and body reads as UTF-8",
|
|
116
|
+
);
|
|
117
|
+
console.log(
|
|
118
|
+
"Non-ASCII KV, D1 and error text round-trip through the broker; a handler-level URL stays scoped; put(key, request.body) stores the body",
|
|
119
|
+
);
|
|
126
120
|
} finally {
|
|
127
121
|
if (server) {
|
|
128
122
|
server.kill(9);
|