-
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathtest_http_thenable_skeleton.mjs
More file actions
71 lines (63 loc) · 2.86 KB
/
Copy pathtest_http_thenable_skeleton.mjs
File metadata and controls
71 lines (63 loc) · 2.86 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
// SPDX-License-Identifier: PMPL-1.0-or-later
// issue #225 PR 1 — wasm e2e for the typed-wasm Http skeleton.
//
// Inlines the generic Http host adapter (the reusable package is
// deferred until the Ephapax convergence-ABI review, typed-wasm#31).
// Implements the #205 protocol: http_request_thenable registers a
// Promise keyed by an i32 handle; the harness (the host) resolves it
// and asserts the round-trip. `globalThis.fetch` is stubbed — no
// network. Mirrors the tests/codegen/*.mjs inline-imports style.
import assert from 'node:assert/strict';
import { readFile } from 'node:fs/promises';
// ── stubbed host fetch (no network) ──────────────────────────────────
globalThis.fetch = async (url, init) => ({
status: url.includes('/missing') ? 404 : 200,
headers: { forEach: (cb) => cb('text/plain', 'content-type') },
text: async () => `ok:${init && init.method}`,
});
let inst = null;
const _handles = new Map();
let _next = 1;
const _results = new Map();
function readString(ptr) {
const dv = new DataView(inst.exports.memory.buffer);
const len = dv.getUint32(ptr, true);
const bytes = new Uint8Array(inst.exports.memory.buffer, ptr + 4, len);
return new TextDecoder('utf-8').decode(bytes);
}
// The generic Http convergence adapter (host import surface).
const imports = {
wasi_snapshot_preview1: { fd_write: () => 0 },
Http: {
http_request_thenable: (urlPtr, methodPtr, bodyPtr) => {
const url = readString(urlPtr);
const method = readString(methodPtr);
const body = readString(bodyPtr);
const h = _next++;
const p = globalThis
.fetch(url, { method, body: body || undefined })
.then(async (r) => {
const headers = [];
r.headers.forEach((v, k) => headers.push([k, v]));
return { status: r.status, headers, body: await r.text() };
})
.catch((e) => ({ __error: String(e) }));
_handles.set(h, p);
p.then((v) => _results.set(h, v));
return h;
},
},
};
const buf = await readFile('./tests/codegen/http_thenable_skeleton.wasm');
const m = await WebAssembly.instantiate(buf, imports);
inst = m.instance;
// Pure pass-through: launch() returns the Thenable handle.
const handle = inst.exports.launch();
assert.ok(Number.isInteger(handle) && handle > 0, 'launch returns an i32 Thenable handle');
// Host resolves it via the protocol (guest-side resolution is PR 2/3).
const settled = await _handles.get(handle);
assert.equal(settled.status, 200, 'response status round-trips');
assert.equal(settled.body, 'ok:GET', 'method + body round-trip via readString');
assert.deepEqual(settled.headers, [['content-type', 'text/plain']], 'headers assoc list');
assert.equal(_results.get(handle).status, 200, 'thenableResultJson-equivalent payload stored');
console.log('test_http_thenable_skeleton.mjs OK');