Skip to main content

script/dom/stream/
readablestreamgenericreader.rs

1/* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this
3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
4
5use 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
21/// <https://streams.spec.whatwg.org/#readablestreamgenericreader>
22pub(crate) trait ReadableStreamGenericReader {
23    /// <https://streams.spec.whatwg.org/#readable-stream-reader-generic-initialize>
24    #[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        // Set reader.[[stream]] to stream.
32        self.set_stream(Some(stream));
33
34        // Set stream.[[reader]] to reader.
35        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            // If stream.[[state]] is "readable
46            // Set reader.[[closedPromise]] to a new promise.
47            self.set_closed_promise(Promise::new(cx, global));
48        } else if stream.is_closed() {
49            // Otherwise, if stream.[[state]] is "closed",
50            // Set reader.[[closedPromise]] to a promise resolved with undefined.
51            self.set_closed_promise(Promise::new_resolved(cx, global, ()));
52        } else {
53            // Assert: stream.[[state]] is "errored"
54            assert!(stream.is_errored());
55
56            // Set reader.[[closedPromise]] to a promise rejected with stream.[[storedError]].
57            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            // Set reader.[[closedPromise]].[[PromiseIsHandled]] to true
62            self.get_closed_promise().set_promise_is_handled(cx);
63        }
64    }
65
66    /// <https://streams.spec.whatwg.org/#readable-stream-reader-generic-cancel>
67    fn reader_generic_cancel(
68        &self,
69        cx: &mut JSContext,
70        global: &GlobalScope,
71        reason: SafeHandleValue,
72    ) -> Rc<Promise> {
73        // Let stream be reader.[[stream]].
74        let stream = self.get_stream();
75
76        // Assert: stream is not undefined.
77        let stream =
78            stream.expect("Reader should have a stream when generic cancel is called into.");
79
80        // Return ! ReadableStreamCancel(stream, reason).
81        stream.cancel(cx, global, reason)
82    }
83
84    /// <https://streams.spec.whatwg.org/#readable-stream-reader-generic-release>
85    fn generic_release(&self, cx: &mut JSContext) -> Fallible<()> {
86        // Let stream be reader.[[stream]].
87
88        // Assert: stream is not undefined.
89        assert!(self.get_stream().is_some());
90
91        if let Some(stream) = self.get_stream() {
92            // Assert: stream.[[reader]] is reader.
93            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                // If stream.[[state]] is "readable", reject reader.[[closedPromise]] with a TypeError exception.
101                self.get_closed_promise()
102                    .reject_error(cx, Error::Type(c"stream state is not readable".to_owned()));
103            } else {
104                // Otherwise, set reader.[[closedPromise]] to a promise rejected with a TypeError exception.
105                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            // Set reader.[[closedPromise]].[[PromiseIsHandled]] to true.
119            self.get_closed_promise().set_promise_is_handled(cx);
120
121            // Perform ! stream.[[controller]].[[ReleaseSteps]]().
122            stream
123                .perform_release_steps()
124                .expect("Stream should have a controller");
125
126            // Set stream.[[reader]] to undefined.
127            stream.set_reader(None);
128            // Set reader.[[stream]] to undefined.
129            self.set_stream(None);
130        }
131        Ok(())
132    }
133
134    /// <https://streams.spec.whatwg.org/#generic-reader-closed>
135    fn closed(&self) -> Rc<Promise> {
136        self.get_closed_promise()
137    }
138
139    // <https://streams.spec.whatwg.org/#generic-reader-cancel>
140    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            // If this.[[stream]] is undefined,
148            // return a promise rejected with a TypeError exception.
149            let promise = Promise::new(cx, global);
150            promise.reject_error(cx, Error::Type(c"stream is undefined".to_owned()));
151            promise
152        } else {
153            // Return ! ReadableStreamReaderGenericCancel(this, reason).
154            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}