script/dom/stream/
readablestreamgenericreader.rs1use std::rc::Rc;
6
7use js::context::JSContext;
8use js::jsval::UndefinedValue;
9use js::rust::HandleValue as SafeHandleValue;
10
11use super::readablestream::ReaderType;
12use crate::dom::bindings::error::{Error, ErrorToJsval, Fallible};
13use crate::dom::bindings::reflector::DomGlobal;
14use crate::dom::bindings::root::{DomRoot, MutNullableDom};
15use crate::dom::globalscope::GlobalScope;
16use crate::dom::promise::Promise;
17use crate::dom::stream::readablestreambyobreader::ReadableStreamBYOBReader;
18use crate::dom::stream::readablestreamdefaultreader::ReadableStreamDefaultReader;
19use crate::dom::types::ReadableStream;
20use crate::script_runtime::CanGc;
21
22pub(crate) trait ReadableStreamGenericReader {
24 #[cfg_attr(crown, expect(crown::unrooted_must_root))]
26 fn generic_initialize(
27 &self,
28 cx: &mut JSContext,
29 global: &GlobalScope,
30 stream: &ReadableStream,
31 ) {
32 self.set_stream(Some(stream));
34
35 let reader_type = if let Some(default_reader) = self.as_default_reader() {
37 ReaderType::Default(MutNullableDom::new(Some(default_reader)))
38 } else if let Some(byob_reader) = self.as_byob_reader() {
39 ReaderType::BYOB(MutNullableDom::new(Some(byob_reader)))
40 } else {
41 unreachable!("Reader must be either Default or BYOB.");
42 };
43 stream.set_reader(Some(reader_type));
44
45 if stream.is_readable() {
46 self.set_closed_promise(Promise::new2(cx, global));
49 } else if stream.is_closed() {
50 self.set_closed_promise(Promise::new_resolved(
53 global,
54 cx.into(),
55 (),
56 CanGc::from_cx(cx),
57 ));
58 } else {
59 assert!(stream.is_errored());
61
62 rooted!(&in(cx) let mut error = UndefinedValue());
64 stream.get_stored_error(error.handle_mut());
65 self.set_closed_promise(Promise::new_rejected(cx, global, error.handle()));
66
67 self.get_closed_promise().set_promise_is_handled();
69 }
70 }
71
72 fn reader_generic_cancel(
74 &self,
75 cx: &mut JSContext,
76 global: &GlobalScope,
77 reason: SafeHandleValue,
78 ) -> Rc<Promise> {
79 let stream = self.get_stream();
81
82 let stream =
84 stream.expect("Reader should have a stream when generic cancel is called into.");
85
86 stream.cancel(cx, global, reason)
88 }
89
90 fn generic_release(&self, cx: &mut JSContext) -> Fallible<()> {
92 assert!(self.get_stream().is_some());
96
97 if let Some(stream) = self.get_stream() {
98 if self.as_default_reader().is_some() {
100 assert!(stream.has_default_reader());
101 } else {
102 assert!(stream.has_byob_reader());
103 }
104
105 if stream.is_readable() {
106 self.get_closed_promise().reject_error_with_cx(
108 cx,
109 Error::Type(c"stream state is not readable".to_owned()),
110 );
111 } else {
112 rooted!(&in(cx) let mut error = UndefinedValue());
114 Error::Type(c"Cannot release lock due to stream state.".to_owned()).to_jsval(
115 cx.into(),
116 &stream.global(),
117 error.handle_mut(),
118 CanGc::from_cx(cx),
119 );
120
121 self.set_closed_promise(Promise::new_rejected(
122 cx,
123 &stream.global(),
124 error.handle(),
125 ));
126 }
127 self.get_closed_promise().set_promise_is_handled();
129
130 stream
132 .perform_release_steps()
133 .expect("Stream should have a controller");
134
135 stream.set_reader(None);
137 self.set_stream(None);
139 }
140 Ok(())
141 }
142
143 fn closed(&self) -> Rc<Promise> {
145 self.get_closed_promise()
146 }
147
148 fn generic_cancel(
150 &self,
151 cx: &mut JSContext,
152 global: &GlobalScope,
153 reason: SafeHandleValue,
154 ) -> Rc<Promise> {
155 if self.get_stream().is_none() {
156 let promise = Promise::new2(cx, global);
159 promise.reject_error_with_cx(cx, Error::Type(c"stream is undefined".to_owned()));
160 promise
161 } else {
162 self.reader_generic_cancel(cx, global, reason)
164 }
165 }
166
167 fn set_stream(&self, stream: Option<&ReadableStream>);
168
169 fn get_stream(&self) -> Option<DomRoot<ReadableStream>>;
170
171 fn set_closed_promise(&self, promise: Rc<Promise>);
172
173 fn get_closed_promise(&self) -> Rc<Promise>;
174
175 fn as_default_reader(&self) -> Option<&ReadableStreamDefaultReader> {
176 None
177 }
178
179 fn as_byob_reader(&self) -> Option<&ReadableStreamBYOBReader> {
180 None
181 }
182}