mirror of
https://github.com/denoland/deno.git
synced 2024-11-21 15:04:11 -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);
|
||||
assert!(!output.status.success());
|
||||
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());
|
||||
}
|
||||
|
||||
|
@ -950,7 +950,7 @@ async fn test_resolve_dns() {
|
|||
let out = String::from_utf8_lossy(&output.stdout);
|
||||
assert!(!output.status.success());
|
||||
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());
|
||||
}
|
||||
|
||||
|
|
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]
|
||||
|
|
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 [WILDCARD]/wasm_unreachable.js:[WILDCARD]
|
||||
|
|
|
@ -1202,47 +1202,44 @@ Deno.test({}, function fetchWritableRespProps() {
|
|||
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(
|
||||
{ permissions: { net: true } },
|
||||
async function fetchFilterOutCustomHostHeader(): Promise<
|
||||
void
|
||||
> {
|
||||
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}/`, {
|
||||
headers: { "Host": "example.com" },
|
||||
});
|
||||
await response.text();
|
||||
listener.close();
|
||||
httpConn!.close();
|
||||
|
||||
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() {
|
||||
let httpConn: Deno.HttpConn;
|
||||
const promise = (async () => {
|
||||
const listener = Deno.listen({ port: 4501 });
|
||||
const conn = await listener.accept();
|
||||
listener.close();
|
||||
const httpConn = Deno.serveHttp(conn);
|
||||
httpConn = Deno.serveHttp(conn);
|
||||
const reqEvent = await httpConn.nextRequest();
|
||||
assert(reqEvent);
|
||||
const { request, respondWith } = reqEvent;
|
||||
|
@ -58,7 +59,6 @@ Deno.test({ permissions: { net: true } }, async function httpServerBasic() {
|
|||
await respondWith(
|
||||
new Response("Hello World", { headers: { "foo": "bar" } }),
|
||||
);
|
||||
httpConn.close();
|
||||
})();
|
||||
|
||||
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();
|
||||
assertEquals(cloneText, "Hello World");
|
||||
await promise;
|
||||
|
||||
httpConn!.close();
|
||||
});
|
||||
|
||||
// https://github.com/denoland/deno/issues/15107
|
||||
|
@ -88,7 +90,7 @@ Deno.test(
|
|||
const { request } = e;
|
||||
request.text();
|
||||
headers = request.headers;
|
||||
httpConn.close();
|
||||
httpConn!.close();
|
||||
})();
|
||||
|
||||
const conn = await Deno.connect({ port: 2333 });
|
||||
|
@ -120,7 +122,7 @@ Deno.test(
|
|||
await respondWith(new Response("Hello World")); // Closes request
|
||||
|
||||
assertThrows(() => request.headers, TypeError, "request closed");
|
||||
httpConn.close();
|
||||
httpConn!.close();
|
||||
})();
|
||||
|
||||
const conn = await Deno.connect({ port: 2334 });
|
||||
|
@ -138,17 +140,17 @@ Deno.test(
|
|||
Deno.test(
|
||||
{ permissions: { net: true } },
|
||||
async function httpServerGetRequestBody() {
|
||||
let httpConn: Deno.HttpConn;
|
||||
const promise = (async () => {
|
||||
const listener = Deno.listen({ port: 4501 });
|
||||
const conn = await listener.accept();
|
||||
listener.close();
|
||||
const httpConn = Deno.serveHttp(conn);
|
||||
httpConn = Deno.serveHttp(conn);
|
||||
const e = await httpConn.nextRequest();
|
||||
assert(e);
|
||||
const { request, respondWith } = e;
|
||||
assertEquals(request.body, null);
|
||||
await respondWith(new Response("", { headers: {} }));
|
||||
httpConn.close();
|
||||
})();
|
||||
|
||||
const conn = await Deno.connect({ port: 4501 });
|
||||
|
@ -166,6 +168,7 @@ Deno.test(
|
|||
conn.close();
|
||||
|
||||
await promise;
|
||||
httpConn!.close();
|
||||
},
|
||||
);
|
||||
|
||||
|
@ -178,23 +181,24 @@ Deno.test(
|
|||
writer.write(new TextEncoder().encode("world"));
|
||||
writer.close();
|
||||
|
||||
let httpConn: Deno.HttpConn;
|
||||
const listener = Deno.listen({ port: 4501 });
|
||||
const promise = (async () => {
|
||||
const listener = Deno.listen({ port: 4501 });
|
||||
const conn = await listener.accept();
|
||||
const httpConn = Deno.serveHttp(conn);
|
||||
httpConn = Deno.serveHttp(conn);
|
||||
const evt = await httpConn.nextRequest();
|
||||
assert(evt);
|
||||
const { request, respondWith } = evt;
|
||||
assert(!request.body);
|
||||
await respondWith(new Response(stream.readable));
|
||||
httpConn.close();
|
||||
listener.close();
|
||||
})();
|
||||
|
||||
const resp = await fetch("http://127.0.0.1:4501/");
|
||||
const respBody = await resp.text();
|
||||
assertEquals("hello world", respBody);
|
||||
await promise;
|
||||
httpConn!.close();
|
||||
listener.close();
|
||||
},
|
||||
);
|
||||
|
||||
|
@ -240,17 +244,16 @@ Deno.test(
|
|||
Deno.test(
|
||||
{ permissions: { net: true } },
|
||||
async function httpServerStreamDuplex() {
|
||||
let httpConn: Deno.HttpConn;
|
||||
const listener = Deno.listen({ port: 4501 });
|
||||
const promise = (async () => {
|
||||
const listener = Deno.listen({ port: 4501 });
|
||||
const conn = await listener.accept();
|
||||
const httpConn = Deno.serveHttp(conn);
|
||||
httpConn = Deno.serveHttp(conn);
|
||||
const evt = await httpConn.nextRequest();
|
||||
assert(evt);
|
||||
const { request, respondWith } = evt;
|
||||
assert(request.body);
|
||||
await respondWith(new Response(request.body));
|
||||
httpConn.close();
|
||||
listener.close();
|
||||
})();
|
||||
|
||||
const ts = new TransformStream();
|
||||
|
@ -269,10 +272,13 @@ Deno.test(
|
|||
const chunk2 = await reader.read();
|
||||
assert(!chunk2.done);
|
||||
assertEquals(chunk2.value, new Uint8Array([2]));
|
||||
|
||||
await writable.close();
|
||||
const chunk3 = await reader.read();
|
||||
assert(chunk3.done);
|
||||
await promise;
|
||||
httpConn!.close();
|
||||
listener.close();
|
||||
},
|
||||
);
|
||||
|
||||
|
@ -351,18 +357,17 @@ Deno.test(
|
|||
Deno.test(
|
||||
{ permissions: { net: true } },
|
||||
async function httpServerRegressionHang() {
|
||||
let httpConn: Deno.HttpConn;
|
||||
const listener = Deno.listen({ port: 4501 });
|
||||
const promise = (async () => {
|
||||
const listener = Deno.listen({ port: 4501 });
|
||||
const conn = await listener.accept();
|
||||
const httpConn = Deno.serveHttp(conn);
|
||||
httpConn = Deno.serveHttp(conn);
|
||||
const event = await httpConn.nextRequest();
|
||||
assert(event);
|
||||
const { request, respondWith } = event;
|
||||
const reqBody = await request.text();
|
||||
assertEquals("request", reqBody);
|
||||
await respondWith(new Response("response"));
|
||||
httpConn.close();
|
||||
listener.close();
|
||||
})();
|
||||
|
||||
const resp = await fetch("http://127.0.0.1:4501/", {
|
||||
|
@ -372,6 +377,9 @@ Deno.test(
|
|||
const respBody = await resp.text();
|
||||
assertEquals("response", respBody);
|
||||
await promise;
|
||||
|
||||
httpConn!.close();
|
||||
listener.close();
|
||||
},
|
||||
);
|
||||
|
||||
|
@ -410,7 +418,7 @@ Deno.test(
|
|||
cancelReason!,
|
||||
);
|
||||
assert(cancelReason!);
|
||||
httpConn.close();
|
||||
httpConn!.close();
|
||||
listener.close();
|
||||
})();
|
||||
|
||||
|
@ -468,22 +476,23 @@ Deno.test(
|
|||
Deno.test(
|
||||
{ permissions: { net: true } },
|
||||
async function httpServerEmptyBlobResponse() {
|
||||
let httpConn: Deno.HttpConn;
|
||||
const listener = Deno.listen({ port: 4501 });
|
||||
const promise = (async () => {
|
||||
const listener = Deno.listen({ port: 4501 });
|
||||
const conn = await listener.accept();
|
||||
const httpConn = Deno.serveHttp(conn);
|
||||
httpConn = Deno.serveHttp(conn);
|
||||
const event = await httpConn.nextRequest();
|
||||
assert(event);
|
||||
const { respondWith } = event;
|
||||
await respondWith(new Response(new Blob([])));
|
||||
httpConn.close();
|
||||
listener.close();
|
||||
})();
|
||||
|
||||
const resp = await fetch("http://127.0.0.1:4501/");
|
||||
const respBody = await resp.text();
|
||||
assertEquals("", respBody);
|
||||
await promise;
|
||||
httpConn!.close();
|
||||
listener.close();
|
||||
},
|
||||
);
|
||||
|
||||
|
@ -633,14 +642,14 @@ Deno.test(
|
|||
}).pipeThrough(new TextEncoderStream());
|
||||
}
|
||||
|
||||
let httpConn: Deno.HttpConn;
|
||||
const listener = Deno.listen({ port: 4501 });
|
||||
const finished = (async () => {
|
||||
const conn = await listener.accept();
|
||||
const httpConn = Deno.serveHttp(conn);
|
||||
httpConn = Deno.serveHttp(conn);
|
||||
const requestEvent = await httpConn.nextRequest();
|
||||
const { respondWith } = requestEvent!;
|
||||
await respondWith(new Response(periodicStream()));
|
||||
httpConn.close();
|
||||
})();
|
||||
|
||||
// start a client
|
||||
|
@ -651,6 +660,8 @@ Deno.test(
|
|||
|
||||
await finished;
|
||||
clientConn.close();
|
||||
|
||||
httpConn!.close();
|
||||
listener.close();
|
||||
},
|
||||
);
|
||||
|
@ -658,11 +669,12 @@ Deno.test(
|
|||
Deno.test(
|
||||
{ permissions: { net: true } },
|
||||
async function httpRequestLatin1Headers() {
|
||||
let httpConn: Deno.HttpConn;
|
||||
const promise = (async () => {
|
||||
const listener = Deno.listen({ port: 4501 });
|
||||
const conn = await listener.accept();
|
||||
listener.close();
|
||||
const httpConn = Deno.serveHttp(conn);
|
||||
httpConn = Deno.serveHttp(conn);
|
||||
const reqEvent = await httpConn.nextRequest();
|
||||
assert(reqEvent);
|
||||
const { request, respondWith } = reqEvent;
|
||||
|
@ -670,7 +682,6 @@ Deno.test(
|
|||
await respondWith(
|
||||
new Response("", { headers: { "X-Header-Test": "Æ" } }),
|
||||
);
|
||||
httpConn.close();
|
||||
})();
|
||||
|
||||
const clientConn = await Deno.connect({ port: 4501 });
|
||||
|
@ -688,11 +699,14 @@ Deno.test(
|
|||
let responseText = "";
|
||||
const buf = new Uint8Array(1024);
|
||||
let read;
|
||||
|
||||
while ((read = await clientConn.read(buf)) !== null) {
|
||||
httpConn!.close();
|
||||
for (let i = 0; i < read; i++) {
|
||||
responseText += String.fromCharCode(buf[i]);
|
||||
}
|
||||
}
|
||||
|
||||
clientConn.close();
|
||||
|
||||
assert(/\r\n[Xx]-[Hh]eader-[Tt]est: Æ\r\n/.test(responseText));
|
||||
|
@ -704,18 +718,18 @@ Deno.test(
|
|||
Deno.test(
|
||||
{ permissions: { net: true } },
|
||||
async function httpServerRequestWithoutPath() {
|
||||
let httpConn: Deno.HttpConn;
|
||||
const listener = Deno.listen({ port: 4501 });
|
||||
const promise = (async () => {
|
||||
const listener = Deno.listen({ port: 4501 });
|
||||
const conn = await listener.accept();
|
||||
listener.close();
|
||||
const httpConn = Deno.serveHttp(conn);
|
||||
httpConn = Deno.serveHttp(conn);
|
||||
const reqEvent = await httpConn.nextRequest();
|
||||
assert(reqEvent);
|
||||
const { request, respondWith } = reqEvent;
|
||||
assertEquals(new URL(request.url).href, "http://127.0.0.1:4501/");
|
||||
assertEquals(await request.text(), "");
|
||||
await respondWith(new Response());
|
||||
httpConn.close();
|
||||
})();
|
||||
|
||||
const clientConn = await Deno.connect({ port: 4501 });
|
||||
|
@ -744,6 +758,7 @@ Deno.test(
|
|||
await writeRequest(clientConn);
|
||||
clientConn.close();
|
||||
await promise;
|
||||
httpConn!.close();
|
||||
},
|
||||
);
|
||||
|
||||
|
@ -868,11 +883,12 @@ Deno.test(function httpUpgradeWebSocketWithoutUpgradeHeader() {
|
|||
Deno.test(
|
||||
{ permissions: { net: true } },
|
||||
async function httpCookieConcatenation() {
|
||||
let httpConn: Deno.HttpConn;
|
||||
const promise = (async () => {
|
||||
const listener = Deno.listen({ port: 4501 });
|
||||
const conn = await listener.accept();
|
||||
listener.close();
|
||||
const httpConn = Deno.serveHttp(conn);
|
||||
httpConn = Deno.serveHttp(conn);
|
||||
const reqEvent = await httpConn.nextRequest();
|
||||
assert(reqEvent);
|
||||
const { request, respondWith } = reqEvent;
|
||||
|
@ -880,7 +896,6 @@ Deno.test(
|
|||
assertEquals(await request.text(), "");
|
||||
assertEquals(request.headers.get("cookie"), "foo=bar; bar=foo");
|
||||
await respondWith(new Response("ok"));
|
||||
httpConn.close();
|
||||
})();
|
||||
|
||||
const resp = await fetch("http://127.0.0.1:4501/", {
|
||||
|
@ -893,6 +908,7 @@ Deno.test(
|
|||
const text = await resp.text();
|
||||
assertEquals(text, "ok");
|
||||
await promise;
|
||||
httpConn!.close();
|
||||
},
|
||||
);
|
||||
|
||||
|
@ -910,7 +926,7 @@ Deno.test({ permissions: { net: true } }, async function httpServerPanic() {
|
|||
|
||||
httpConn.nextRequest();
|
||||
await client.write(encoder.encode("\r\n\r\n"));
|
||||
httpConn.close();
|
||||
httpConn!.close();
|
||||
|
||||
client.close();
|
||||
listener.close();
|
||||
|
@ -923,21 +939,23 @@ Deno.test(
|
|||
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
|
||||
file.close();
|
||||
|
||||
let httpConn: Deno.HttpConn;
|
||||
const listener = Deno.listen({ port: 4503 });
|
||||
const promise = (async () => {
|
||||
const listener = Deno.listen({ port: 4503 });
|
||||
const conn = await listener.accept();
|
||||
const httpConn = Deno.serveHttp(conn);
|
||||
httpConn = Deno.serveHttp(conn);
|
||||
const ev = await httpConn.nextRequest();
|
||||
const { respondWith } = ev!;
|
||||
const f = await Deno.open(tmpFile, { read: true });
|
||||
await respondWith(new Response(f.readable, { status: 200 }));
|
||||
httpConn.close();
|
||||
listener.close();
|
||||
})();
|
||||
const resp = await fetch("http://127.0.0.1:4503/");
|
||||
const body = await resp.arrayBuffer();
|
||||
assertEquals(body.byteLength, 70 * 1024);
|
||||
await promise;
|
||||
httpConn!.close();
|
||||
listener.close();
|
||||
},
|
||||
);
|
||||
|
||||
|
@ -976,7 +994,7 @@ Deno.test(
|
|||
}
|
||||
|
||||
assert(didThrow);
|
||||
httpConn.close();
|
||||
httpConn!.close();
|
||||
listener.close();
|
||||
client.close();
|
||||
},
|
||||
|
@ -1018,7 +1036,7 @@ Deno.test(
|
|||
|
||||
await respondWith(res).catch((error: Error) => errors.push(error));
|
||||
|
||||
httpConn.close();
|
||||
httpConn!.close();
|
||||
listener.close();
|
||||
|
||||
assert(errors.length >= 1);
|
||||
|
@ -1047,7 +1065,7 @@ Deno.test(
|
|||
)),
|
||||
]);
|
||||
|
||||
httpConn.close();
|
||||
httpConn!.close();
|
||||
listener.close();
|
||||
clientConn.close();
|
||||
},
|
||||
|
@ -1133,10 +1151,11 @@ Deno.test(
|
|||
const hostname = "localhost";
|
||||
const port = 4501;
|
||||
|
||||
let httpConn: Deno.HttpConn;
|
||||
const listener = Deno.listen({ hostname, port });
|
||||
async function server() {
|
||||
const listener = Deno.listen({ hostname, port });
|
||||
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 event = await httpConn.nextRequest();
|
||||
assert(event);
|
||||
|
@ -1146,8 +1165,6 @@ Deno.test(
|
|||
await event.respondWith(response);
|
||||
});
|
||||
await Promise.all(promises);
|
||||
httpConn.close();
|
||||
listener.close();
|
||||
}
|
||||
|
||||
async function client() {
|
||||
|
@ -1159,6 +1176,8 @@ Deno.test(
|
|||
}
|
||||
|
||||
await Promise.all([server(), delay(100).then(client)]);
|
||||
httpConn!.close();
|
||||
listener.close();
|
||||
},
|
||||
);
|
||||
|
||||
|
@ -1213,16 +1232,15 @@ Deno.test(
|
|||
const hostname = "localhost";
|
||||
const port = 4501;
|
||||
|
||||
let httpConn: Deno.HttpConn;
|
||||
const listener = Deno.listen({ hostname, port });
|
||||
async function server() {
|
||||
const listener = Deno.listen({ hostname, port });
|
||||
const tcpConn = await listener.accept();
|
||||
const httpConn = Deno.serveHttp(tcpConn);
|
||||
httpConn = Deno.serveHttp(tcpConn);
|
||||
const event = await httpConn.nextRequest() as Deno.RequestEvent;
|
||||
assert(event.request.body);
|
||||
const response = new Response();
|
||||
await event.respondWith(response);
|
||||
httpConn.close();
|
||||
listener.close();
|
||||
}
|
||||
|
||||
async function client() {
|
||||
|
@ -1237,17 +1255,20 @@ Deno.test(
|
|||
}
|
||||
|
||||
await Promise.all([server(), client()]);
|
||||
httpConn!.close();
|
||||
listener.close();
|
||||
},
|
||||
);
|
||||
|
||||
Deno.test(
|
||||
{ permissions: { net: true } },
|
||||
async function httpServerRespondNonAsciiUint8Array() {
|
||||
let httpConn: Deno.HttpConn;
|
||||
const listener = Deno.listen({ port: 4501 });
|
||||
const promise = (async () => {
|
||||
const listener = Deno.listen({ port: 4501 });
|
||||
const conn = await listener.accept();
|
||||
listener.close();
|
||||
const httpConn = Deno.serveHttp(conn);
|
||||
httpConn = Deno.serveHttp(conn);
|
||||
const e = await httpConn.nextRequest();
|
||||
assert(e);
|
||||
const { request, respondWith } = e;
|
||||
|
@ -1255,7 +1276,6 @@ Deno.test(
|
|||
await respondWith(
|
||||
new Response(new Uint8Array([128]), {}),
|
||||
);
|
||||
httpConn.close();
|
||||
})();
|
||||
|
||||
const resp = await fetch("http://localhost:4501/");
|
||||
|
@ -1264,6 +1284,7 @@ Deno.test(
|
|||
assertEquals(new Uint8Array(body), new Uint8Array([128]));
|
||||
|
||||
await promise;
|
||||
httpConn!.close();
|
||||
},
|
||||
);
|
||||
|
||||
|
@ -1276,11 +1297,12 @@ Deno.test(
|
|||
async function httpServerOnUnixSocket() {
|
||||
const filePath = Deno.makeTempFileSync();
|
||||
|
||||
let httpConn: Deno.HttpConn;
|
||||
const promise = (async () => {
|
||||
const listener = Deno.listen({ path: filePath, transport: "unix" });
|
||||
const conn = await listener.accept();
|
||||
listener.close();
|
||||
const httpConn = Deno.serveHttp(conn);
|
||||
httpConn = Deno.serveHttp(conn);
|
||||
const reqEvent = await httpConn.nextRequest();
|
||||
assert(reqEvent);
|
||||
const { request, respondWith } = reqEvent;
|
||||
|
@ -1289,7 +1311,6 @@ Deno.test(
|
|||
assertEquals(decodeURIComponent(url.host), filePath);
|
||||
assertEquals(url.pathname, "/path/name");
|
||||
await respondWith(new Response("", { headers: {} }));
|
||||
httpConn.close();
|
||||
})();
|
||||
|
||||
// fetch() does not supports unix domain sockets yet https://github.com/denoland/deno/issues/8821
|
||||
|
@ -1307,6 +1328,7 @@ Deno.test(
|
|||
conn.close();
|
||||
|
||||
await promise;
|
||||
httpConn!.close();
|
||||
},
|
||||
);
|
||||
|
||||
|
@ -1324,9 +1346,10 @@ Deno.test({
|
|||
|
||||
const data = { hello: "deno", now: "with", compressed: "body" };
|
||||
|
||||
let httpConn: Deno.HttpConn;
|
||||
async function server() {
|
||||
const tcpConn = await listener.accept();
|
||||
const httpConn = Deno.serveHttp(tcpConn);
|
||||
httpConn = Deno.serveHttp(tcpConn);
|
||||
const e = await httpConn.nextRequest();
|
||||
assert(e);
|
||||
const { request, respondWith } = e;
|
||||
|
@ -1335,7 +1358,6 @@ Deno.test({
|
|||
headers: { "content-type": "application/json" },
|
||||
});
|
||||
await respondWith(response);
|
||||
httpConn.close();
|
||||
listener.close();
|
||||
}
|
||||
|
||||
|
@ -1361,6 +1383,7 @@ Deno.test({
|
|||
}
|
||||
|
||||
await Promise.all([server(), client()]);
|
||||
httpConn!.close();
|
||||
},
|
||||
});
|
||||
|
||||
|
@ -1374,9 +1397,10 @@ Deno.test({
|
|||
|
||||
const data = { hello: "deno", now: "with", compressed: "body" };
|
||||
|
||||
let httpConn: Deno.HttpConn;
|
||||
async function server() {
|
||||
const tcpConn = await listener.accept();
|
||||
const httpConn = Deno.serveHttp(tcpConn);
|
||||
httpConn = Deno.serveHttp(tcpConn);
|
||||
const e = await httpConn.nextRequest();
|
||||
assert(e);
|
||||
const { request, respondWith } = e;
|
||||
|
@ -1385,7 +1409,6 @@ Deno.test({
|
|||
headers: { "content-type": "application/json" },
|
||||
});
|
||||
await respondWith(response);
|
||||
httpConn.close();
|
||||
listener.close();
|
||||
}
|
||||
|
||||
|
@ -1413,6 +1436,7 @@ Deno.test({
|
|||
}
|
||||
|
||||
await Promise.all([server(), client()]);
|
||||
httpConn!.close();
|
||||
},
|
||||
});
|
||||
|
||||
|
@ -1423,10 +1447,11 @@ Deno.test({
|
|||
const hostname = "localhost";
|
||||
const port = 4501;
|
||||
|
||||
let httpConn: Deno.HttpConn;
|
||||
async function server() {
|
||||
const listener = Deno.listen({ hostname, port });
|
||||
const tcpConn = await listener.accept();
|
||||
const httpConn = Deno.serveHttp(tcpConn);
|
||||
httpConn = Deno.serveHttp(tcpConn);
|
||||
const e = await httpConn.nextRequest();
|
||||
assert(e);
|
||||
const { request, respondWith } = e;
|
||||
|
@ -1438,7 +1463,6 @@ Deno.test({
|
|||
},
|
||||
);
|
||||
await respondWith(response);
|
||||
httpConn.close();
|
||||
listener.close();
|
||||
}
|
||||
|
||||
|
@ -1464,6 +1488,7 @@ Deno.test({
|
|||
}
|
||||
|
||||
await Promise.all([server(), client()]);
|
||||
httpConn!.close();
|
||||
},
|
||||
});
|
||||
|
||||
|
@ -1474,10 +1499,11 @@ Deno.test({
|
|||
const hostname = "localhost";
|
||||
const port = 4501;
|
||||
|
||||
let httpConn: Deno.HttpConn;
|
||||
async function server() {
|
||||
const listener = Deno.listen({ hostname, port });
|
||||
const tcpConn = await listener.accept();
|
||||
const httpConn = Deno.serveHttp(tcpConn);
|
||||
httpConn = Deno.serveHttp(tcpConn);
|
||||
const e = await httpConn.nextRequest();
|
||||
assert(e);
|
||||
const { request, respondWith } = e;
|
||||
|
@ -1492,7 +1518,6 @@ Deno.test({
|
|||
},
|
||||
);
|
||||
await respondWith(response);
|
||||
httpConn.close();
|
||||
listener.close();
|
||||
}
|
||||
|
||||
|
@ -1518,6 +1543,7 @@ Deno.test({
|
|||
}
|
||||
|
||||
await Promise.all([server(), client()]);
|
||||
httpConn!.close();
|
||||
},
|
||||
});
|
||||
|
||||
|
@ -1528,10 +1554,11 @@ Deno.test({
|
|||
const hostname = "localhost";
|
||||
const port = 4501;
|
||||
|
||||
let httpConn: Deno.HttpConn;
|
||||
async function server() {
|
||||
const listener = Deno.listen({ hostname, port });
|
||||
const tcpConn = await listener.accept();
|
||||
const httpConn = Deno.serveHttp(tcpConn);
|
||||
httpConn = Deno.serveHttp(tcpConn);
|
||||
const e = await httpConn.nextRequest();
|
||||
assert(e);
|
||||
const { request, respondWith } = e;
|
||||
|
@ -1543,7 +1570,6 @@ Deno.test({
|
|||
},
|
||||
);
|
||||
await respondWith(response);
|
||||
httpConn.close();
|
||||
listener.close();
|
||||
}
|
||||
|
||||
|
@ -1569,6 +1595,7 @@ Deno.test({
|
|||
}
|
||||
|
||||
await Promise.all([server(), client()]);
|
||||
httpConn!.close();
|
||||
},
|
||||
});
|
||||
|
||||
|
@ -1579,10 +1606,11 @@ Deno.test({
|
|||
const hostname = "localhost";
|
||||
const port = 4501;
|
||||
|
||||
let httpConn: Deno.HttpConn;
|
||||
async function server() {
|
||||
const listener = Deno.listen({ hostname, port });
|
||||
const tcpConn = await listener.accept();
|
||||
const httpConn = Deno.serveHttp(tcpConn);
|
||||
httpConn = Deno.serveHttp(tcpConn);
|
||||
const e = await httpConn.nextRequest();
|
||||
assert(e);
|
||||
const { request, respondWith } = e;
|
||||
|
@ -1597,7 +1625,6 @@ Deno.test({
|
|||
},
|
||||
);
|
||||
await respondWith(response);
|
||||
httpConn.close();
|
||||
listener.close();
|
||||
}
|
||||
|
||||
|
@ -1627,6 +1654,7 @@ Deno.test({
|
|||
}
|
||||
|
||||
await Promise.all([server(), client()]);
|
||||
httpConn!.close();
|
||||
},
|
||||
});
|
||||
|
||||
|
@ -1637,10 +1665,11 @@ Deno.test({
|
|||
const hostname = "localhost";
|
||||
const port = 4501;
|
||||
|
||||
let httpConn: Deno.HttpConn;
|
||||
async function server() {
|
||||
const listener = Deno.listen({ hostname, port });
|
||||
const tcpConn = await listener.accept();
|
||||
const httpConn = Deno.serveHttp(tcpConn);
|
||||
httpConn = Deno.serveHttp(tcpConn);
|
||||
const e = await httpConn.nextRequest();
|
||||
assert(e);
|
||||
const { request, respondWith } = e;
|
||||
|
@ -1655,7 +1684,6 @@ Deno.test({
|
|||
},
|
||||
);
|
||||
await respondWith(response);
|
||||
httpConn.close();
|
||||
listener.close();
|
||||
}
|
||||
|
||||
|
@ -1684,6 +1712,7 @@ Deno.test({
|
|||
}
|
||||
|
||||
await Promise.all([server(), client()]);
|
||||
httpConn!.close();
|
||||
},
|
||||
});
|
||||
|
||||
|
@ -1694,10 +1723,11 @@ Deno.test({
|
|||
const hostname = "localhost";
|
||||
const port = 4501;
|
||||
|
||||
let httpConn: Deno.HttpConn;
|
||||
async function server() {
|
||||
const listener = Deno.listen({ hostname, port });
|
||||
const tcpConn = await listener.accept();
|
||||
const httpConn = Deno.serveHttp(tcpConn);
|
||||
httpConn = Deno.serveHttp(tcpConn);
|
||||
const e = await httpConn.nextRequest();
|
||||
assert(e);
|
||||
const { request, respondWith } = e;
|
||||
|
@ -1712,7 +1742,6 @@ Deno.test({
|
|||
},
|
||||
);
|
||||
await respondWith(response);
|
||||
httpConn.close();
|
||||
listener.close();
|
||||
}
|
||||
|
||||
|
@ -1738,6 +1767,7 @@ Deno.test({
|
|||
}
|
||||
|
||||
await Promise.all([server(), client()]);
|
||||
httpConn!.close();
|
||||
},
|
||||
});
|
||||
|
||||
|
@ -1748,10 +1778,11 @@ Deno.test({
|
|||
const hostname = "localhost";
|
||||
const port = 4501;
|
||||
|
||||
let httpConn: Deno.HttpConn;
|
||||
async function server() {
|
||||
const listener = Deno.listen({ hostname, port });
|
||||
const tcpConn = await listener.accept();
|
||||
const httpConn = Deno.serveHttp(tcpConn);
|
||||
httpConn = Deno.serveHttp(tcpConn);
|
||||
const e = await httpConn.nextRequest();
|
||||
assert(e);
|
||||
const { request, respondWith } = e;
|
||||
|
@ -1766,7 +1797,6 @@ Deno.test({
|
|||
},
|
||||
);
|
||||
await respondWith(response);
|
||||
httpConn.close();
|
||||
listener.close();
|
||||
}
|
||||
|
||||
|
@ -1792,6 +1822,7 @@ Deno.test({
|
|||
}
|
||||
|
||||
await Promise.all([server(), client()]);
|
||||
httpConn!.close();
|
||||
},
|
||||
});
|
||||
|
||||
|
@ -1807,9 +1838,10 @@ Deno.test({
|
|||
|
||||
const data = { hello: "deno", now: "with", compressed: "body" };
|
||||
|
||||
let httpConn: Deno.HttpConn;
|
||||
async function server() {
|
||||
const tcpConn = await listener.accept();
|
||||
const httpConn = Deno.serveHttp(tcpConn);
|
||||
httpConn = Deno.serveHttp(tcpConn);
|
||||
const e = await httpConn.nextRequest();
|
||||
assert(e);
|
||||
const { request, respondWith } = e;
|
||||
|
@ -1825,7 +1857,6 @@ Deno.test({
|
|||
{ headers: { "content-type": "application/json" } },
|
||||
);
|
||||
await respondWith(response);
|
||||
httpConn.close();
|
||||
listener.close();
|
||||
}
|
||||
|
||||
|
@ -1852,6 +1883,7 @@ Deno.test({
|
|||
}
|
||||
|
||||
await Promise.all([server(), client()]);
|
||||
httpConn!.close();
|
||||
},
|
||||
});
|
||||
|
||||
|
@ -1867,9 +1899,10 @@ Deno.test({
|
|||
|
||||
const data = { hello: "deno", now: "with", compressed: "body" };
|
||||
|
||||
let httpConn: Deno.HttpConn;
|
||||
async function server() {
|
||||
const tcpConn = await listener.accept();
|
||||
const httpConn = Deno.serveHttp(tcpConn);
|
||||
httpConn = Deno.serveHttp(tcpConn);
|
||||
const e = await httpConn.nextRequest();
|
||||
assert(e);
|
||||
const { request, respondWith } = e;
|
||||
|
@ -1885,7 +1918,6 @@ Deno.test({
|
|||
{ headers: { "content-type": "application/json" } },
|
||||
);
|
||||
await respondWith(response);
|
||||
httpConn.close();
|
||||
listener.close();
|
||||
}
|
||||
|
||||
|
@ -1913,6 +1945,7 @@ Deno.test({
|
|||
}
|
||||
|
||||
await Promise.all([server(), client()]);
|
||||
httpConn!.close();
|
||||
},
|
||||
});
|
||||
|
||||
|
@ -1924,10 +1957,11 @@ Deno.test({
|
|||
const port = 4501;
|
||||
let contentLength: string;
|
||||
|
||||
let httpConn: Deno.HttpConn;
|
||||
async function server() {
|
||||
const listener = Deno.listen({ hostname, port });
|
||||
const tcpConn = await listener.accept();
|
||||
const httpConn = Deno.serveHttp(tcpConn);
|
||||
httpConn = Deno.serveHttp(tcpConn);
|
||||
const e = await httpConn.nextRequest();
|
||||
assert(e);
|
||||
const { request, respondWith } = e;
|
||||
|
@ -1948,7 +1982,6 @@ Deno.test({
|
|||
},
|
||||
);
|
||||
await respondWith(response);
|
||||
httpConn.close();
|
||||
listener.close();
|
||||
}
|
||||
|
||||
|
@ -1977,6 +2010,7 @@ Deno.test({
|
|||
}
|
||||
|
||||
await Promise.all([server(), client()]);
|
||||
httpConn!.close();
|
||||
},
|
||||
});
|
||||
|
||||
|
@ -1988,10 +2022,11 @@ Deno.test({
|
|||
const port = 4501;
|
||||
let contentLength: string;
|
||||
|
||||
let httpConn: Deno.HttpConn;
|
||||
async function server() {
|
||||
const listener = Deno.listen({ hostname, port });
|
||||
const tcpConn = await listener.accept();
|
||||
const httpConn = Deno.serveHttp(tcpConn);
|
||||
httpConn = Deno.serveHttp(tcpConn);
|
||||
const e = await httpConn.nextRequest();
|
||||
assert(e);
|
||||
const { request, respondWith } = e;
|
||||
|
@ -2007,7 +2042,6 @@ Deno.test({
|
|||
},
|
||||
);
|
||||
await respondWith(response);
|
||||
httpConn.close();
|
||||
listener.close();
|
||||
}
|
||||
|
||||
|
@ -2037,6 +2071,7 @@ Deno.test({
|
|||
}
|
||||
|
||||
await Promise.all([server(), client()]);
|
||||
httpConn!.close();
|
||||
},
|
||||
});
|
||||
|
||||
|
@ -2048,10 +2083,11 @@ Deno.test({
|
|||
const port = 4501;
|
||||
let contentLength: string;
|
||||
|
||||
let httpConn: Deno.HttpConn;
|
||||
async function server() {
|
||||
const listener = Deno.listen({ hostname, port });
|
||||
const tcpConn = await listener.accept();
|
||||
const httpConn = Deno.serveHttp(tcpConn);
|
||||
httpConn = Deno.serveHttp(tcpConn);
|
||||
const e = await httpConn.nextRequest();
|
||||
assert(e);
|
||||
const { request, respondWith } = e;
|
||||
|
@ -2068,7 +2104,6 @@ Deno.test({
|
|||
},
|
||||
);
|
||||
await respondWith(response);
|
||||
httpConn.close();
|
||||
listener.close();
|
||||
}
|
||||
|
||||
|
@ -2095,6 +2130,7 @@ Deno.test({
|
|||
}
|
||||
|
||||
await Promise.all([server(), client()]);
|
||||
httpConn!.close();
|
||||
},
|
||||
});
|
||||
|
||||
|
@ -2248,7 +2284,7 @@ Deno.test("upgradeHttp unix", {
|
|||
const resp = new Response(null, { status: 101 });
|
||||
await respondWith(resp);
|
||||
await promise;
|
||||
httpConn.close();
|
||||
httpConn!.close();
|
||||
})();
|
||||
|
||||
await Promise.all([server, client()]);
|
||||
|
|
|
@ -160,10 +160,11 @@
|
|||
|
||||
function opAsync(opName, ...args) {
|
||||
const promiseId = nextPromiseId++;
|
||||
let p = setPromise(promiseId);
|
||||
const maybeError = ops[opName](promiseId, ...args);
|
||||
// Handle sync error (e.g: error parsing args)
|
||||
if (maybeError) return unwrapOpResult(maybeError);
|
||||
let p = PromisePrototypeThen(setPromise(promiseId), unwrapOpResult);
|
||||
p = PromisePrototypeThen(p, unwrapOpResult);
|
||||
if (opCallTracingEnabled) {
|
||||
// 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.
|
||||
|
|
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.
|
||||
pub struct OpCall<T>(MaybeDone<Pin<Box<dyn Future<Output = T>>>>);
|
||||
|
||||
pub enum EagerPollResult<T> {
|
||||
Ready(T),
|
||||
Pending(OpCall<T>),
|
||||
}
|
||||
|
||||
impl<T> OpCall<T> {
|
||||
/// Wraps a future, and polls the inner future immediately.
|
||||
/// 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 mut inner = maybe_done(boxed);
|
||||
let waker = noop_waker();
|
||||
let mut cx = Context::from_waker(&waker);
|
||||
let mut pinned = Pin::new(&mut inner);
|
||||
let _ = pinned.as_mut().poll(&mut cx);
|
||||
Self(inner)
|
||||
let poll = pinned.as_mut().poll(&mut cx);
|
||||
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).
|
||||
|
|
122
core/runtime.rs
122
core/runtime.rs
|
@ -2145,14 +2145,54 @@ impl JsRealm {
|
|||
|
||||
#[inline]
|
||||
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)>
|
||||
+ 'static,
|
||||
) {
|
||||
let state_rc = JsRuntime::state(scope);
|
||||
let mut state = state_rc.borrow_mut();
|
||||
state.pending_ops.push(OpCall::eager(op));
|
||||
state.have_unpolled_ops = true;
|
||||
match OpCall::eager(op) {
|
||||
// This calls promise.resolve() before the control goes back to userland JS. It works something
|
||||
// along the lines of:
|
||||
//
|
||||
// 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)]
|
||||
|
@ -2194,7 +2234,7 @@ pub mod tests {
|
|||
dispatch_count: Arc<AtomicUsize>,
|
||||
}
|
||||
|
||||
#[op]
|
||||
#[op(deferred)]
|
||||
async fn op_test(
|
||||
rc_op_state: Rc<RefCell<OpState>>,
|
||||
control: u8,
|
||||
|
@ -2255,41 +2295,6 @@ pub mod tests {
|
|||
(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]
|
||||
fn test_ref_unref_ops() {
|
||||
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]
|
||||
fn test_dispatch_no_zero_copy_buf() {
|
||||
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
|
||||
/// [`TimerHandle`] resource given by `rid` has been canceled.
|
||||
#[op]
|
||||
#[op(deferred)]
|
||||
pub async fn op_sleep(
|
||||
state: Rc<RefCell<OpState>>,
|
||||
millis: u64,
|
||||
|
|
|
@ -420,7 +420,7 @@ pub async fn op_ws_send(
|
|||
Ok(())
|
||||
}
|
||||
|
||||
#[op]
|
||||
#[op(deferred)]
|
||||
pub async fn op_ws_close(
|
||||
state: Rc<RefCell<OpState>>,
|
||||
rid: ResourceId,
|
||||
|
|
10
ops/lib.rs
10
ops/lib.rs
|
@ -51,6 +51,7 @@ struct MacroArgs {
|
|||
is_unstable: bool,
|
||||
is_v8: bool,
|
||||
must_be_fast: bool,
|
||||
deferred: bool,
|
||||
}
|
||||
|
||||
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(String::as_str).collect();
|
||||
for var in vars.iter() {
|
||||
if !["unstable", "v8", "fast"].contains(var) {
|
||||
if !["unstable", "v8", "fast", "deferred"].contains(var) {
|
||||
return Err(syn::Error::new(
|
||||
input.span(),
|
||||
"Ops expect #[op] or #[op(unstable)]",
|
||||
|
@ -73,6 +74,7 @@ impl syn::parse::Parse for MacroArgs {
|
|||
is_unstable: vars.contains(&"unstable"),
|
||||
is_v8: vars.contains(&"v8"),
|
||||
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_v8,
|
||||
must_be_fast,
|
||||
deferred,
|
||||
} = margs;
|
||||
let func = syn::parse::<syn::ItemFn>(item).expect("expected a function");
|
||||
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 is_async = asyncness || is_future(&func.sig.output);
|
||||
let v8_body = if is_async {
|
||||
codegen_v8_async(&core, &func, margs, asyncness)
|
||||
codegen_v8_async(&core, &func, margs, asyncness, deferred)
|
||||
} else {
|
||||
codegen_v8_sync(&core, &func, margs)
|
||||
};
|
||||
|
@ -173,6 +176,7 @@ fn codegen_v8_async(
|
|||
f: &syn::ItemFn,
|
||||
margs: MacroArgs,
|
||||
asyncness: bool,
|
||||
deferred: bool,
|
||||
) -> TokenStream2 {
|
||||
let MacroArgs { is_v8, .. } = margs;
|
||||
let special_args = f
|
||||
|
@ -256,7 +260,7 @@ fn codegen_v8_async(
|
|||
};
|
||||
|
||||
#pre_result
|
||||
#core::_ops::queue_async_op(scope, async move {
|
||||
#core::_ops::queue_async_op(state, scope, #deferred, async move {
|
||||
let result = #result_fut
|
||||
#result_wrapper
|
||||
(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
|
||||
// false positives may occur (https://github.com/denoland/deno/issues/4591)
|
||||
await opSanitizerDelay();
|
||||
await opSanitizerDelay();
|
||||
}
|
||||
|
||||
if (shouldSkipSanitizers(desc)) return;
|
||||
|
|
|
@ -39,7 +39,7 @@ fn op_worker_post_message(
|
|||
Ok(())
|
||||
}
|
||||
|
||||
#[op]
|
||||
#[op(deferred)]
|
||||
async fn op_worker_recv_message(
|
||||
state: Rc<RefCell<OpState>>,
|
||||
) -> Result<Option<JsMessageData>, AnyError> {
|
||||
|
|
Loading…
Reference in a new issue