This commit is contained in:
parent
0bb3f607c7
commit
92f1190b11
1 changed files with 30 additions and 1 deletions
|
|
@ -90,6 +90,19 @@ fn release_writer_lock(writer: &JsValue) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Release a `ReadableStreamDefaultReader`'s lock on its stream. Mirrors
|
||||||
|
/// `release_writer_lock`: abandoning a locked reader can be interpreted by the
|
||||||
|
/// runtime as a `reader.cancel()` (sending STOP_SENDING to the peer) even on an
|
||||||
|
/// already-closed or errored stream. Calling `releaseLock` explicitly avoids
|
||||||
|
/// that. Errors are ignored — best-effort cleanup.
|
||||||
|
fn release_reader_lock(reader: &JsValue) {
|
||||||
|
if let Ok(release) = js_sys::Reflect::get(reader, &JsValue::from_str("releaseLock"))
|
||||||
|
.and_then(|f| f.dyn_into::<js_sys::Function>().map_err(Into::into))
|
||||||
|
{
|
||||||
|
let _ = release.call0(reader);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Outcome of reading the next framed message from the incoming stream(s).
|
/// Outcome of reading the next framed message from the incoming stream(s).
|
||||||
enum FrameOutcome {
|
enum FrameOutcome {
|
||||||
/// A complete application frame.
|
/// A complete application frame.
|
||||||
|
|
@ -408,7 +421,12 @@ impl WasmTransport {
|
||||||
// Current stream finished; the next frame (if any) is on a
|
// Current stream finished; the next frame (if any) is on a
|
||||||
// subsequent stream. Any trailing partial bytes are dropped
|
// subsequent stream. Any trailing partial bytes are dropped
|
||||||
// since the host never splits a frame across streams.
|
// since the host never splits a frame across streams.
|
||||||
*self.stream_reader.borrow_mut() = None;
|
// Release the reader's lock explicitly so the runtime does
|
||||||
|
// not treat the abandoned lock as a cancel (which would send
|
||||||
|
// STOP_SENDING to the peer on an already-closed stream).
|
||||||
|
if let Some(reader) = self.stream_reader.borrow_mut().take() {
|
||||||
|
release_reader_lock(&reader);
|
||||||
|
}
|
||||||
self.buffer.borrow_mut().clear();
|
self.buffer.borrow_mut().clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -452,6 +470,17 @@ impl WasmTransport {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn close(&self) {
|
pub fn close(&self) {
|
||||||
|
// Release any held reader locks before tearing down the session, so the
|
||||||
|
// runtime does not interpret an abandoned locked reader as a cancel
|
||||||
|
// (which would send STOP_SENDING to the peer). Once the locks are
|
||||||
|
// released the underlying streams can be torn down cleanly.
|
||||||
|
if let Some(reader) = self.stream_reader.borrow_mut().take() {
|
||||||
|
release_reader_lock(&reader);
|
||||||
|
}
|
||||||
|
if let Some(reader) = self.streams_reader.borrow_mut().take() {
|
||||||
|
release_reader_lock(&reader);
|
||||||
|
}
|
||||||
|
|
||||||
if let Ok(close) = js_sys::Reflect::get(&self.inner, &JsValue::from_str("close"))
|
if let Ok(close) = js_sys::Reflect::get(&self.inner, &JsValue::from_str("close"))
|
||||||
.and_then(|value| value.dyn_into::<js_sys::Function>().map_err(Into::into))
|
.and_then(|value| value.dyn_into::<js_sys::Function>().map_err(Into::into))
|
||||||
{
|
{
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue