mirror of
https://github.com/servo/servo.git
synced 2025-06-06 16:45:39 +00:00
Part of https://github.com/servo/servo/issues/34676 --------- Signed-off-by: Taym Haddadi <haddadi.taym@gmail.com> Signed-off-by: gterzian <2792687+gterzian@users.noreply.github.com> Signed-off-by: Taym <haddadi.taym@gmail.com> Co-authored-by: gterzian <2792687+gterzian@users.noreply.github.com>
175 lines
6.7 KiB
Rust
175 lines
6.7 KiB
Rust
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
|
|
use std::rc::Rc;
|
|
|
|
use js::jsval::UndefinedValue;
|
|
use js::rust::HandleValue as SafeHandleValue;
|
|
|
|
use super::readablestream::ReaderType;
|
|
use super::types::ReadableStream;
|
|
use crate::dom::bindings::error::{Error, ErrorToJsval, Fallible};
|
|
use crate::dom::bindings::reflector::DomGlobal;
|
|
use crate::dom::bindings::root::{DomRoot, MutNullableDom};
|
|
use crate::dom::globalscope::GlobalScope;
|
|
use crate::dom::promise::Promise;
|
|
use crate::dom::readablestreambyobreader::ReadableStreamBYOBReader;
|
|
use crate::dom::readablestreamdefaultreader::ReadableStreamDefaultReader;
|
|
use crate::script_runtime::{CanGc, JSContext as SafeJSContext};
|
|
|
|
/// <https://streams.spec.whatwg.org/#readablestreamgenericreader>
|
|
pub(crate) trait ReadableStreamGenericReader {
|
|
/// <https://streams.spec.whatwg.org/#readable-stream-reader-generic-initialize>
|
|
#[cfg_attr(crown, allow(crown::unrooted_must_root))]
|
|
fn generic_initialize(&self, global: &GlobalScope, stream: &ReadableStream, can_gc: CanGc) {
|
|
// Set reader.[[stream]] to stream.
|
|
self.set_stream(Some(stream));
|
|
|
|
// Set stream.[[reader]] to reader.
|
|
let reader_type = if let Some(default_reader) = self.as_default_reader() {
|
|
ReaderType::Default(MutNullableDom::new(Some(default_reader)))
|
|
} else if let Some(byob_reader) = self.as_byob_reader() {
|
|
ReaderType::BYOB(MutNullableDom::new(Some(byob_reader)))
|
|
} else {
|
|
unreachable!("Reader must be either Default or BYOB.");
|
|
};
|
|
stream.set_reader(Some(reader_type));
|
|
|
|
if stream.is_readable() {
|
|
// If stream.[[state]] is "readable
|
|
// Set reader.[[closedPromise]] to a new promise.
|
|
self.set_closed_promise(Promise::new(global, can_gc));
|
|
} else if stream.is_closed() {
|
|
// Otherwise, if stream.[[state]] is "closed",
|
|
// Set reader.[[closedPromise]] to a promise resolved with undefined.
|
|
let cx = GlobalScope::get_cx();
|
|
self.set_closed_promise(Promise::new_resolved(global, cx, (), can_gc));
|
|
} else {
|
|
// Assert: stream.[[state]] is "errored"
|
|
assert!(stream.is_errored());
|
|
|
|
// Set reader.[[closedPromise]] to a promise rejected with stream.[[storedError]].
|
|
let cx = GlobalScope::get_cx();
|
|
rooted!(in(*cx) let mut error = UndefinedValue());
|
|
stream.get_stored_error(error.handle_mut());
|
|
self.set_closed_promise(Promise::new_rejected(global, cx, error.handle(), can_gc));
|
|
|
|
// Set reader.[[closedPromise]].[[PromiseIsHandled]] to true
|
|
self.get_closed_promise().set_promise_is_handled();
|
|
}
|
|
}
|
|
|
|
/// <https://streams.spec.whatwg.org/#readable-stream-reader-generic-cancel>
|
|
fn reader_generic_cancel(
|
|
&self,
|
|
cx: SafeJSContext,
|
|
global: &GlobalScope,
|
|
reason: SafeHandleValue,
|
|
can_gc: CanGc,
|
|
) -> Rc<Promise> {
|
|
// Let stream be reader.[[stream]].
|
|
let stream = self.get_stream();
|
|
|
|
// Assert: stream is not undefined.
|
|
let stream =
|
|
stream.expect("Reader should have a stream when generic cancel is called into.");
|
|
|
|
// Return ! ReadableStreamCancel(stream, reason).
|
|
stream.cancel(cx, global, reason, can_gc)
|
|
}
|
|
|
|
/// <https://streams.spec.whatwg.org/#readable-stream-reader-generic-release>
|
|
fn generic_release(&self, can_gc: CanGc) -> Fallible<()> {
|
|
// Let stream be reader.[[stream]].
|
|
|
|
// Assert: stream is not undefined.
|
|
assert!(self.get_stream().is_some());
|
|
|
|
if let Some(stream) = self.get_stream() {
|
|
// Assert: stream.[[reader]] is reader.
|
|
if self.as_default_reader().is_some() {
|
|
assert!(stream.has_default_reader());
|
|
} else {
|
|
assert!(stream.has_byob_reader());
|
|
}
|
|
|
|
if stream.is_readable() {
|
|
// If stream.[[state]] is "readable", reject reader.[[closedPromise]] with a TypeError exception.
|
|
self.get_closed_promise().reject_error(
|
|
Error::Type("stream state is not readable".to_owned()),
|
|
can_gc,
|
|
);
|
|
} else {
|
|
// Otherwise, set reader.[[closedPromise]] to a promise rejected with a TypeError exception.
|
|
let cx = GlobalScope::get_cx();
|
|
rooted!(in(*cx) let mut error = UndefinedValue());
|
|
Error::Type("Cannot release lock due to stream state.".to_owned()).to_jsval(
|
|
cx,
|
|
&stream.global(),
|
|
error.handle_mut(),
|
|
can_gc,
|
|
);
|
|
|
|
self.set_closed_promise(Promise::new_rejected(
|
|
&stream.global(),
|
|
cx,
|
|
error.handle(),
|
|
can_gc,
|
|
));
|
|
}
|
|
// Set reader.[[closedPromise]].[[PromiseIsHandled]] to true.
|
|
self.get_closed_promise().set_promise_is_handled();
|
|
|
|
// Perform ! stream.[[controller]].[[ReleaseSteps]]().
|
|
stream.perform_release_steps()?;
|
|
|
|
// Set stream.[[reader]] to undefined.
|
|
stream.set_reader(None);
|
|
// Set reader.[[stream]] to undefined.
|
|
self.set_stream(None);
|
|
}
|
|
Ok(())
|
|
}
|
|
|
|
/// <https://streams.spec.whatwg.org/#generic-reader-closed>
|
|
fn closed(&self) -> Rc<Promise> {
|
|
self.get_closed_promise()
|
|
}
|
|
|
|
// <https://streams.spec.whatwg.org/#generic-reader-cancel>
|
|
fn generic_cancel(
|
|
&self,
|
|
cx: SafeJSContext,
|
|
global: &GlobalScope,
|
|
reason: SafeHandleValue,
|
|
can_gc: CanGc,
|
|
) -> Rc<Promise> {
|
|
if self.get_stream().is_none() {
|
|
// If this.[[stream]] is undefined,
|
|
// return a promise rejected with a TypeError exception.
|
|
let promise = Promise::new(global, can_gc);
|
|
promise.reject_error(Error::Type("stream is undefined".to_owned()), can_gc);
|
|
promise
|
|
} else {
|
|
// Return ! ReadableStreamReaderGenericCancel(this, reason).
|
|
self.reader_generic_cancel(cx, global, reason, can_gc)
|
|
}
|
|
}
|
|
|
|
fn set_stream(&self, stream: Option<&ReadableStream>);
|
|
|
|
fn get_stream(&self) -> Option<DomRoot<ReadableStream>>;
|
|
|
|
fn set_closed_promise(&self, promise: Rc<Promise>);
|
|
|
|
fn get_closed_promise(&self) -> Rc<Promise>;
|
|
|
|
fn as_default_reader(&self) -> Option<&ReadableStreamDefaultReader> {
|
|
None
|
|
}
|
|
|
|
fn as_byob_reader(&self) -> Option<&ReadableStreamBYOBReader> {
|
|
None
|
|
}
|
|
}
|