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;
20
21pub(crate) trait ReadableStreamGenericReader {
23 #[cfg_attr(crown, expect(crown::unrooted_must_root))]
25 fn generic_initialize(
26 &self,
27 cx: &mut JSContext,
28 global: &GlobalScope,
29 stream: &ReadableStream,
30 ) {
31 self.set_stream(Some(stream));
33
34 let reader_type = if let Some(default_reader) = self.as_default_reader() {
36 ReaderType::Default(MutNullableDom::new(Some(default_reader)))
37 } else if let Some(byob_reader) = self.as_byob_reader() {
38 ReaderType::BYOB(MutNullableDom::new(Some(byob_reader)))
39 } else {
40 unreachable!("Reader must be either Default or BYOB.");
41 };
42 stream.set_reader(Some(reader_type));
43
44 if stream.is_readable() {
45 self.set_closed_promise(Promise::new(cx, global));
48 } else if stream.is_closed() {
49 self.set_closed_promise(Promise::new_resolved(cx, global, ()));
52 } else {
53 assert!(stream.is_errored());
55
56 rooted!(&in(cx) let mut error = UndefinedValue());
58 stream.get_stored_error(error.handle_mut());
59 self.set_closed_promise(Promise::new_rejected(cx, global, error.handle()));
60
61 self.get_closed_promise().set_promise_is_handled(cx);
63 }
64 }
65
66 fn reader_generic_cancel(
68 &self,
69 cx: &mut JSContext,
70 global: &GlobalScope,
71 reason: SafeHandleValue,
72 ) -> Rc<Promise> {
73 let stream = self.get_stream();
75
76 let stream =
78 stream.expect("Reader should have a stream when generic cancel is called into.");
79
80 stream.cancel(cx, global, reason)
82 }
83
84 fn generic_release(&self, cx: &mut JSContext) -> Fallible<()> {
86 assert!(self.get_stream().is_some());
90
91 if let Some(stream) = self.get_stream() {
92 if self.as_default_reader().is_some() {
94 assert!(stream.has_default_reader());
95 } else {
96 assert!(stream.has_byob_reader());
97 }
98
99 if stream.is_readable() {
100 self.get_closed_promise()
102 .reject_error(cx, Error::Type(c"stream state is not readable".to_owned()));
103 } else {
104 rooted!(&in(cx) let mut error = UndefinedValue());
106 Error::Type(c"Cannot release lock due to stream state.".to_owned()).to_jsval(
107 cx,
108 &stream.global(),
109 error.handle_mut(),
110 );
111
112 self.set_closed_promise(Promise::new_rejected(
113 cx,
114 &stream.global(),
115 error.handle(),
116 ));
117 }
118 self.get_closed_promise().set_promise_is_handled(cx);
120
121 stream
123 .perform_release_steps()
124 .expect("Stream should have a controller");
125
126 stream.set_reader(None);
128 self.set_stream(None);
130 }
131 Ok(())
132 }
133
134 fn closed(&self) -> Rc<Promise> {
136 self.get_closed_promise()
137 }
138
139 fn generic_cancel(
141 &self,
142 cx: &mut JSContext,
143 global: &GlobalScope,
144 reason: SafeHandleValue,
145 ) -> Rc<Promise> {
146 if self.get_stream().is_none() {
147 let promise = Promise::new(cx, global);
150 promise.reject_error(cx, Error::Type(c"stream is undefined".to_owned()));
151 promise
152 } else {
153 self.reader_generic_cancel(cx, global, reason)
155 }
156 }
157
158 fn set_stream(&self, stream: Option<&ReadableStream>);
159
160 fn get_stream(&self) -> Option<DomRoot<ReadableStream>>;
161
162 fn set_closed_promise(&self, promise: Rc<Promise>);
163
164 fn get_closed_promise(&self) -> Rc<Promise>;
165
166 fn as_default_reader(&self) -> Option<&ReadableStreamDefaultReader> {
167 None
168 }
169
170 fn as_byob_reader(&self) -> Option<&ReadableStreamBYOBReader> {
171 None
172 }
173}