mirror of
https://github.com/denoland/deno.git
synced 2024-11-21 15:04:11 -05:00
fix(ext/websocket): WebSocket dispatch single close event (#13443)
This commit is contained in:
parent
d55444b41c
commit
3c97bbe165
5 changed files with 62 additions and 39 deletions
|
@ -738,10 +738,12 @@ fn websocket_server_multi_field_connection_header() {
|
|||
.uri("ws://localhost:4319")
|
||||
.body(())
|
||||
.unwrap();
|
||||
assert!(
|
||||
let (mut socket, _) =
|
||||
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());
|
||||
}
|
||||
|
||||
|
|
|
@ -357,32 +357,18 @@
|
|||
|
||||
httpConn.close();
|
||||
|
||||
if (ws[_readyState] === WebSocket.CLOSING) {
|
||||
await core.opAsync("op_ws_close", wsRid);
|
||||
ws[_readyState] = WebSocket.OPEN;
|
||||
const event = new Event("open");
|
||||
ws.dispatchEvent(event);
|
||||
|
||||
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;
|
||||
const event = new Event("open");
|
||||
ws.dispatchEvent(event);
|
||||
|
||||
ws[_eventLoop]();
|
||||
if (ws[_idleTimeoutDuration]) {
|
||||
ws.addEventListener(
|
||||
"close",
|
||||
() => clearTimeout(ws[_idleTimeoutTimeout]),
|
||||
);
|
||||
}
|
||||
ws[_serverHandleIdleTimeout]();
|
||||
ws[_eventLoop]();
|
||||
if (ws[_idleTimeoutDuration]) {
|
||||
ws.addEventListener(
|
||||
"close",
|
||||
() => clearTimeout(ws[_idleTimeoutTimeout]),
|
||||
);
|
||||
}
|
||||
ws[_serverHandleIdleTimeout]();
|
||||
}
|
||||
} finally {
|
||||
if (SetPrototypeDelete(httpConn.managedResources, streamRid)) {
|
||||
|
|
|
@ -29,6 +29,8 @@
|
|||
StringPrototypeToLowerCase,
|
||||
Symbol,
|
||||
SymbolIterator,
|
||||
PromisePrototypeCatch,
|
||||
SymbolFor,
|
||||
} = window.__bootstrap.primordials;
|
||||
|
||||
webidl.converters["sequence<DOMString> or DOMString"] = (V, opts) => {
|
||||
|
@ -367,16 +369,19 @@
|
|||
} else if (this[_readyState] === OPEN) {
|
||||
this[_readyState] = CLOSING;
|
||||
|
||||
PromisePrototypeThen(
|
||||
PromisePrototypeCatch(
|
||||
core.opAsync("op_ws_close", this[_rid], code, reason),
|
||||
() => {
|
||||
(err) => {
|
||||
this[_readyState] = CLOSED;
|
||||
const event = new CloseEvent("close", {
|
||||
wasClean: true,
|
||||
code: code ?? 1005,
|
||||
reason,
|
||||
|
||||
const errorEv = new ErrorEvent("error", {
|
||||
error: err,
|
||||
message: ErrorPrototypeToString(err),
|
||||
});
|
||||
this.dispatchEvent(event);
|
||||
this.dispatchEvent(errorEv);
|
||||
|
||||
const closeEv = new CloseEvent("close");
|
||||
this.dispatchEvent(closeEv);
|
||||
core.tryClose(this[_rid]);
|
||||
},
|
||||
);
|
||||
|
@ -384,7 +389,7 @@
|
|||
}
|
||||
|
||||
async [_eventLoop]() {
|
||||
while (this[_readyState] === OPEN) {
|
||||
while (this[_readyState] !== CLOSED) {
|
||||
const { kind, value } = await core.opAsync(
|
||||
"op_ws_next_event",
|
||||
this[_rid],
|
||||
|
@ -429,9 +434,23 @@
|
|||
}
|
||||
case "closed":
|
||||
case "close": {
|
||||
const prevState = this[_readyState];
|
||||
this[_readyState] = CLOSED;
|
||||
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", {
|
||||
wasClean: true,
|
||||
code: value.code,
|
||||
|
@ -487,6 +506,19 @@
|
|||
}, (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, {
|
||||
|
|
|
@ -136,6 +136,9 @@ impl WsStreamResource {
|
|||
match res {
|
||||
Ok(()) => Ok(()),
|
||||
Err(Error::ConnectionClosed) => Ok(()),
|
||||
Err(tokio_tungstenite::tungstenite::Error::Protocol(
|
||||
tokio_tungstenite::tungstenite::error::ProtocolError::SendAfterClosing,
|
||||
)) => Ok(()),
|
||||
Err(err) => Err(err.into()),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4184,12 +4184,12 @@
|
|||
"eventhandlers.any.worker.html?wss": true,
|
||||
"referrer.any.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?wss": false,
|
||||
"Close-delayed.any.worker.html": false,
|
||||
"Close-delayed.any.html?wss": true,
|
||||
"Close-delayed.any.worker.html": true,
|
||||
"Close-delayed.any.worker.html?wpt_flags=h2": false,
|
||||
"Close-delayed.any.worker.html?wss": false,
|
||||
"Close-delayed.any.worker.html?wss": true,
|
||||
"stream": {
|
||||
"tentative": {
|
||||
"abort.any.html?wss": true,
|
||||
|
|
Loading…
Reference in a new issue