summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock4
-rw-r--r--cli/tests/unit/websocket_test.ts51
-rw-r--r--ext/websocket/Cargo.toml2
-rw-r--r--ext/websocket/lib.rs18
4 files changed, 70 insertions, 5 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 29f02d5c4..cb5bc2f9d 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1819,9 +1819,9 @@ dependencies = [
[[package]]
name = "fastwebsockets"
-version = "0.2.1"
+version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "99a248d92ac4e9048a30d147d7897eaaadd0a5230f11982ab7d6935d7d268902"
+checksum = "fcf2f933f24f45831bd66580a8f9394e440f1f5a23806cf0d4d8b6649e1a01e9"
dependencies = [
"base64 0.21.0",
"cc",
diff --git a/cli/tests/unit/websocket_test.ts b/cli/tests/unit/websocket_test.ts
index 948e2add2..997d8f0df 100644
--- a/cli/tests/unit/websocket_test.ts
+++ b/cli/tests/unit/websocket_test.ts
@@ -1,5 +1,11 @@
// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
-import { assertEquals, assertThrows, deferred, fail } from "./test_util.ts";
+import {
+ assert,
+ assertEquals,
+ assertThrows,
+ deferred,
+ fail,
+} from "./test_util.ts";
Deno.test({ permissions: "none" }, function websocketPermissionless() {
assertThrows(
@@ -82,3 +88,46 @@ Deno.test(
ws.close();
},
);
+
+// https://github.com/denoland/deno/issues/18775
+Deno.test({
+ sanitizeOps: false,
+ sanitizeResources: false,
+}, async function websocketDoubleClose() {
+ const promise = deferred();
+
+ const ac = new AbortController();
+ const listeningPromise = deferred();
+
+ const server = Deno.serve({
+ handler: (req) => {
+ const { response, socket } = Deno.upgradeWebSocket(req);
+ let called = false;
+ socket.onopen = () => socket.send("Hello");
+ socket.onmessage = () => {
+ assert(!called);
+ called = true;
+ socket.send("bye");
+ socket.close();
+ };
+ socket.onclose = () => ac.abort();
+ socket.onerror = () => fail();
+ return response;
+ },
+ signal: ac.signal,
+ onListen: () => listeningPromise.resolve(),
+ hostname: "localhost",
+ port: 4247,
+ });
+
+ await listeningPromise;
+
+ const ws = new WebSocket("ws://localhost:4247/");
+ assertEquals(ws.url, "ws://localhost:4247/");
+ ws.onerror = () => fail();
+ ws.onmessage = () => ws.send("bye");
+ ws.onclose = () => {
+ promise.resolve();
+ };
+ await Promise.all([promise, server]);
+});
diff --git a/ext/websocket/Cargo.toml b/ext/websocket/Cargo.toml
index 03cb3076a..a96b6cceb 100644
--- a/ext/websocket/Cargo.toml
+++ b/ext/websocket/Cargo.toml
@@ -16,7 +16,7 @@ path = "lib.rs"
[dependencies]
deno_core.workspace = true
deno_tls.workspace = true
-fastwebsockets = { version = "0.2.1", features = ["upgrade"] }
+fastwebsockets = { version = "0.2.4", features = ["upgrade"] }
http.workspace = true
hyper.workspace = true
serde.workspace = true
diff --git a/ext/websocket/lib.rs b/ext/websocket/lib.rs
index f63191a8e..798856bc1 100644
--- a/ext/websocket/lib.rs
+++ b/ext/websocket/lib.rs
@@ -34,6 +34,7 @@ use std::cell::Cell;
use std::cell::RefCell;
use std::convert::TryFrom;
use std::fmt;
+use std::future::Future;
use std::path::PathBuf;
use std::rc::Rc;
use std::sync::Arc;
@@ -239,7 +240,8 @@ where
_ => unreachable!(),
};
- let client = fastwebsockets::handshake::client(request, socket);
+ let client =
+ fastwebsockets::handshake::client(&LocalExecutor, request, socket);
let (stream, response): (WebSocket<Upgraded>, Response<Body>) =
if let Some(cancel_resource) = cancel_resource {
@@ -533,3 +535,17 @@ pub fn get_network_error_class_name(e: &AnyError) -> Option<&'static str> {
e.downcast_ref::<DomExceptionNetworkError>()
.map(|_| "DOMExceptionNetworkError")
}
+
+// Needed so hyper can use non Send futures
+#[derive(Clone)]
+struct LocalExecutor;
+
+impl<Fut> hyper::rt::Executor<Fut> for LocalExecutor
+where
+ Fut: Future + 'static,
+ Fut::Output: 'static,
+{
+ fn execute(&self, fut: Fut) {
+ tokio::task::spawn_local(fut);
+ }
+}