mirror of
https://github.com/denoland/deno.git
synced 2024-11-25 15:29:32 -05:00
perf(runtime): short-circuit queue_async_op
for Poll::Ready (#15773)
This commit is contained in:
parent
83dcf6ede3
commit
8a4e389bca
15 changed files with 295 additions and 167 deletions
19
cli/bench/async_ops.js
Normal file
19
cli/bench/async_ops.js
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
|
||||||
|
const queueMicrotask = globalThis.queueMicrotask || process.nextTick;
|
||||||
|
let [total, count] = typeof Deno !== "undefined"
|
||||||
|
? Deno.args
|
||||||
|
: [process.argv[2], process.argv[3]];
|
||||||
|
|
||||||
|
total = total ? parseInt(total, 0) : 50;
|
||||||
|
count = count ? parseInt(count, 10) : 100000;
|
||||||
|
|
||||||
|
async function bench(fun) {
|
||||||
|
const start = Date.now();
|
||||||
|
for (let i = 0; i < count; i++) await fun();
|
||||||
|
const elapsed = Date.now() - start;
|
||||||
|
const rate = Math.floor(count / (elapsed / 1000));
|
||||||
|
console.log(`time ${elapsed} ms rate ${rate}`);
|
||||||
|
if (--total) queueMicrotask(() => bench(fun));
|
||||||
|
}
|
||||||
|
|
||||||
|
bench(() => Deno.core.opAsync("op_void_async"));
|
22
cli/bench/tcp.js
Normal file
22
cli/bench/tcp.js
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
// Copyright 2018-2022 the Deno authors. All rights reserved. MIT license.
|
||||||
|
|
||||||
|
const listener = Deno.listen({ port: 4500 });
|
||||||
|
const response = new TextEncoder().encode(
|
||||||
|
"HTTP/1.1 200 OK\r\nContent-Length: 12\r\n\r\nHello World\n",
|
||||||
|
);
|
||||||
|
|
||||||
|
// Accept a connection and write packets as fast as possible.
|
||||||
|
async function acceptWrite() {
|
||||||
|
const conn = await listener.accept();
|
||||||
|
try {
|
||||||
|
while (true) {
|
||||||
|
await conn.write(response);
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
// Pass
|
||||||
|
}
|
||||||
|
conn.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
await acceptWrite();
|
||||||
|
await acceptWrite();
|
|
@ -928,7 +928,7 @@ async fn test_resolve_dns() {
|
||||||
let out = String::from_utf8_lossy(&output.stdout);
|
let out = String::from_utf8_lossy(&output.stdout);
|
||||||
assert!(!output.status.success());
|
assert!(!output.status.success());
|
||||||
assert!(err.starts_with("Check file"));
|
assert!(err.starts_with("Check file"));
|
||||||
assert!(err.contains(r#"error: Uncaught (in promise) PermissionDenied: Requires net access to "127.0.0.1:4553""#));
|
assert!(err.contains(r#"error: Uncaught PermissionDenied: Requires net access to "127.0.0.1:4553""#));
|
||||||
assert!(out.is_empty());
|
assert!(out.is_empty());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -950,7 +950,7 @@ async fn test_resolve_dns() {
|
||||||
let out = String::from_utf8_lossy(&output.stdout);
|
let out = String::from_utf8_lossy(&output.stdout);
|
||||||
assert!(!output.status.success());
|
assert!(!output.status.success());
|
||||||
assert!(err.starts_with("Check file"));
|
assert!(err.starts_with("Check file"));
|
||||||
assert!(err.contains(r#"error: Uncaught (in promise) PermissionDenied: Requires net access to "127.0.0.1:4553""#));
|
assert!(err.contains(r#"error: Uncaught PermissionDenied: Requires net access to "127.0.0.1:4553""#));
|
||||||
assert!(out.is_empty());
|
assert!(out.is_empty());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
2
cli/tests/testdata/044_bad_resource.ts.out
vendored
2
cli/tests/testdata/044_bad_resource.ts.out
vendored
|
@ -1,2 +1,2 @@
|
||||||
[WILDCARD]error: Uncaught (in promise) BadResource: Bad resource ID
|
[WILDCARD]error: Uncaught [WILDCARD] BadResource: Bad resource ID
|
||||||
[WILDCARD]
|
[WILDCARD]
|
||||||
|
|
2
cli/tests/testdata/wasm_unreachable.out
vendored
2
cli/tests/testdata/wasm_unreachable.out
vendored
|
@ -1,3 +1,3 @@
|
||||||
error: Uncaught (in promise) RuntimeError: unreachable
|
error: Uncaught [WILDCARD] RuntimeError: unreachable
|
||||||
at <anonymous> (wasm://wasm/d1c677ea:1:41)
|
at <anonymous> (wasm://wasm/d1c677ea:1:41)
|
||||||
at [WILDCARD]/wasm_unreachable.js:[WILDCARD]
|
at [WILDCARD]/wasm_unreachable.js:[WILDCARD]
|
||||||
|
|
|
@ -1202,47 +1202,44 @@ Deno.test({}, function fetchWritableRespProps() {
|
||||||
assertEquals(new_.headers.get("x-deno"), "foo");
|
assertEquals(new_.headers.get("x-deno"), "foo");
|
||||||
});
|
});
|
||||||
|
|
||||||
function returnHostHeaderServer(addr: string): Deno.Listener {
|
|
||||||
const [hostname, port] = addr.split(":");
|
|
||||||
const listener = Deno.listen({
|
|
||||||
hostname,
|
|
||||||
port: Number(port),
|
|
||||||
}) as Deno.Listener;
|
|
||||||
|
|
||||||
listener.accept().then(async (conn: Deno.Conn) => {
|
|
||||||
const httpConn = Deno.serveHttp(conn);
|
|
||||||
|
|
||||||
await httpConn.nextRequest()
|
|
||||||
.then(async (requestEvent: Deno.RequestEvent | null) => {
|
|
||||||
const hostHeader = requestEvent?.request.headers.get("Host");
|
|
||||||
const headersToReturn = hostHeader ? { "Host": hostHeader } : undefined;
|
|
||||||
|
|
||||||
await requestEvent?.respondWith(
|
|
||||||
new Response("", {
|
|
||||||
status: 200,
|
|
||||||
headers: headersToReturn,
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
httpConn.close();
|
|
||||||
});
|
|
||||||
|
|
||||||
return listener;
|
|
||||||
}
|
|
||||||
|
|
||||||
Deno.test(
|
Deno.test(
|
||||||
{ permissions: { net: true } },
|
{ permissions: { net: true } },
|
||||||
async function fetchFilterOutCustomHostHeader(): Promise<
|
async function fetchFilterOutCustomHostHeader(): Promise<
|
||||||
void
|
void
|
||||||
> {
|
> {
|
||||||
const addr = "127.0.0.1:4511";
|
const addr = "127.0.0.1:4511";
|
||||||
const listener = returnHostHeaderServer(addr);
|
const [hostname, port] = addr.split(":");
|
||||||
|
const listener = Deno.listen({
|
||||||
|
hostname,
|
||||||
|
port: Number(port),
|
||||||
|
}) as Deno.Listener;
|
||||||
|
|
||||||
|
let httpConn: Deno.HttpConn;
|
||||||
|
listener.accept().then(async (conn: Deno.Conn) => {
|
||||||
|
httpConn = Deno.serveHttp(conn);
|
||||||
|
|
||||||
|
await httpConn.nextRequest()
|
||||||
|
.then(async (requestEvent: Deno.RequestEvent | null) => {
|
||||||
|
const hostHeader = requestEvent?.request.headers.get("Host");
|
||||||
|
const headersToReturn = hostHeader
|
||||||
|
? { "Host": hostHeader }
|
||||||
|
: undefined;
|
||||||
|
|
||||||
|
await requestEvent?.respondWith(
|
||||||
|
new Response("", {
|
||||||
|
status: 200,
|
||||||
|
headers: headersToReturn,
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
const response = await fetch(`http://${addr}/`, {
|
const response = await fetch(`http://${addr}/`, {
|
||||||
headers: { "Host": "example.com" },
|
headers: { "Host": "example.com" },
|
||||||
});
|
});
|
||||||
await response.text();
|
await response.text();
|
||||||
listener.close();
|
listener.close();
|
||||||
|
httpConn!.close();
|
||||||
|
|
||||||
assertEquals(response.headers.get("Host"), addr);
|
assertEquals(response.headers.get("Host"), addr);
|
||||||
},
|
},
|
||||||
|
|
|
@ -45,11 +45,12 @@ async function writeRequestAndReadResponse(conn: Deno.Conn): Promise<string> {
|
||||||
}
|
}
|
||||||
|
|
||||||
Deno.test({ permissions: { net: true } }, async function httpServerBasic() {
|
Deno.test({ permissions: { net: true } }, async function httpServerBasic() {
|
||||||
|
let httpConn: Deno.HttpConn;
|
||||||
const promise = (async () => {
|
const promise = (async () => {
|
||||||
const listener = Deno.listen({ port: 4501 });
|
const listener = Deno.listen({ port: 4501 });
|
||||||
const conn = await listener.accept();
|
const conn = await listener.accept();
|
||||||
listener.close();
|
listener.close();
|
||||||
const httpConn = Deno.serveHttp(conn);
|
httpConn = Deno.serveHttp(conn);
|
||||||
const reqEvent = await httpConn.nextRequest();
|
const reqEvent = await httpConn.nextRequest();
|
||||||
assert(reqEvent);
|
assert(reqEvent);
|
||||||
const { request, respondWith } = reqEvent;
|
const { request, respondWith } = reqEvent;
|
||||||
|
@ -58,7 +59,6 @@ Deno.test({ permissions: { net: true } }, async function httpServerBasic() {
|
||||||
await respondWith(
|
await respondWith(
|
||||||
new Response("Hello World", { headers: { "foo": "bar" } }),
|
new Response("Hello World", { headers: { "foo": "bar" } }),
|
||||||
);
|
);
|
||||||
httpConn.close();
|
|
||||||
})();
|
})();
|
||||||
|
|
||||||
const resp = await fetch("http://127.0.0.1:4501/", {
|
const resp = await fetch("http://127.0.0.1:4501/", {
|
||||||
|
@ -71,6 +71,8 @@ Deno.test({ permissions: { net: true } }, async function httpServerBasic() {
|
||||||
const cloneText = await clone.text();
|
const cloneText = await clone.text();
|
||||||
assertEquals(cloneText, "Hello World");
|
assertEquals(cloneText, "Hello World");
|
||||||
await promise;
|
await promise;
|
||||||
|
|
||||||
|
httpConn!.close();
|
||||||
});
|
});
|
||||||
|
|
||||||
// https://github.com/denoland/deno/issues/15107
|
// https://github.com/denoland/deno/issues/15107
|
||||||
|
@ -88,7 +90,7 @@ Deno.test(
|
||||||
const { request } = e;
|
const { request } = e;
|
||||||
request.text();
|
request.text();
|
||||||
headers = request.headers;
|
headers = request.headers;
|
||||||
httpConn.close();
|
httpConn!.close();
|
||||||
})();
|
})();
|
||||||
|
|
||||||
const conn = await Deno.connect({ port: 2333 });
|
const conn = await Deno.connect({ port: 2333 });
|
||||||
|
@ -120,7 +122,7 @@ Deno.test(
|
||||||
await respondWith(new Response("Hello World")); // Closes request
|
await respondWith(new Response("Hello World")); // Closes request
|
||||||
|
|
||||||
assertThrows(() => request.headers, TypeError, "request closed");
|
assertThrows(() => request.headers, TypeError, "request closed");
|
||||||
httpConn.close();
|
httpConn!.close();
|
||||||
})();
|
})();
|
||||||
|
|
||||||
const conn = await Deno.connect({ port: 2334 });
|
const conn = await Deno.connect({ port: 2334 });
|
||||||
|
@ -138,17 +140,17 @@ Deno.test(
|
||||||
Deno.test(
|
Deno.test(
|
||||||
{ permissions: { net: true } },
|
{ permissions: { net: true } },
|
||||||
async function httpServerGetRequestBody() {
|
async function httpServerGetRequestBody() {
|
||||||
|
let httpConn: Deno.HttpConn;
|
||||||
const promise = (async () => {
|
const promise = (async () => {
|
||||||
const listener = Deno.listen({ port: 4501 });
|
const listener = Deno.listen({ port: 4501 });
|
||||||
const conn = await listener.accept();
|
const conn = await listener.accept();
|
||||||
listener.close();
|
listener.close();
|
||||||
const httpConn = Deno.serveHttp(conn);
|
httpConn = Deno.serveHttp(conn);
|
||||||
const e = await httpConn.nextRequest();
|
const e = await httpConn.nextRequest();
|
||||||
assert(e);
|
assert(e);
|
||||||
const { request, respondWith } = e;
|
const { request, respondWith } = e;
|
||||||
assertEquals(request.body, null);
|
assertEquals(request.body, null);
|
||||||
await respondWith(new Response("", { headers: {} }));
|
await respondWith(new Response("", { headers: {} }));
|
||||||
httpConn.close();
|
|
||||||
})();
|
})();
|
||||||
|
|
||||||
const conn = await Deno.connect({ port: 4501 });
|
const conn = await Deno.connect({ port: 4501 });
|
||||||
|
@ -166,6 +168,7 @@ Deno.test(
|
||||||
conn.close();
|
conn.close();
|
||||||
|
|
||||||
await promise;
|
await promise;
|
||||||
|
httpConn!.close();
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -178,23 +181,24 @@ Deno.test(
|
||||||
writer.write(new TextEncoder().encode("world"));
|
writer.write(new TextEncoder().encode("world"));
|
||||||
writer.close();
|
writer.close();
|
||||||
|
|
||||||
|
let httpConn: Deno.HttpConn;
|
||||||
|
const listener = Deno.listen({ port: 4501 });
|
||||||
const promise = (async () => {
|
const promise = (async () => {
|
||||||
const listener = Deno.listen({ port: 4501 });
|
|
||||||
const conn = await listener.accept();
|
const conn = await listener.accept();
|
||||||
const httpConn = Deno.serveHttp(conn);
|
httpConn = Deno.serveHttp(conn);
|
||||||
const evt = await httpConn.nextRequest();
|
const evt = await httpConn.nextRequest();
|
||||||
assert(evt);
|
assert(evt);
|
||||||
const { request, respondWith } = evt;
|
const { request, respondWith } = evt;
|
||||||
assert(!request.body);
|
assert(!request.body);
|
||||||
await respondWith(new Response(stream.readable));
|
await respondWith(new Response(stream.readable));
|
||||||
httpConn.close();
|
|
||||||
listener.close();
|
|
||||||
})();
|
})();
|
||||||
|
|
||||||
const resp = await fetch("http://127.0.0.1:4501/");
|
const resp = await fetch("http://127.0.0.1:4501/");
|
||||||
const respBody = await resp.text();
|
const respBody = await resp.text();
|
||||||
assertEquals("hello world", respBody);
|
assertEquals("hello world", respBody);
|
||||||
await promise;
|
await promise;
|
||||||
|
httpConn!.close();
|
||||||
|
listener.close();
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -240,17 +244,16 @@ Deno.test(
|
||||||
Deno.test(
|
Deno.test(
|
||||||
{ permissions: { net: true } },
|
{ permissions: { net: true } },
|
||||||
async function httpServerStreamDuplex() {
|
async function httpServerStreamDuplex() {
|
||||||
|
let httpConn: Deno.HttpConn;
|
||||||
|
const listener = Deno.listen({ port: 4501 });
|
||||||
const promise = (async () => {
|
const promise = (async () => {
|
||||||
const listener = Deno.listen({ port: 4501 });
|
|
||||||
const conn = await listener.accept();
|
const conn = await listener.accept();
|
||||||
const httpConn = Deno.serveHttp(conn);
|
httpConn = Deno.serveHttp(conn);
|
||||||
const evt = await httpConn.nextRequest();
|
const evt = await httpConn.nextRequest();
|
||||||
assert(evt);
|
assert(evt);
|
||||||
const { request, respondWith } = evt;
|
const { request, respondWith } = evt;
|
||||||
assert(request.body);
|
assert(request.body);
|
||||||
await respondWith(new Response(request.body));
|
await respondWith(new Response(request.body));
|
||||||
httpConn.close();
|
|
||||||
listener.close();
|
|
||||||
})();
|
})();
|
||||||
|
|
||||||
const ts = new TransformStream();
|
const ts = new TransformStream();
|
||||||
|
@ -269,10 +272,13 @@ Deno.test(
|
||||||
const chunk2 = await reader.read();
|
const chunk2 = await reader.read();
|
||||||
assert(!chunk2.done);
|
assert(!chunk2.done);
|
||||||
assertEquals(chunk2.value, new Uint8Array([2]));
|
assertEquals(chunk2.value, new Uint8Array([2]));
|
||||||
|
|
||||||
await writable.close();
|
await writable.close();
|
||||||
const chunk3 = await reader.read();
|
const chunk3 = await reader.read();
|
||||||
assert(chunk3.done);
|
assert(chunk3.done);
|
||||||
await promise;
|
await promise;
|
||||||
|
httpConn!.close();
|
||||||
|
listener.close();
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -351,18 +357,17 @@ Deno.test(
|
||||||
Deno.test(
|
Deno.test(
|
||||||
{ permissions: { net: true } },
|
{ permissions: { net: true } },
|
||||||
async function httpServerRegressionHang() {
|
async function httpServerRegressionHang() {
|
||||||
|
let httpConn: Deno.HttpConn;
|
||||||
|
const listener = Deno.listen({ port: 4501 });
|
||||||
const promise = (async () => {
|
const promise = (async () => {
|
||||||
const listener = Deno.listen({ port: 4501 });
|
|
||||||
const conn = await listener.accept();
|
const conn = await listener.accept();
|
||||||
const httpConn = Deno.serveHttp(conn);
|
httpConn = Deno.serveHttp(conn);
|
||||||
const event = await httpConn.nextRequest();
|
const event = await httpConn.nextRequest();
|
||||||
assert(event);
|
assert(event);
|
||||||
const { request, respondWith } = event;
|
const { request, respondWith } = event;
|
||||||
const reqBody = await request.text();
|
const reqBody = await request.text();
|
||||||
assertEquals("request", reqBody);
|
assertEquals("request", reqBody);
|
||||||
await respondWith(new Response("response"));
|
await respondWith(new Response("response"));
|
||||||
httpConn.close();
|
|
||||||
listener.close();
|
|
||||||
})();
|
})();
|
||||||
|
|
||||||
const resp = await fetch("http://127.0.0.1:4501/", {
|
const resp = await fetch("http://127.0.0.1:4501/", {
|
||||||
|
@ -372,6 +377,9 @@ Deno.test(
|
||||||
const respBody = await resp.text();
|
const respBody = await resp.text();
|
||||||
assertEquals("response", respBody);
|
assertEquals("response", respBody);
|
||||||
await promise;
|
await promise;
|
||||||
|
|
||||||
|
httpConn!.close();
|
||||||
|
listener.close();
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -410,7 +418,7 @@ Deno.test(
|
||||||
cancelReason!,
|
cancelReason!,
|
||||||
);
|
);
|
||||||
assert(cancelReason!);
|
assert(cancelReason!);
|
||||||
httpConn.close();
|
httpConn!.close();
|
||||||
listener.close();
|
listener.close();
|
||||||
})();
|
})();
|
||||||
|
|
||||||
|
@ -468,22 +476,23 @@ Deno.test(
|
||||||
Deno.test(
|
Deno.test(
|
||||||
{ permissions: { net: true } },
|
{ permissions: { net: true } },
|
||||||
async function httpServerEmptyBlobResponse() {
|
async function httpServerEmptyBlobResponse() {
|
||||||
|
let httpConn: Deno.HttpConn;
|
||||||
|
const listener = Deno.listen({ port: 4501 });
|
||||||
const promise = (async () => {
|
const promise = (async () => {
|
||||||
const listener = Deno.listen({ port: 4501 });
|
|
||||||
const conn = await listener.accept();
|
const conn = await listener.accept();
|
||||||
const httpConn = Deno.serveHttp(conn);
|
httpConn = Deno.serveHttp(conn);
|
||||||
const event = await httpConn.nextRequest();
|
const event = await httpConn.nextRequest();
|
||||||
assert(event);
|
assert(event);
|
||||||
const { respondWith } = event;
|
const { respondWith } = event;
|
||||||
await respondWith(new Response(new Blob([])));
|
await respondWith(new Response(new Blob([])));
|
||||||
httpConn.close();
|
|
||||||
listener.close();
|
|
||||||
})();
|
})();
|
||||||
|
|
||||||
const resp = await fetch("http://127.0.0.1:4501/");
|
const resp = await fetch("http://127.0.0.1:4501/");
|
||||||
const respBody = await resp.text();
|
const respBody = await resp.text();
|
||||||
assertEquals("", respBody);
|
assertEquals("", respBody);
|
||||||
await promise;
|
await promise;
|
||||||
|
httpConn!.close();
|
||||||
|
listener.close();
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -633,14 +642,14 @@ Deno.test(
|
||||||
}).pipeThrough(new TextEncoderStream());
|
}).pipeThrough(new TextEncoderStream());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let httpConn: Deno.HttpConn;
|
||||||
const listener = Deno.listen({ port: 4501 });
|
const listener = Deno.listen({ port: 4501 });
|
||||||
const finished = (async () => {
|
const finished = (async () => {
|
||||||
const conn = await listener.accept();
|
const conn = await listener.accept();
|
||||||
const httpConn = Deno.serveHttp(conn);
|
httpConn = Deno.serveHttp(conn);
|
||||||
const requestEvent = await httpConn.nextRequest();
|
const requestEvent = await httpConn.nextRequest();
|
||||||
const { respondWith } = requestEvent!;
|
const { respondWith } = requestEvent!;
|
||||||
await respondWith(new Response(periodicStream()));
|
await respondWith(new Response(periodicStream()));
|
||||||
httpConn.close();
|
|
||||||
})();
|
})();
|
||||||
|
|
||||||
// start a client
|
// start a client
|
||||||
|
@ -651,6 +660,8 @@ Deno.test(
|
||||||
|
|
||||||
await finished;
|
await finished;
|
||||||
clientConn.close();
|
clientConn.close();
|
||||||
|
|
||||||
|
httpConn!.close();
|
||||||
listener.close();
|
listener.close();
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
@ -658,11 +669,12 @@ Deno.test(
|
||||||
Deno.test(
|
Deno.test(
|
||||||
{ permissions: { net: true } },
|
{ permissions: { net: true } },
|
||||||
async function httpRequestLatin1Headers() {
|
async function httpRequestLatin1Headers() {
|
||||||
|
let httpConn: Deno.HttpConn;
|
||||||
const promise = (async () => {
|
const promise = (async () => {
|
||||||
const listener = Deno.listen({ port: 4501 });
|
const listener = Deno.listen({ port: 4501 });
|
||||||
const conn = await listener.accept();
|
const conn = await listener.accept();
|
||||||
listener.close();
|
listener.close();
|
||||||
const httpConn = Deno.serveHttp(conn);
|
httpConn = Deno.serveHttp(conn);
|
||||||
const reqEvent = await httpConn.nextRequest();
|
const reqEvent = await httpConn.nextRequest();
|
||||||
assert(reqEvent);
|
assert(reqEvent);
|
||||||
const { request, respondWith } = reqEvent;
|
const { request, respondWith } = reqEvent;
|
||||||
|
@ -670,7 +682,6 @@ Deno.test(
|
||||||
await respondWith(
|
await respondWith(
|
||||||
new Response("", { headers: { "X-Header-Test": "Æ" } }),
|
new Response("", { headers: { "X-Header-Test": "Æ" } }),
|
||||||
);
|
);
|
||||||
httpConn.close();
|
|
||||||
})();
|
})();
|
||||||
|
|
||||||
const clientConn = await Deno.connect({ port: 4501 });
|
const clientConn = await Deno.connect({ port: 4501 });
|
||||||
|
@ -688,11 +699,14 @@ Deno.test(
|
||||||
let responseText = "";
|
let responseText = "";
|
||||||
const buf = new Uint8Array(1024);
|
const buf = new Uint8Array(1024);
|
||||||
let read;
|
let read;
|
||||||
|
|
||||||
while ((read = await clientConn.read(buf)) !== null) {
|
while ((read = await clientConn.read(buf)) !== null) {
|
||||||
|
httpConn!.close();
|
||||||
for (let i = 0; i < read; i++) {
|
for (let i = 0; i < read; i++) {
|
||||||
responseText += String.fromCharCode(buf[i]);
|
responseText += String.fromCharCode(buf[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
clientConn.close();
|
clientConn.close();
|
||||||
|
|
||||||
assert(/\r\n[Xx]-[Hh]eader-[Tt]est: Æ\r\n/.test(responseText));
|
assert(/\r\n[Xx]-[Hh]eader-[Tt]est: Æ\r\n/.test(responseText));
|
||||||
|
@ -704,18 +718,18 @@ Deno.test(
|
||||||
Deno.test(
|
Deno.test(
|
||||||
{ permissions: { net: true } },
|
{ permissions: { net: true } },
|
||||||
async function httpServerRequestWithoutPath() {
|
async function httpServerRequestWithoutPath() {
|
||||||
|
let httpConn: Deno.HttpConn;
|
||||||
|
const listener = Deno.listen({ port: 4501 });
|
||||||
const promise = (async () => {
|
const promise = (async () => {
|
||||||
const listener = Deno.listen({ port: 4501 });
|
|
||||||
const conn = await listener.accept();
|
const conn = await listener.accept();
|
||||||
listener.close();
|
listener.close();
|
||||||
const httpConn = Deno.serveHttp(conn);
|
httpConn = Deno.serveHttp(conn);
|
||||||
const reqEvent = await httpConn.nextRequest();
|
const reqEvent = await httpConn.nextRequest();
|
||||||
assert(reqEvent);
|
assert(reqEvent);
|
||||||
const { request, respondWith } = reqEvent;
|
const { request, respondWith } = reqEvent;
|
||||||
assertEquals(new URL(request.url).href, "http://127.0.0.1:4501/");
|
assertEquals(new URL(request.url).href, "http://127.0.0.1:4501/");
|
||||||
assertEquals(await request.text(), "");
|
assertEquals(await request.text(), "");
|
||||||
await respondWith(new Response());
|
await respondWith(new Response());
|
||||||
httpConn.close();
|
|
||||||
})();
|
})();
|
||||||
|
|
||||||
const clientConn = await Deno.connect({ port: 4501 });
|
const clientConn = await Deno.connect({ port: 4501 });
|
||||||
|
@ -744,6 +758,7 @@ Deno.test(
|
||||||
await writeRequest(clientConn);
|
await writeRequest(clientConn);
|
||||||
clientConn.close();
|
clientConn.close();
|
||||||
await promise;
|
await promise;
|
||||||
|
httpConn!.close();
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -868,11 +883,12 @@ Deno.test(function httpUpgradeWebSocketWithoutUpgradeHeader() {
|
||||||
Deno.test(
|
Deno.test(
|
||||||
{ permissions: { net: true } },
|
{ permissions: { net: true } },
|
||||||
async function httpCookieConcatenation() {
|
async function httpCookieConcatenation() {
|
||||||
|
let httpConn: Deno.HttpConn;
|
||||||
const promise = (async () => {
|
const promise = (async () => {
|
||||||
const listener = Deno.listen({ port: 4501 });
|
const listener = Deno.listen({ port: 4501 });
|
||||||
const conn = await listener.accept();
|
const conn = await listener.accept();
|
||||||
listener.close();
|
listener.close();
|
||||||
const httpConn = Deno.serveHttp(conn);
|
httpConn = Deno.serveHttp(conn);
|
||||||
const reqEvent = await httpConn.nextRequest();
|
const reqEvent = await httpConn.nextRequest();
|
||||||
assert(reqEvent);
|
assert(reqEvent);
|
||||||
const { request, respondWith } = reqEvent;
|
const { request, respondWith } = reqEvent;
|
||||||
|
@ -880,7 +896,6 @@ Deno.test(
|
||||||
assertEquals(await request.text(), "");
|
assertEquals(await request.text(), "");
|
||||||
assertEquals(request.headers.get("cookie"), "foo=bar; bar=foo");
|
assertEquals(request.headers.get("cookie"), "foo=bar; bar=foo");
|
||||||
await respondWith(new Response("ok"));
|
await respondWith(new Response("ok"));
|
||||||
httpConn.close();
|
|
||||||
})();
|
})();
|
||||||
|
|
||||||
const resp = await fetch("http://127.0.0.1:4501/", {
|
const resp = await fetch("http://127.0.0.1:4501/", {
|
||||||
|
@ -893,6 +908,7 @@ Deno.test(
|
||||||
const text = await resp.text();
|
const text = await resp.text();
|
||||||
assertEquals(text, "ok");
|
assertEquals(text, "ok");
|
||||||
await promise;
|
await promise;
|
||||||
|
httpConn!.close();
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -910,7 +926,7 @@ Deno.test({ permissions: { net: true } }, async function httpServerPanic() {
|
||||||
|
|
||||||
httpConn.nextRequest();
|
httpConn.nextRequest();
|
||||||
await client.write(encoder.encode("\r\n\r\n"));
|
await client.write(encoder.encode("\r\n\r\n"));
|
||||||
httpConn.close();
|
httpConn!.close();
|
||||||
|
|
||||||
client.close();
|
client.close();
|
||||||
listener.close();
|
listener.close();
|
||||||
|
@ -923,21 +939,23 @@ Deno.test(
|
||||||
const file = await Deno.open(tmpFile, { write: true, read: true });
|
const file = await Deno.open(tmpFile, { write: true, read: true });
|
||||||
await file.write(new Uint8Array(70 * 1024).fill(1)); // 70kb sent in 64kb + 6kb chunks
|
await file.write(new Uint8Array(70 * 1024).fill(1)); // 70kb sent in 64kb + 6kb chunks
|
||||||
file.close();
|
file.close();
|
||||||
|
|
||||||
|
let httpConn: Deno.HttpConn;
|
||||||
|
const listener = Deno.listen({ port: 4503 });
|
||||||
const promise = (async () => {
|
const promise = (async () => {
|
||||||
const listener = Deno.listen({ port: 4503 });
|
|
||||||
const conn = await listener.accept();
|
const conn = await listener.accept();
|
||||||
const httpConn = Deno.serveHttp(conn);
|
httpConn = Deno.serveHttp(conn);
|
||||||
const ev = await httpConn.nextRequest();
|
const ev = await httpConn.nextRequest();
|
||||||
const { respondWith } = ev!;
|
const { respondWith } = ev!;
|
||||||
const f = await Deno.open(tmpFile, { read: true });
|
const f = await Deno.open(tmpFile, { read: true });
|
||||||
await respondWith(new Response(f.readable, { status: 200 }));
|
await respondWith(new Response(f.readable, { status: 200 }));
|
||||||
httpConn.close();
|
|
||||||
listener.close();
|
|
||||||
})();
|
})();
|
||||||
const resp = await fetch("http://127.0.0.1:4503/");
|
const resp = await fetch("http://127.0.0.1:4503/");
|
||||||
const body = await resp.arrayBuffer();
|
const body = await resp.arrayBuffer();
|
||||||
assertEquals(body.byteLength, 70 * 1024);
|
assertEquals(body.byteLength, 70 * 1024);
|
||||||
await promise;
|
await promise;
|
||||||
|
httpConn!.close();
|
||||||
|
listener.close();
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -976,7 +994,7 @@ Deno.test(
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(didThrow);
|
assert(didThrow);
|
||||||
httpConn.close();
|
httpConn!.close();
|
||||||
listener.close();
|
listener.close();
|
||||||
client.close();
|
client.close();
|
||||||
},
|
},
|
||||||
|
@ -1018,7 +1036,7 @@ Deno.test(
|
||||||
|
|
||||||
await respondWith(res).catch((error: Error) => errors.push(error));
|
await respondWith(res).catch((error: Error) => errors.push(error));
|
||||||
|
|
||||||
httpConn.close();
|
httpConn!.close();
|
||||||
listener.close();
|
listener.close();
|
||||||
|
|
||||||
assert(errors.length >= 1);
|
assert(errors.length >= 1);
|
||||||
|
@ -1047,7 +1065,7 @@ Deno.test(
|
||||||
)),
|
)),
|
||||||
]);
|
]);
|
||||||
|
|
||||||
httpConn.close();
|
httpConn!.close();
|
||||||
listener.close();
|
listener.close();
|
||||||
clientConn.close();
|
clientConn.close();
|
||||||
},
|
},
|
||||||
|
@ -1133,10 +1151,11 @@ Deno.test(
|
||||||
const hostname = "localhost";
|
const hostname = "localhost";
|
||||||
const port = 4501;
|
const port = 4501;
|
||||||
|
|
||||||
|
let httpConn: Deno.HttpConn;
|
||||||
|
const listener = Deno.listen({ hostname, port });
|
||||||
async function server() {
|
async function server() {
|
||||||
const listener = Deno.listen({ hostname, port });
|
|
||||||
const tcpConn = await listener.accept();
|
const tcpConn = await listener.accept();
|
||||||
const httpConn = Deno.serveHttp(tcpConn);
|
httpConn = Deno.serveHttp(tcpConn);
|
||||||
const promises = new Array(10).fill(null).map(async (_, i) => {
|
const promises = new Array(10).fill(null).map(async (_, i) => {
|
||||||
const event = await httpConn.nextRequest();
|
const event = await httpConn.nextRequest();
|
||||||
assert(event);
|
assert(event);
|
||||||
|
@ -1146,8 +1165,6 @@ Deno.test(
|
||||||
await event.respondWith(response);
|
await event.respondWith(response);
|
||||||
});
|
});
|
||||||
await Promise.all(promises);
|
await Promise.all(promises);
|
||||||
httpConn.close();
|
|
||||||
listener.close();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async function client() {
|
async function client() {
|
||||||
|
@ -1159,6 +1176,8 @@ Deno.test(
|
||||||
}
|
}
|
||||||
|
|
||||||
await Promise.all([server(), delay(100).then(client)]);
|
await Promise.all([server(), delay(100).then(client)]);
|
||||||
|
httpConn!.close();
|
||||||
|
listener.close();
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -1213,16 +1232,15 @@ Deno.test(
|
||||||
const hostname = "localhost";
|
const hostname = "localhost";
|
||||||
const port = 4501;
|
const port = 4501;
|
||||||
|
|
||||||
|
let httpConn: Deno.HttpConn;
|
||||||
|
const listener = Deno.listen({ hostname, port });
|
||||||
async function server() {
|
async function server() {
|
||||||
const listener = Deno.listen({ hostname, port });
|
|
||||||
const tcpConn = await listener.accept();
|
const tcpConn = await listener.accept();
|
||||||
const httpConn = Deno.serveHttp(tcpConn);
|
httpConn = Deno.serveHttp(tcpConn);
|
||||||
const event = await httpConn.nextRequest() as Deno.RequestEvent;
|
const event = await httpConn.nextRequest() as Deno.RequestEvent;
|
||||||
assert(event.request.body);
|
assert(event.request.body);
|
||||||
const response = new Response();
|
const response = new Response();
|
||||||
await event.respondWith(response);
|
await event.respondWith(response);
|
||||||
httpConn.close();
|
|
||||||
listener.close();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async function client() {
|
async function client() {
|
||||||
|
@ -1237,17 +1255,20 @@ Deno.test(
|
||||||
}
|
}
|
||||||
|
|
||||||
await Promise.all([server(), client()]);
|
await Promise.all([server(), client()]);
|
||||||
|
httpConn!.close();
|
||||||
|
listener.close();
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
Deno.test(
|
Deno.test(
|
||||||
{ permissions: { net: true } },
|
{ permissions: { net: true } },
|
||||||
async function httpServerRespondNonAsciiUint8Array() {
|
async function httpServerRespondNonAsciiUint8Array() {
|
||||||
|
let httpConn: Deno.HttpConn;
|
||||||
|
const listener = Deno.listen({ port: 4501 });
|
||||||
const promise = (async () => {
|
const promise = (async () => {
|
||||||
const listener = Deno.listen({ port: 4501 });
|
|
||||||
const conn = await listener.accept();
|
const conn = await listener.accept();
|
||||||
listener.close();
|
listener.close();
|
||||||
const httpConn = Deno.serveHttp(conn);
|
httpConn = Deno.serveHttp(conn);
|
||||||
const e = await httpConn.nextRequest();
|
const e = await httpConn.nextRequest();
|
||||||
assert(e);
|
assert(e);
|
||||||
const { request, respondWith } = e;
|
const { request, respondWith } = e;
|
||||||
|
@ -1255,7 +1276,6 @@ Deno.test(
|
||||||
await respondWith(
|
await respondWith(
|
||||||
new Response(new Uint8Array([128]), {}),
|
new Response(new Uint8Array([128]), {}),
|
||||||
);
|
);
|
||||||
httpConn.close();
|
|
||||||
})();
|
})();
|
||||||
|
|
||||||
const resp = await fetch("http://localhost:4501/");
|
const resp = await fetch("http://localhost:4501/");
|
||||||
|
@ -1264,6 +1284,7 @@ Deno.test(
|
||||||
assertEquals(new Uint8Array(body), new Uint8Array([128]));
|
assertEquals(new Uint8Array(body), new Uint8Array([128]));
|
||||||
|
|
||||||
await promise;
|
await promise;
|
||||||
|
httpConn!.close();
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -1276,11 +1297,12 @@ Deno.test(
|
||||||
async function httpServerOnUnixSocket() {
|
async function httpServerOnUnixSocket() {
|
||||||
const filePath = Deno.makeTempFileSync();
|
const filePath = Deno.makeTempFileSync();
|
||||||
|
|
||||||
|
let httpConn: Deno.HttpConn;
|
||||||
const promise = (async () => {
|
const promise = (async () => {
|
||||||
const listener = Deno.listen({ path: filePath, transport: "unix" });
|
const listener = Deno.listen({ path: filePath, transport: "unix" });
|
||||||
const conn = await listener.accept();
|
const conn = await listener.accept();
|
||||||
listener.close();
|
listener.close();
|
||||||
const httpConn = Deno.serveHttp(conn);
|
httpConn = Deno.serveHttp(conn);
|
||||||
const reqEvent = await httpConn.nextRequest();
|
const reqEvent = await httpConn.nextRequest();
|
||||||
assert(reqEvent);
|
assert(reqEvent);
|
||||||
const { request, respondWith } = reqEvent;
|
const { request, respondWith } = reqEvent;
|
||||||
|
@ -1289,7 +1311,6 @@ Deno.test(
|
||||||
assertEquals(decodeURIComponent(url.host), filePath);
|
assertEquals(decodeURIComponent(url.host), filePath);
|
||||||
assertEquals(url.pathname, "/path/name");
|
assertEquals(url.pathname, "/path/name");
|
||||||
await respondWith(new Response("", { headers: {} }));
|
await respondWith(new Response("", { headers: {} }));
|
||||||
httpConn.close();
|
|
||||||
})();
|
})();
|
||||||
|
|
||||||
// fetch() does not supports unix domain sockets yet https://github.com/denoland/deno/issues/8821
|
// fetch() does not supports unix domain sockets yet https://github.com/denoland/deno/issues/8821
|
||||||
|
@ -1307,6 +1328,7 @@ Deno.test(
|
||||||
conn.close();
|
conn.close();
|
||||||
|
|
||||||
await promise;
|
await promise;
|
||||||
|
httpConn!.close();
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -1324,9 +1346,10 @@ Deno.test({
|
||||||
|
|
||||||
const data = { hello: "deno", now: "with", compressed: "body" };
|
const data = { hello: "deno", now: "with", compressed: "body" };
|
||||||
|
|
||||||
|
let httpConn: Deno.HttpConn;
|
||||||
async function server() {
|
async function server() {
|
||||||
const tcpConn = await listener.accept();
|
const tcpConn = await listener.accept();
|
||||||
const httpConn = Deno.serveHttp(tcpConn);
|
httpConn = Deno.serveHttp(tcpConn);
|
||||||
const e = await httpConn.nextRequest();
|
const e = await httpConn.nextRequest();
|
||||||
assert(e);
|
assert(e);
|
||||||
const { request, respondWith } = e;
|
const { request, respondWith } = e;
|
||||||
|
@ -1335,7 +1358,6 @@ Deno.test({
|
||||||
headers: { "content-type": "application/json" },
|
headers: { "content-type": "application/json" },
|
||||||
});
|
});
|
||||||
await respondWith(response);
|
await respondWith(response);
|
||||||
httpConn.close();
|
|
||||||
listener.close();
|
listener.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1361,6 +1383,7 @@ Deno.test({
|
||||||
}
|
}
|
||||||
|
|
||||||
await Promise.all([server(), client()]);
|
await Promise.all([server(), client()]);
|
||||||
|
httpConn!.close();
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -1374,9 +1397,10 @@ Deno.test({
|
||||||
|
|
||||||
const data = { hello: "deno", now: "with", compressed: "body" };
|
const data = { hello: "deno", now: "with", compressed: "body" };
|
||||||
|
|
||||||
|
let httpConn: Deno.HttpConn;
|
||||||
async function server() {
|
async function server() {
|
||||||
const tcpConn = await listener.accept();
|
const tcpConn = await listener.accept();
|
||||||
const httpConn = Deno.serveHttp(tcpConn);
|
httpConn = Deno.serveHttp(tcpConn);
|
||||||
const e = await httpConn.nextRequest();
|
const e = await httpConn.nextRequest();
|
||||||
assert(e);
|
assert(e);
|
||||||
const { request, respondWith } = e;
|
const { request, respondWith } = e;
|
||||||
|
@ -1385,7 +1409,6 @@ Deno.test({
|
||||||
headers: { "content-type": "application/json" },
|
headers: { "content-type": "application/json" },
|
||||||
});
|
});
|
||||||
await respondWith(response);
|
await respondWith(response);
|
||||||
httpConn.close();
|
|
||||||
listener.close();
|
listener.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1413,6 +1436,7 @@ Deno.test({
|
||||||
}
|
}
|
||||||
|
|
||||||
await Promise.all([server(), client()]);
|
await Promise.all([server(), client()]);
|
||||||
|
httpConn!.close();
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -1423,10 +1447,11 @@ Deno.test({
|
||||||
const hostname = "localhost";
|
const hostname = "localhost";
|
||||||
const port = 4501;
|
const port = 4501;
|
||||||
|
|
||||||
|
let httpConn: Deno.HttpConn;
|
||||||
async function server() {
|
async function server() {
|
||||||
const listener = Deno.listen({ hostname, port });
|
const listener = Deno.listen({ hostname, port });
|
||||||
const tcpConn = await listener.accept();
|
const tcpConn = await listener.accept();
|
||||||
const httpConn = Deno.serveHttp(tcpConn);
|
httpConn = Deno.serveHttp(tcpConn);
|
||||||
const e = await httpConn.nextRequest();
|
const e = await httpConn.nextRequest();
|
||||||
assert(e);
|
assert(e);
|
||||||
const { request, respondWith } = e;
|
const { request, respondWith } = e;
|
||||||
|
@ -1438,7 +1463,6 @@ Deno.test({
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
await respondWith(response);
|
await respondWith(response);
|
||||||
httpConn.close();
|
|
||||||
listener.close();
|
listener.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1464,6 +1488,7 @@ Deno.test({
|
||||||
}
|
}
|
||||||
|
|
||||||
await Promise.all([server(), client()]);
|
await Promise.all([server(), client()]);
|
||||||
|
httpConn!.close();
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -1474,10 +1499,11 @@ Deno.test({
|
||||||
const hostname = "localhost";
|
const hostname = "localhost";
|
||||||
const port = 4501;
|
const port = 4501;
|
||||||
|
|
||||||
|
let httpConn: Deno.HttpConn;
|
||||||
async function server() {
|
async function server() {
|
||||||
const listener = Deno.listen({ hostname, port });
|
const listener = Deno.listen({ hostname, port });
|
||||||
const tcpConn = await listener.accept();
|
const tcpConn = await listener.accept();
|
||||||
const httpConn = Deno.serveHttp(tcpConn);
|
httpConn = Deno.serveHttp(tcpConn);
|
||||||
const e = await httpConn.nextRequest();
|
const e = await httpConn.nextRequest();
|
||||||
assert(e);
|
assert(e);
|
||||||
const { request, respondWith } = e;
|
const { request, respondWith } = e;
|
||||||
|
@ -1492,7 +1518,6 @@ Deno.test({
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
await respondWith(response);
|
await respondWith(response);
|
||||||
httpConn.close();
|
|
||||||
listener.close();
|
listener.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1518,6 +1543,7 @@ Deno.test({
|
||||||
}
|
}
|
||||||
|
|
||||||
await Promise.all([server(), client()]);
|
await Promise.all([server(), client()]);
|
||||||
|
httpConn!.close();
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -1528,10 +1554,11 @@ Deno.test({
|
||||||
const hostname = "localhost";
|
const hostname = "localhost";
|
||||||
const port = 4501;
|
const port = 4501;
|
||||||
|
|
||||||
|
let httpConn: Deno.HttpConn;
|
||||||
async function server() {
|
async function server() {
|
||||||
const listener = Deno.listen({ hostname, port });
|
const listener = Deno.listen({ hostname, port });
|
||||||
const tcpConn = await listener.accept();
|
const tcpConn = await listener.accept();
|
||||||
const httpConn = Deno.serveHttp(tcpConn);
|
httpConn = Deno.serveHttp(tcpConn);
|
||||||
const e = await httpConn.nextRequest();
|
const e = await httpConn.nextRequest();
|
||||||
assert(e);
|
assert(e);
|
||||||
const { request, respondWith } = e;
|
const { request, respondWith } = e;
|
||||||
|
@ -1543,7 +1570,6 @@ Deno.test({
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
await respondWith(response);
|
await respondWith(response);
|
||||||
httpConn.close();
|
|
||||||
listener.close();
|
listener.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1569,6 +1595,7 @@ Deno.test({
|
||||||
}
|
}
|
||||||
|
|
||||||
await Promise.all([server(), client()]);
|
await Promise.all([server(), client()]);
|
||||||
|
httpConn!.close();
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -1579,10 +1606,11 @@ Deno.test({
|
||||||
const hostname = "localhost";
|
const hostname = "localhost";
|
||||||
const port = 4501;
|
const port = 4501;
|
||||||
|
|
||||||
|
let httpConn: Deno.HttpConn;
|
||||||
async function server() {
|
async function server() {
|
||||||
const listener = Deno.listen({ hostname, port });
|
const listener = Deno.listen({ hostname, port });
|
||||||
const tcpConn = await listener.accept();
|
const tcpConn = await listener.accept();
|
||||||
const httpConn = Deno.serveHttp(tcpConn);
|
httpConn = Deno.serveHttp(tcpConn);
|
||||||
const e = await httpConn.nextRequest();
|
const e = await httpConn.nextRequest();
|
||||||
assert(e);
|
assert(e);
|
||||||
const { request, respondWith } = e;
|
const { request, respondWith } = e;
|
||||||
|
@ -1597,7 +1625,6 @@ Deno.test({
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
await respondWith(response);
|
await respondWith(response);
|
||||||
httpConn.close();
|
|
||||||
listener.close();
|
listener.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1627,6 +1654,7 @@ Deno.test({
|
||||||
}
|
}
|
||||||
|
|
||||||
await Promise.all([server(), client()]);
|
await Promise.all([server(), client()]);
|
||||||
|
httpConn!.close();
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -1637,10 +1665,11 @@ Deno.test({
|
||||||
const hostname = "localhost";
|
const hostname = "localhost";
|
||||||
const port = 4501;
|
const port = 4501;
|
||||||
|
|
||||||
|
let httpConn: Deno.HttpConn;
|
||||||
async function server() {
|
async function server() {
|
||||||
const listener = Deno.listen({ hostname, port });
|
const listener = Deno.listen({ hostname, port });
|
||||||
const tcpConn = await listener.accept();
|
const tcpConn = await listener.accept();
|
||||||
const httpConn = Deno.serveHttp(tcpConn);
|
httpConn = Deno.serveHttp(tcpConn);
|
||||||
const e = await httpConn.nextRequest();
|
const e = await httpConn.nextRequest();
|
||||||
assert(e);
|
assert(e);
|
||||||
const { request, respondWith } = e;
|
const { request, respondWith } = e;
|
||||||
|
@ -1655,7 +1684,6 @@ Deno.test({
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
await respondWith(response);
|
await respondWith(response);
|
||||||
httpConn.close();
|
|
||||||
listener.close();
|
listener.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1684,6 +1712,7 @@ Deno.test({
|
||||||
}
|
}
|
||||||
|
|
||||||
await Promise.all([server(), client()]);
|
await Promise.all([server(), client()]);
|
||||||
|
httpConn!.close();
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -1694,10 +1723,11 @@ Deno.test({
|
||||||
const hostname = "localhost";
|
const hostname = "localhost";
|
||||||
const port = 4501;
|
const port = 4501;
|
||||||
|
|
||||||
|
let httpConn: Deno.HttpConn;
|
||||||
async function server() {
|
async function server() {
|
||||||
const listener = Deno.listen({ hostname, port });
|
const listener = Deno.listen({ hostname, port });
|
||||||
const tcpConn = await listener.accept();
|
const tcpConn = await listener.accept();
|
||||||
const httpConn = Deno.serveHttp(tcpConn);
|
httpConn = Deno.serveHttp(tcpConn);
|
||||||
const e = await httpConn.nextRequest();
|
const e = await httpConn.nextRequest();
|
||||||
assert(e);
|
assert(e);
|
||||||
const { request, respondWith } = e;
|
const { request, respondWith } = e;
|
||||||
|
@ -1712,7 +1742,6 @@ Deno.test({
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
await respondWith(response);
|
await respondWith(response);
|
||||||
httpConn.close();
|
|
||||||
listener.close();
|
listener.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1738,6 +1767,7 @@ Deno.test({
|
||||||
}
|
}
|
||||||
|
|
||||||
await Promise.all([server(), client()]);
|
await Promise.all([server(), client()]);
|
||||||
|
httpConn!.close();
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -1748,10 +1778,11 @@ Deno.test({
|
||||||
const hostname = "localhost";
|
const hostname = "localhost";
|
||||||
const port = 4501;
|
const port = 4501;
|
||||||
|
|
||||||
|
let httpConn: Deno.HttpConn;
|
||||||
async function server() {
|
async function server() {
|
||||||
const listener = Deno.listen({ hostname, port });
|
const listener = Deno.listen({ hostname, port });
|
||||||
const tcpConn = await listener.accept();
|
const tcpConn = await listener.accept();
|
||||||
const httpConn = Deno.serveHttp(tcpConn);
|
httpConn = Deno.serveHttp(tcpConn);
|
||||||
const e = await httpConn.nextRequest();
|
const e = await httpConn.nextRequest();
|
||||||
assert(e);
|
assert(e);
|
||||||
const { request, respondWith } = e;
|
const { request, respondWith } = e;
|
||||||
|
@ -1766,7 +1797,6 @@ Deno.test({
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
await respondWith(response);
|
await respondWith(response);
|
||||||
httpConn.close();
|
|
||||||
listener.close();
|
listener.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1792,6 +1822,7 @@ Deno.test({
|
||||||
}
|
}
|
||||||
|
|
||||||
await Promise.all([server(), client()]);
|
await Promise.all([server(), client()]);
|
||||||
|
httpConn!.close();
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -1807,9 +1838,10 @@ Deno.test({
|
||||||
|
|
||||||
const data = { hello: "deno", now: "with", compressed: "body" };
|
const data = { hello: "deno", now: "with", compressed: "body" };
|
||||||
|
|
||||||
|
let httpConn: Deno.HttpConn;
|
||||||
async function server() {
|
async function server() {
|
||||||
const tcpConn = await listener.accept();
|
const tcpConn = await listener.accept();
|
||||||
const httpConn = Deno.serveHttp(tcpConn);
|
httpConn = Deno.serveHttp(tcpConn);
|
||||||
const e = await httpConn.nextRequest();
|
const e = await httpConn.nextRequest();
|
||||||
assert(e);
|
assert(e);
|
||||||
const { request, respondWith } = e;
|
const { request, respondWith } = e;
|
||||||
|
@ -1825,7 +1857,6 @@ Deno.test({
|
||||||
{ headers: { "content-type": "application/json" } },
|
{ headers: { "content-type": "application/json" } },
|
||||||
);
|
);
|
||||||
await respondWith(response);
|
await respondWith(response);
|
||||||
httpConn.close();
|
|
||||||
listener.close();
|
listener.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1852,6 +1883,7 @@ Deno.test({
|
||||||
}
|
}
|
||||||
|
|
||||||
await Promise.all([server(), client()]);
|
await Promise.all([server(), client()]);
|
||||||
|
httpConn!.close();
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -1867,9 +1899,10 @@ Deno.test({
|
||||||
|
|
||||||
const data = { hello: "deno", now: "with", compressed: "body" };
|
const data = { hello: "deno", now: "with", compressed: "body" };
|
||||||
|
|
||||||
|
let httpConn: Deno.HttpConn;
|
||||||
async function server() {
|
async function server() {
|
||||||
const tcpConn = await listener.accept();
|
const tcpConn = await listener.accept();
|
||||||
const httpConn = Deno.serveHttp(tcpConn);
|
httpConn = Deno.serveHttp(tcpConn);
|
||||||
const e = await httpConn.nextRequest();
|
const e = await httpConn.nextRequest();
|
||||||
assert(e);
|
assert(e);
|
||||||
const { request, respondWith } = e;
|
const { request, respondWith } = e;
|
||||||
|
@ -1885,7 +1918,6 @@ Deno.test({
|
||||||
{ headers: { "content-type": "application/json" } },
|
{ headers: { "content-type": "application/json" } },
|
||||||
);
|
);
|
||||||
await respondWith(response);
|
await respondWith(response);
|
||||||
httpConn.close();
|
|
||||||
listener.close();
|
listener.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1913,6 +1945,7 @@ Deno.test({
|
||||||
}
|
}
|
||||||
|
|
||||||
await Promise.all([server(), client()]);
|
await Promise.all([server(), client()]);
|
||||||
|
httpConn!.close();
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -1924,10 +1957,11 @@ Deno.test({
|
||||||
const port = 4501;
|
const port = 4501;
|
||||||
let contentLength: string;
|
let contentLength: string;
|
||||||
|
|
||||||
|
let httpConn: Deno.HttpConn;
|
||||||
async function server() {
|
async function server() {
|
||||||
const listener = Deno.listen({ hostname, port });
|
const listener = Deno.listen({ hostname, port });
|
||||||
const tcpConn = await listener.accept();
|
const tcpConn = await listener.accept();
|
||||||
const httpConn = Deno.serveHttp(tcpConn);
|
httpConn = Deno.serveHttp(tcpConn);
|
||||||
const e = await httpConn.nextRequest();
|
const e = await httpConn.nextRequest();
|
||||||
assert(e);
|
assert(e);
|
||||||
const { request, respondWith } = e;
|
const { request, respondWith } = e;
|
||||||
|
@ -1948,7 +1982,6 @@ Deno.test({
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
await respondWith(response);
|
await respondWith(response);
|
||||||
httpConn.close();
|
|
||||||
listener.close();
|
listener.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1977,6 +2010,7 @@ Deno.test({
|
||||||
}
|
}
|
||||||
|
|
||||||
await Promise.all([server(), client()]);
|
await Promise.all([server(), client()]);
|
||||||
|
httpConn!.close();
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -1988,10 +2022,11 @@ Deno.test({
|
||||||
const port = 4501;
|
const port = 4501;
|
||||||
let contentLength: string;
|
let contentLength: string;
|
||||||
|
|
||||||
|
let httpConn: Deno.HttpConn;
|
||||||
async function server() {
|
async function server() {
|
||||||
const listener = Deno.listen({ hostname, port });
|
const listener = Deno.listen({ hostname, port });
|
||||||
const tcpConn = await listener.accept();
|
const tcpConn = await listener.accept();
|
||||||
const httpConn = Deno.serveHttp(tcpConn);
|
httpConn = Deno.serveHttp(tcpConn);
|
||||||
const e = await httpConn.nextRequest();
|
const e = await httpConn.nextRequest();
|
||||||
assert(e);
|
assert(e);
|
||||||
const { request, respondWith } = e;
|
const { request, respondWith } = e;
|
||||||
|
@ -2007,7 +2042,6 @@ Deno.test({
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
await respondWith(response);
|
await respondWith(response);
|
||||||
httpConn.close();
|
|
||||||
listener.close();
|
listener.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2037,6 +2071,7 @@ Deno.test({
|
||||||
}
|
}
|
||||||
|
|
||||||
await Promise.all([server(), client()]);
|
await Promise.all([server(), client()]);
|
||||||
|
httpConn!.close();
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -2048,10 +2083,11 @@ Deno.test({
|
||||||
const port = 4501;
|
const port = 4501;
|
||||||
let contentLength: string;
|
let contentLength: string;
|
||||||
|
|
||||||
|
let httpConn: Deno.HttpConn;
|
||||||
async function server() {
|
async function server() {
|
||||||
const listener = Deno.listen({ hostname, port });
|
const listener = Deno.listen({ hostname, port });
|
||||||
const tcpConn = await listener.accept();
|
const tcpConn = await listener.accept();
|
||||||
const httpConn = Deno.serveHttp(tcpConn);
|
httpConn = Deno.serveHttp(tcpConn);
|
||||||
const e = await httpConn.nextRequest();
|
const e = await httpConn.nextRequest();
|
||||||
assert(e);
|
assert(e);
|
||||||
const { request, respondWith } = e;
|
const { request, respondWith } = e;
|
||||||
|
@ -2068,7 +2104,6 @@ Deno.test({
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
await respondWith(response);
|
await respondWith(response);
|
||||||
httpConn.close();
|
|
||||||
listener.close();
|
listener.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2095,6 +2130,7 @@ Deno.test({
|
||||||
}
|
}
|
||||||
|
|
||||||
await Promise.all([server(), client()]);
|
await Promise.all([server(), client()]);
|
||||||
|
httpConn!.close();
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -2248,7 +2284,7 @@ Deno.test("upgradeHttp unix", {
|
||||||
const resp = new Response(null, { status: 101 });
|
const resp = new Response(null, { status: 101 });
|
||||||
await respondWith(resp);
|
await respondWith(resp);
|
||||||
await promise;
|
await promise;
|
||||||
httpConn.close();
|
httpConn!.close();
|
||||||
})();
|
})();
|
||||||
|
|
||||||
await Promise.all([server, client()]);
|
await Promise.all([server, client()]);
|
||||||
|
|
|
@ -160,10 +160,11 @@
|
||||||
|
|
||||||
function opAsync(opName, ...args) {
|
function opAsync(opName, ...args) {
|
||||||
const promiseId = nextPromiseId++;
|
const promiseId = nextPromiseId++;
|
||||||
|
let p = setPromise(promiseId);
|
||||||
const maybeError = ops[opName](promiseId, ...args);
|
const maybeError = ops[opName](promiseId, ...args);
|
||||||
// Handle sync error (e.g: error parsing args)
|
// Handle sync error (e.g: error parsing args)
|
||||||
if (maybeError) return unwrapOpResult(maybeError);
|
if (maybeError) return unwrapOpResult(maybeError);
|
||||||
let p = PromisePrototypeThen(setPromise(promiseId), unwrapOpResult);
|
p = PromisePrototypeThen(p, unwrapOpResult);
|
||||||
if (opCallTracingEnabled) {
|
if (opCallTracingEnabled) {
|
||||||
// Capture a stack trace by creating a new `Error` object. We remove the
|
// Capture a stack trace by creating a new `Error` object. We remove the
|
||||||
// first 6 characters (the `Error\n` prefix) to get just the stack trace.
|
// first 6 characters (the `Error\n` prefix) to get just the stack trace.
|
||||||
|
|
14
core/ops.rs
14
core/ops.rs
|
@ -28,17 +28,25 @@ use std::task::Poll;
|
||||||
/// turn of the event loop, which is too late for certain ops.
|
/// turn of the event loop, which is too late for certain ops.
|
||||||
pub struct OpCall<T>(MaybeDone<Pin<Box<dyn Future<Output = T>>>>);
|
pub struct OpCall<T>(MaybeDone<Pin<Box<dyn Future<Output = T>>>>);
|
||||||
|
|
||||||
|
pub enum EagerPollResult<T> {
|
||||||
|
Ready(T),
|
||||||
|
Pending(OpCall<T>),
|
||||||
|
}
|
||||||
|
|
||||||
impl<T> OpCall<T> {
|
impl<T> OpCall<T> {
|
||||||
/// Wraps a future, and polls the inner future immediately.
|
/// Wraps a future, and polls the inner future immediately.
|
||||||
/// This should be the default choice for ops.
|
/// This should be the default choice for ops.
|
||||||
pub fn eager(fut: impl Future<Output = T> + 'static) -> Self {
|
pub fn eager(fut: impl Future<Output = T> + 'static) -> EagerPollResult<T> {
|
||||||
let boxed = Box::pin(fut) as Pin<Box<dyn Future<Output = T>>>;
|
let boxed = Box::pin(fut) as Pin<Box<dyn Future<Output = T>>>;
|
||||||
let mut inner = maybe_done(boxed);
|
let mut inner = maybe_done(boxed);
|
||||||
let waker = noop_waker();
|
let waker = noop_waker();
|
||||||
let mut cx = Context::from_waker(&waker);
|
let mut cx = Context::from_waker(&waker);
|
||||||
let mut pinned = Pin::new(&mut inner);
|
let mut pinned = Pin::new(&mut inner);
|
||||||
let _ = pinned.as_mut().poll(&mut cx);
|
let poll = pinned.as_mut().poll(&mut cx);
|
||||||
Self(inner)
|
match poll {
|
||||||
|
Poll::Ready(_) => EagerPollResult::Ready(pinned.take_output().unwrap()),
|
||||||
|
_ => EagerPollResult::Pending(Self(inner)),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Wraps a future; the inner future is polled the usual way (lazily).
|
/// Wraps a future; the inner future is polled the usual way (lazily).
|
||||||
|
|
122
core/runtime.rs
122
core/runtime.rs
|
@ -2145,14 +2145,54 @@ impl JsRealm {
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn queue_async_op(
|
pub fn queue_async_op(
|
||||||
scope: &v8::Isolate,
|
state: Rc<RefCell<OpState>>,
|
||||||
|
scope: &mut v8::HandleScope,
|
||||||
|
deferred: bool,
|
||||||
op: impl Future<Output = (v8::Global<v8::Context>, PromiseId, OpId, OpResult)>
|
op: impl Future<Output = (v8::Global<v8::Context>, PromiseId, OpId, OpResult)>
|
||||||
+ 'static,
|
+ 'static,
|
||||||
) {
|
) {
|
||||||
let state_rc = JsRuntime::state(scope);
|
match OpCall::eager(op) {
|
||||||
let mut state = state_rc.borrow_mut();
|
// This calls promise.resolve() before the control goes back to userland JS. It works something
|
||||||
state.pending_ops.push(OpCall::eager(op));
|
// along the lines of:
|
||||||
state.have_unpolled_ops = true;
|
//
|
||||||
|
// function opresolve(promiseId, ...) {
|
||||||
|
// getPromise(promiseId).resolve(...);
|
||||||
|
// }
|
||||||
|
// const p = setPromise();
|
||||||
|
// op.op_async(promiseId, ...); // Calls `opresolve`
|
||||||
|
// return p;
|
||||||
|
EagerPollResult::Ready((context, promise_id, op_id, mut resp))
|
||||||
|
if !deferred =>
|
||||||
|
{
|
||||||
|
let args = &[
|
||||||
|
v8::Integer::new(scope, promise_id).into(),
|
||||||
|
resp.to_v8(scope).unwrap(),
|
||||||
|
];
|
||||||
|
|
||||||
|
let realm = JsRealm::new(context);
|
||||||
|
let js_recv_cb_handle =
|
||||||
|
realm.state(scope).borrow().js_recv_cb.clone().unwrap();
|
||||||
|
state.borrow().tracker.track_async_completed(op_id);
|
||||||
|
|
||||||
|
let tc_scope = &mut v8::TryCatch::new(scope);
|
||||||
|
let js_recv_cb = js_recv_cb_handle.open(tc_scope);
|
||||||
|
let this = v8::undefined(tc_scope).into();
|
||||||
|
js_recv_cb.call(tc_scope, this, args);
|
||||||
|
}
|
||||||
|
EagerPollResult::Ready(op) => {
|
||||||
|
let ready = OpCall::ready(op);
|
||||||
|
let state_rc = JsRuntime::state(scope);
|
||||||
|
let mut state = state_rc.borrow_mut();
|
||||||
|
state.pending_ops.push(ready);
|
||||||
|
state.have_unpolled_ops = true;
|
||||||
|
}
|
||||||
|
EagerPollResult::Pending(op) => {
|
||||||
|
let state_rc = JsRuntime::state(scope);
|
||||||
|
let mut state = state_rc.borrow_mut();
|
||||||
|
state.pending_ops.push(op);
|
||||||
|
state.have_unpolled_ops = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
@ -2194,7 +2234,7 @@ pub mod tests {
|
||||||
dispatch_count: Arc<AtomicUsize>,
|
dispatch_count: Arc<AtomicUsize>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[op]
|
#[op(deferred)]
|
||||||
async fn op_test(
|
async fn op_test(
|
||||||
rc_op_state: Rc<RefCell<OpState>>,
|
rc_op_state: Rc<RefCell<OpState>>,
|
||||||
control: u8,
|
control: u8,
|
||||||
|
@ -2255,41 +2295,6 @@ pub mod tests {
|
||||||
(runtime, dispatch_count)
|
(runtime, dispatch_count)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_dispatch() {
|
|
||||||
let (mut runtime, dispatch_count) = setup(Mode::Async);
|
|
||||||
runtime
|
|
||||||
.execute_script(
|
|
||||||
"filename.js",
|
|
||||||
r#"
|
|
||||||
let control = 42;
|
|
||||||
Deno.core.opAsync("op_test", control);
|
|
||||||
async function main() {
|
|
||||||
Deno.core.opAsync("op_test", control);
|
|
||||||
}
|
|
||||||
main();
|
|
||||||
"#,
|
|
||||||
)
|
|
||||||
.unwrap();
|
|
||||||
assert_eq!(dispatch_count.load(Ordering::Relaxed), 2);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_op_async_promise_id() {
|
|
||||||
let (mut runtime, _dispatch_count) = setup(Mode::Async);
|
|
||||||
runtime
|
|
||||||
.execute_script(
|
|
||||||
"filename.js",
|
|
||||||
r#"
|
|
||||||
const p = Deno.core.opAsync("op_test", 42);
|
|
||||||
if (p[Symbol.for("Deno.core.internalPromiseId")] == undefined) {
|
|
||||||
throw new Error("missing id on returned promise");
|
|
||||||
}
|
|
||||||
"#,
|
|
||||||
)
|
|
||||||
.unwrap();
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_ref_unref_ops() {
|
fn test_ref_unref_ops() {
|
||||||
let (mut runtime, _dispatch_count) = setup(Mode::Async);
|
let (mut runtime, _dispatch_count) = setup(Mode::Async);
|
||||||
|
@ -2344,6 +2349,41 @@ pub mod tests {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_dispatch() {
|
||||||
|
let (mut runtime, dispatch_count) = setup(Mode::Async);
|
||||||
|
runtime
|
||||||
|
.execute_script(
|
||||||
|
"filename.js",
|
||||||
|
r#"
|
||||||
|
let control = 42;
|
||||||
|
Deno.core.opAsync("op_test", control);
|
||||||
|
async function main() {
|
||||||
|
Deno.core.opAsync("op_test", control);
|
||||||
|
}
|
||||||
|
main();
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
assert_eq!(dispatch_count.load(Ordering::Relaxed), 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_op_async_promise_id() {
|
||||||
|
let (mut runtime, _dispatch_count) = setup(Mode::Async);
|
||||||
|
runtime
|
||||||
|
.execute_script(
|
||||||
|
"filename.js",
|
||||||
|
r#"
|
||||||
|
const p = Deno.core.opAsync("op_test", 42);
|
||||||
|
if (p[Symbol.for("Deno.core.internalPromiseId")] == undefined) {
|
||||||
|
throw new Error("missing id on returned promise");
|
||||||
|
}
|
||||||
|
"#,
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_dispatch_no_zero_copy_buf() {
|
fn test_dispatch_no_zero_copy_buf() {
|
||||||
let (mut runtime, dispatch_count) = setup(Mode::AsyncZeroCopy(false));
|
let (mut runtime, dispatch_count) = setup(Mode::AsyncZeroCopy(false));
|
||||||
|
|
|
@ -93,7 +93,7 @@ pub fn op_timer_handle(state: &mut OpState) -> ResourceId {
|
||||||
|
|
||||||
/// Waits asynchronously until either `millis` milliseconds have passed or the
|
/// Waits asynchronously until either `millis` milliseconds have passed or the
|
||||||
/// [`TimerHandle`] resource given by `rid` has been canceled.
|
/// [`TimerHandle`] resource given by `rid` has been canceled.
|
||||||
#[op]
|
#[op(deferred)]
|
||||||
pub async fn op_sleep(
|
pub async fn op_sleep(
|
||||||
state: Rc<RefCell<OpState>>,
|
state: Rc<RefCell<OpState>>,
|
||||||
millis: u64,
|
millis: u64,
|
||||||
|
|
|
@ -420,7 +420,7 @@ pub async fn op_ws_send(
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[op]
|
#[op(deferred)]
|
||||||
pub async fn op_ws_close(
|
pub async fn op_ws_close(
|
||||||
state: Rc<RefCell<OpState>>,
|
state: Rc<RefCell<OpState>>,
|
||||||
rid: ResourceId,
|
rid: ResourceId,
|
||||||
|
|
10
ops/lib.rs
10
ops/lib.rs
|
@ -51,6 +51,7 @@ struct MacroArgs {
|
||||||
is_unstable: bool,
|
is_unstable: bool,
|
||||||
is_v8: bool,
|
is_v8: bool,
|
||||||
must_be_fast: bool,
|
must_be_fast: bool,
|
||||||
|
deferred: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl syn::parse::Parse for MacroArgs {
|
impl syn::parse::Parse for MacroArgs {
|
||||||
|
@ -62,7 +63,7 @@ impl syn::parse::Parse for MacroArgs {
|
||||||
let vars: Vec<_> = vars.iter().map(Ident::to_string).collect();
|
let vars: Vec<_> = vars.iter().map(Ident::to_string).collect();
|
||||||
let vars: Vec<_> = vars.iter().map(String::as_str).collect();
|
let vars: Vec<_> = vars.iter().map(String::as_str).collect();
|
||||||
for var in vars.iter() {
|
for var in vars.iter() {
|
||||||
if !["unstable", "v8", "fast"].contains(var) {
|
if !["unstable", "v8", "fast", "deferred"].contains(var) {
|
||||||
return Err(syn::Error::new(
|
return Err(syn::Error::new(
|
||||||
input.span(),
|
input.span(),
|
||||||
"Ops expect #[op] or #[op(unstable)]",
|
"Ops expect #[op] or #[op(unstable)]",
|
||||||
|
@ -73,6 +74,7 @@ impl syn::parse::Parse for MacroArgs {
|
||||||
is_unstable: vars.contains(&"unstable"),
|
is_unstable: vars.contains(&"unstable"),
|
||||||
is_v8: vars.contains(&"v8"),
|
is_v8: vars.contains(&"v8"),
|
||||||
must_be_fast: vars.contains(&"fast"),
|
must_be_fast: vars.contains(&"fast"),
|
||||||
|
deferred: vars.contains(&"deferred"),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -84,6 +86,7 @@ pub fn op(attr: TokenStream, item: TokenStream) -> TokenStream {
|
||||||
is_unstable,
|
is_unstable,
|
||||||
is_v8,
|
is_v8,
|
||||||
must_be_fast,
|
must_be_fast,
|
||||||
|
deferred,
|
||||||
} = margs;
|
} = margs;
|
||||||
let func = syn::parse::<syn::ItemFn>(item).expect("expected a function");
|
let func = syn::parse::<syn::ItemFn>(item).expect("expected a function");
|
||||||
let name = &func.sig.ident;
|
let name = &func.sig.ident;
|
||||||
|
@ -110,7 +113,7 @@ pub fn op(attr: TokenStream, item: TokenStream) -> TokenStream {
|
||||||
let asyncness = func.sig.asyncness.is_some();
|
let asyncness = func.sig.asyncness.is_some();
|
||||||
let is_async = asyncness || is_future(&func.sig.output);
|
let is_async = asyncness || is_future(&func.sig.output);
|
||||||
let v8_body = if is_async {
|
let v8_body = if is_async {
|
||||||
codegen_v8_async(&core, &func, margs, asyncness)
|
codegen_v8_async(&core, &func, margs, asyncness, deferred)
|
||||||
} else {
|
} else {
|
||||||
codegen_v8_sync(&core, &func, margs)
|
codegen_v8_sync(&core, &func, margs)
|
||||||
};
|
};
|
||||||
|
@ -173,6 +176,7 @@ fn codegen_v8_async(
|
||||||
f: &syn::ItemFn,
|
f: &syn::ItemFn,
|
||||||
margs: MacroArgs,
|
margs: MacroArgs,
|
||||||
asyncness: bool,
|
asyncness: bool,
|
||||||
|
deferred: bool,
|
||||||
) -> TokenStream2 {
|
) -> TokenStream2 {
|
||||||
let MacroArgs { is_v8, .. } = margs;
|
let MacroArgs { is_v8, .. } = margs;
|
||||||
let special_args = f
|
let special_args = f
|
||||||
|
@ -256,7 +260,7 @@ fn codegen_v8_async(
|
||||||
};
|
};
|
||||||
|
|
||||||
#pre_result
|
#pre_result
|
||||||
#core::_ops::queue_async_op(scope, async move {
|
#core::_ops::queue_async_op(state, scope, #deferred, async move {
|
||||||
let result = #result_fut
|
let result = #result_fut
|
||||||
#result_wrapper
|
#result_wrapper
|
||||||
(context, promise_id, op_id, #core::_ops::to_op_result(get_class, result))
|
(context, promise_id, op_id, #core::_ops::to_op_result(get_class, result))
|
||||||
|
|
|
@ -147,6 +147,7 @@
|
||||||
// cleared can actually be removed from resource table, otherwise
|
// cleared can actually be removed from resource table, otherwise
|
||||||
// false positives may occur (https://github.com/denoland/deno/issues/4591)
|
// false positives may occur (https://github.com/denoland/deno/issues/4591)
|
||||||
await opSanitizerDelay();
|
await opSanitizerDelay();
|
||||||
|
await opSanitizerDelay();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (shouldSkipSanitizers(desc)) return;
|
if (shouldSkipSanitizers(desc)) return;
|
||||||
|
|
|
@ -39,7 +39,7 @@ fn op_worker_post_message(
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[op]
|
#[op(deferred)]
|
||||||
async fn op_worker_recv_message(
|
async fn op_worker_recv_message(
|
||||||
state: Rc<RefCell<OpState>>,
|
state: Rc<RefCell<OpState>>,
|
||||||
) -> Result<Option<JsMessageData>, AnyError> {
|
) -> Result<Option<JsMessageData>, AnyError> {
|
||||||
|
|
Loading…
Reference in a new issue