0
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2025-03-09 21:57:40 -04:00

fix(ext/websocket): WebSocket dispatch single close event (#13443)

This commit is contained in:
Leo Kettmeir 2022-05-23 13:21:11 +02:00 committed by Kitson Kelly
parent bcc8891ec3
commit 50ebb8799b
No known key found for this signature in database
GPG key ID: 2D87CFF11B51960A
5 changed files with 62 additions and 39 deletions

View file

@ -738,10 +738,12 @@ fn websocket_server_multi_field_connection_header() {
.uri("ws://localhost:4319") .uri("ws://localhost:4319")
.body(()) .body(())
.unwrap(); .unwrap();
assert!( let (mut socket, _) =
deno_runtime::deno_websocket::tokio_tungstenite::tungstenite::connect(req) deno_runtime::deno_websocket::tokio_tungstenite::tungstenite::connect(req)
.is_ok() .unwrap();
); let message = socket.read_message().unwrap();
assert_eq!(message, deno_runtime::deno_websocket::tokio_tungstenite::tungstenite::Message::Close(None));
socket.close(None).unwrap();
assert!(child.wait().unwrap().success()); assert!(child.wait().unwrap().success());
} }

View file

@ -357,19 +357,6 @@
httpConn.close(); httpConn.close();
if (ws[_readyState] === WebSocket.CLOSING) {
await core.opAsync("op_ws_close", wsRid);
ws[_readyState] = WebSocket.CLOSED;
const errEvent = new ErrorEvent("error");
ws.dispatchEvent(errEvent);
const event = new CloseEvent("close");
ws.dispatchEvent(event);
core.tryClose(wsRid);
} else {
ws[_readyState] = WebSocket.OPEN; ws[_readyState] = WebSocket.OPEN;
const event = new Event("open"); const event = new Event("open");
ws.dispatchEvent(event); ws.dispatchEvent(event);
@ -383,7 +370,6 @@
} }
ws[_serverHandleIdleTimeout](); ws[_serverHandleIdleTimeout]();
} }
}
} finally { } finally {
if (SetPrototypeDelete(httpConn.managedResources, streamRid)) { if (SetPrototypeDelete(httpConn.managedResources, streamRid)) {
core.close(streamRid); core.close(streamRid);

View file

@ -29,6 +29,8 @@
StringPrototypeToLowerCase, StringPrototypeToLowerCase,
Symbol, Symbol,
SymbolIterator, SymbolIterator,
PromisePrototypeCatch,
SymbolFor,
} = window.__bootstrap.primordials; } = window.__bootstrap.primordials;
webidl.converters["sequence<DOMString> or DOMString"] = (V, opts) => { webidl.converters["sequence<DOMString> or DOMString"] = (V, opts) => {
@ -367,16 +369,19 @@
} else if (this[_readyState] === OPEN) { } else if (this[_readyState] === OPEN) {
this[_readyState] = CLOSING; this[_readyState] = CLOSING;
PromisePrototypeThen( PromisePrototypeCatch(
core.opAsync("op_ws_close", this[_rid], code, reason), core.opAsync("op_ws_close", this[_rid], code, reason),
() => { (err) => {
this[_readyState] = CLOSED; this[_readyState] = CLOSED;
const event = new CloseEvent("close", {
wasClean: true, const errorEv = new ErrorEvent("error", {
code: code ?? 1005, error: err,
reason, message: ErrorPrototypeToString(err),
}); });
this.dispatchEvent(event); this.dispatchEvent(errorEv);
const closeEv = new CloseEvent("close");
this.dispatchEvent(closeEv);
core.tryClose(this[_rid]); core.tryClose(this[_rid]);
}, },
); );
@ -384,7 +389,7 @@
} }
async [_eventLoop]() { async [_eventLoop]() {
while (this[_readyState] === OPEN) { while (this[_readyState] !== CLOSED) {
const { kind, value } = await core.opAsync( const { kind, value } = await core.opAsync(
"op_ws_next_event", "op_ws_next_event",
this[_rid], this[_rid],
@ -429,9 +434,23 @@
} }
case "closed": case "closed":
case "close": { case "close": {
const prevState = this[_readyState];
this[_readyState] = CLOSED; this[_readyState] = CLOSED;
clearTimeout(this[_idleTimeoutTimeout]); clearTimeout(this[_idleTimeoutTimeout]);
if (prevState === OPEN) {
try {
await core.opAsync(
"op_ws_close",
this[_rid],
value.code,
value.reason,
);
} catch {
// ignore failures
}
}
const event = new CloseEvent("close", { const event = new CloseEvent("close", {
wasClean: true, wasClean: true,
code: value.code, code: value.code,
@ -487,6 +506,19 @@
}, (this[_idleTimeoutDuration] / 2) * 1000); }, (this[_idleTimeoutDuration] / 2) * 1000);
} }
} }
[SymbolFor("Deno.customInspect")](inspect) {
return `${this.constructor.name} ${
inspect({
url: this.url,
readyState: this.readyState,
extensions: this.extensions,
protocol: this.protocol,
binaryType: this.binaryType,
bufferedAmount: this.bufferedAmount,
})
}`;
}
} }
ObjectDefineProperties(WebSocket, { ObjectDefineProperties(WebSocket, {

View file

@ -136,6 +136,9 @@ impl WsStreamResource {
match res { match res {
Ok(()) => Ok(()), Ok(()) => Ok(()),
Err(Error::ConnectionClosed) => Ok(()), Err(Error::ConnectionClosed) => Ok(()),
Err(tokio_tungstenite::tungstenite::Error::Protocol(
tokio_tungstenite::tungstenite::error::ProtocolError::SendAfterClosing,
)) => Ok(()),
Err(err) => Err(err.into()), Err(err) => Err(err.into()),
} }
} }

View file

@ -4184,12 +4184,12 @@
"eventhandlers.any.worker.html?wss": true, "eventhandlers.any.worker.html?wss": true,
"referrer.any.html": true, "referrer.any.html": true,
"referrer.any.worker.html": true, "referrer.any.worker.html": true,
"Close-delayed.any.html": false, "Close-delayed.any.html": true,
"Close-delayed.any.html?wpt_flags=h2": false, "Close-delayed.any.html?wpt_flags=h2": false,
"Close-delayed.any.html?wss": false, "Close-delayed.any.html?wss": true,
"Close-delayed.any.worker.html": false, "Close-delayed.any.worker.html": true,
"Close-delayed.any.worker.html?wpt_flags=h2": false, "Close-delayed.any.worker.html?wpt_flags=h2": false,
"Close-delayed.any.worker.html?wss": false, "Close-delayed.any.worker.html?wss": true,
"stream": { "stream": {
"tentative": { "tentative": {
"abort.any.html?wss": true, "abort.any.html?wss": true,