script/dom/
readablestreamgenericreader.rs1use std::rc::Rc;
6
7use js::jsval::UndefinedValue;
8use js::rust::HandleValue as SafeHandleValue;
9
10use super::readablestream::ReaderType;
11use super::types::ReadableStream;
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::readablestreambyobreader::ReadableStreamBYOBReader;
18use crate::dom::readablestreamdefaultreader::ReadableStreamDefaultReader;
19use crate::script_runtime::{CanGc, JSContext as SafeJSContext};
20
21pub(crate) trait ReadableStreamGenericReader {
23 #[cfg_attr(crown, allow(crown::unrooted_must_root))]
25 fn generic_initialize(&self, global: &GlobalScope, stream: &ReadableStream, can_gc: CanGc) {
26 self.set_stream(Some(stream));
28
29 let reader_type = if let Some(default_reader) = self.as_default_reader() {
31 ReaderType::Default(MutNullableDom::new(Some(default_reader)))
32 } else if let Some(byob_reader) = self.as_byob_reader() {
33 ReaderType::BYOB(MutNullableDom::new(Some(byob_reader)))
34 } else {
35 unreachable!("Reader must be either Default or BYOB.");
36 };
37 stream.set_reader(Some(reader_type));
38
39 if stream.is_readable() {
40 self.set_closed_promise(Promise::new(global, can_gc));
43 } else if stream.is_closed() {
44 let cx = GlobalScope::get_cx();
47 self.set_closed_promise(Promise::new_resolved(global, cx, (), can_gc));
48 } else {
49 assert!(stream.is_errored());
51
52 let cx = GlobalScope::get_cx();
54 rooted!(in(*cx) let mut error = UndefinedValue());
55 stream.get_stored_error(error.handle_mut());
56 self.set_closed_promise(Promise::new_rejected(global, cx, error.handle(), can_gc));
57
58 self.get_closed_promise().set_promise_is_handled();
60 }
61 }
62
63 fn reader_generic_cancel(
65 &self,
66 cx: SafeJSContext,
67 global: &GlobalScope,
68 reason: SafeHandleValue,
69 can_gc: CanGc,
70 ) -> Rc<Promise> {
71 let stream = self.get_stream();
73
74 let stream =
76 stream.expect("Reader should have a stream when generic cancel is called into.");
77
78 stream.cancel(cx, global, reason, can_gc)
80 }
81
82 fn generic_release(&self, can_gc: CanGc) -> Fallible<()> {
84 assert!(self.get_stream().is_some());
88
89 if let Some(stream) = self.get_stream() {
90 if self.as_default_reader().is_some() {
92 assert!(stream.has_default_reader());
93 } else {
94 assert!(stream.has_byob_reader());
95 }
96
97 if stream.is_readable() {
98 self.get_closed_promise().reject_error(
100 Error::Type("stream state is not readable".to_owned()),
101 can_gc,
102 );
103 } else {
104 let cx = GlobalScope::get_cx();
106 rooted!(in(*cx) let mut error = UndefinedValue());
107 Error::Type("Cannot release lock due to stream state.".to_owned()).to_jsval(
108 cx,
109 &stream.global(),
110 error.handle_mut(),
111 can_gc,
112 );
113
114 self.set_closed_promise(Promise::new_rejected(
115 &stream.global(),
116 cx,
117 error.handle(),
118 can_gc,
119 ));
120 }
121 self.get_closed_promise().set_promise_is_handled();
123
124 stream.perform_release_steps()?;
126
127 stream.set_reader(None);
129 self.set_stream(None);
131 }
132 Ok(())
133 }
134
135 fn closed(&self) -> Rc<Promise> {
137 self.get_closed_promise()
138 }
139
140 fn generic_cancel(
142 &self,
143 cx: SafeJSContext,
144 global: &GlobalScope,
145 reason: SafeHandleValue,
146 can_gc: CanGc,
147 ) -> Rc<Promise> {
148 if self.get_stream().is_none() {
149 let promise = Promise::new(global, can_gc);
152 promise.reject_error(Error::Type("stream is undefined".to_owned()), can_gc);
153 promise
154 } else {
155 self.reader_generic_cancel(cx, global, reason, can_gc)
157 }
158 }
159
160 fn set_stream(&self, stream: Option<&ReadableStream>);
161
162 fn get_stream(&self) -> Option<DomRoot<ReadableStream>>;
163
164 fn set_closed_promise(&self, promise: Rc<Promise>);
165
166 fn get_closed_promise(&self) -> Rc<Promise>;
167
168 fn as_default_reader(&self) -> Option<&ReadableStreamDefaultReader> {
169 None
170 }
171
172 fn as_byob_reader(&self) -> Option<&ReadableStreamBYOBReader> {
173 None
174 }
175}