Skip to content

Commit d627966

Browse files
authored
Merge pull request #25 from golemcloud/async-wasi-runtime
Switched from Tokio to wasi-async-runtime
2 parents e6e332c + 078606b commit d627966

File tree

13 files changed

+507
-333
lines changed

13 files changed

+507
-333
lines changed

crates/wasm-rquickjs/skeleton/Cargo.toml_

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,16 @@ logging = ["dep:log", "dep:wasi-logger"]
2121
[dependencies]
2222
# Core dependencies
2323
rquickjs = { version = "0.9.0", default-features = false, features = ["futures", "bindgen", "loader", "macro"] }
24-
tokio = { version = "1.43.0", features = ["macros", "rt", "sync", "time"] }
25-
tokio-util = { version = "0.7.15", default-features = false }
24+
25+
futures = { version = "0.3.31", features = [] }
26+
futures-concurrency = "7.6.3"
27+
pin-project = "1.1.10"
28+
wasi = "0.12.1+wasi-0.2.0"
29+
wasi-async-runtime = "0.1.2"
2630
wit-bindgen-rt = { version = "0.42.1", features = ["bitflags"] }
2731

2832
# HTTP
29-
reqwest = { git = "https://github.com/golemcloud/reqwest", branch = "update-may-2025", optional = true }
33+
reqwest = { git = "https://github.com/golemcloud/reqwest", branch = "update-july-2025", features = ["async"], optional = true }
3034

3135
# Logging
3236
log = { version = "0.4.22", default-features = false, optional = true }

crates/wasm-rquickjs/skeleton/src/builtin/http.js

Lines changed: 49 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -39,36 +39,38 @@ export async function fetch(resource, options = {}) {
3939

4040
let body = options.body || '';
4141

42-
if (body instanceof ArrayBuffer) {
43-
request.arrayBufferBody(body);
44-
} else if (body instanceof Uint8Array) {
45-
request.uint8ArrayBody(body);
46-
} else if (typeof body === 'string' || body instanceof String) {
47-
request.stringBody(body);
48-
} else if (body instanceof ReadableStream) {
49-
// TODO: currently the native implementation does not support streaming request body, so we just buffer the stream here
50-
const reader = body.getReader();
51-
let chunks = [];
52-
let done, value;
53-
while ({done, value} = await reader.read(), !done) {
54-
chunks.push(value);
55-
}
56-
// Concatenate all chunks into a single Uint8Array
57-
const totalLength = chunks.reduce((acc, chunk) => acc + chunk.length, 0);
58-
const concatenated = new Uint8Array(totalLength);
59-
let offset = 0;
60-
for (const chunk of chunks) {
61-
concatenated.set(chunk, offset);
62-
offset += chunk.length;
42+
if (body instanceof ReadableStream) {
43+
request.initSend();
44+
const bodyWriter = request.initRequestBody();
45+
request.sendRequest();
46+
47+
async function sendBody(bodyWriter, body) {
48+
const reader = body.getReader();
49+
while (true) {
50+
const { done, value } = await reader.read();
51+
if (done) break;
52+
await bodyWriter.writeRequestBodyChunk(value);
53+
}
54+
bodyWriter.finishBody();
6355
}
64-
request.uint8ArrayBody(concatenated);
65-
} else {
66-
console.warn('Unsupported body type');
67-
}
6856

69-
let nativeResponse = await request.send();
57+
const [nativeResponse, _] = await Promise.all([request.receiveResponse(), sendBody(bodyWriter, body)]);
58+
59+
return new Response(nativeResponse, resource);
60+
} else {
61+
if (body instanceof ArrayBuffer) {
62+
request.arrayBufferBody(body);
63+
} else if (body instanceof Uint8Array) {
64+
request.uint8ArrayBody(body);
65+
} else if (typeof body === 'string' || body instanceof String) {
66+
request.stringBody(body);
67+
} else {
68+
console.warn('Unsupported body type');
69+
}
7070

71-
return new Response(nativeResponse, resource);
71+
const nativeResponse = await request.simpleSend();
72+
return new Response(nativeResponse, resource);
73+
}
7274
}
7375

7476
export class Response {
@@ -87,9 +89,27 @@ export class Response {
8789
}
8890

8991
get body() {
90-
let streamSource = this.nativeResponse.stream();
92+
let nativeStreamSource = this.nativeResponse.stream();
9193
this.bodyUsed = true;
92-
return new ReadableStream(streamSource);
94+
return new ReadableStream({
95+
start() {
96+
},
97+
get type() {
98+
return "bytes";
99+
},
100+
async pull(controller) {
101+
// controller is https://developer.mozilla.org/en-US/docs/Web/API/ReadableByteStreamController
102+
const [next, err] = await nativeStreamSource.pull();
103+
if (err !== undefined) {
104+
console.error("Error reading response body stream:", err);
105+
controller.error(err);
106+
} else if (next === undefined) {
107+
controller.close();
108+
} else {
109+
controller.enqueue(next);
110+
}
111+
}
112+
});
93113
}
94114

95115
get headers() {

0 commit comments

Comments
 (0)