1#![cfg_attr(crown, allow(crown::jscontext_first_arg))]
6
7use std::cell::{Cell, RefCell};
8use std::collections::VecDeque;
9use std::ptr::{self};
10use std::rc::Rc;
11
12use dom_struct::dom_struct;
13use js::context::JSContext;
14use js::conversions::ToJSValConvertible;
15use js::jsapi::{Heap, JSObject};
16use js::jsval::{JSVal, ObjectValue, UndefinedValue};
17use js::realm::CurrentRealm;
18use js::rust::{
19 HandleObject as SafeHandleObject, HandleValue as SafeHandleValue,
20 MutableHandleValue as SafeMutableHandleValue,
21};
22use js::typedarray::{ArrayBufferViewU8, Uint8};
23use rustc_hash::FxHashMap;
24use servo_base::generic_channel::GenericSharedMemory;
25use servo_base::id::{MessagePortId, MessagePortIndex};
26use servo_constellation_traits::MessagePortImpl;
27
28use crate::dom::bindings::codegen::Bindings::QueuingStrategyBinding::QueuingStrategy;
29use crate::dom::bindings::codegen::Bindings::ReadableStreamBinding::{
30 ReadableStreamGetReaderOptions, ReadableStreamMethods, ReadableStreamReaderMode,
31 ReadableWritablePair, StreamPipeOptions,
32};
33use script_bindings::str::DOMString;
34use crate::dom::domexception::{DOMErrorName, DOMException};
35use crate::dom::encoding::textdecoderstream::TextDecoderStream;
36use script_bindings::codegen::GenericBindings::TextDecoderStreamBinding::TextDecoderStreamMethods;
37use script_bindings::conversions::{is_array_like, StringificationBehavior};
38use crate::dom::bindings::callback::RootedCallback;
39use crate::dom::bindings::codegen::Bindings::QueuingStrategyBinding::QueuingStrategySize;
40use crate::dom::abortsignal::{AbortAlgorithm, AbortSignal};
41use crate::dom::bindings::codegen::Bindings::ReadableStreamDefaultReaderBinding::ReadableStreamDefaultReaderMethods;
42use crate::dom::bindings::codegen::Bindings::ReadableStreamDefaultControllerBinding::ReadableStreamDefaultController_Binding::ReadableStreamDefaultControllerMethods;
43use crate::dom::bindings::codegen::Bindings::UnderlyingSourceBinding::UnderlyingSource as JsUnderlyingSource;
44use crate::dom::bindings::conversions::{ConversionBehavior, ConversionResult, get_property, get_property_jsval};
45use crate::dom::bindings::error::{Error, ErrorToJsval, Fallible};
46use crate::dom::bindings::codegen::GenericBindings::WritableStreamDefaultWriterBinding::WritableStreamDefaultWriter_Binding::WritableStreamDefaultWriterMethods;
47use crate::dom::stream::writablestream::WritableStream;
48use crate::dom::bindings::codegen::UnionTypes::ReadableStreamDefaultReaderOrReadableStreamBYOBReader as ReadableStreamReader;
49use crate::dom::bindings::reflector::DomGlobal;
50use script_bindings::reflector::{Reflector, reflect_dom_object_with_proto};
51use crate::dom::bindings::root::{DomRoot, MutNullableDom, Dom};
52use crate::dom::bindings::trace::RootedTraceableBox;
53use crate::dom::stream::byteteeunderlyingsource::{ByteTeeCancelAlgorithm, ByteTeePullAlgorithm, ByteTeeUnderlyingSource};
54use crate::dom::stream::countqueuingstrategy::{extract_high_water_mark, extract_size_algorithm};
55use crate::dom::stream::readablestreamgenericreader::ReadableStreamGenericReader;
56use crate::dom::globalscope::GlobalScope;
57use crate::dom::promise::{wait_for_all_promise, Promise, RootedPromise, TracedPromise};
58use crate::dom::stream::readablebytestreamcontroller::ReadableByteStreamController;
59use crate::dom::stream::readablestreambyobreader::ReadableStreamBYOBReader;
60use crate::dom::stream::readablestreamdefaultcontroller::ReadableStreamDefaultController;
61use crate::dom::stream::readablestreamdefaultreader::{ReadRequest, ReadableStreamDefaultReader};
62use crate::dom::stream::defaultteeunderlyingsource::DefaultTeeCancelAlgorithm;
63use crate::dom::types::DefaultTeeUnderlyingSource;
64use crate::dom::stream::underlyingsourcecontainer::UnderlyingSourceType;
65use crate::dom::stream::writablestreamdefaultwriter::WritableStreamDefaultWriter;
66use script_bindings::codegen::GenericBindings::MessagePortBinding::MessagePortMethods;
67use crate::dom::messageport::MessagePort;
68use crate::realms::{enter_auto_realm};
69use crate::dom::promisenativehandler::{Callback, PromiseNativeHandler};
70use crate::dom::bindings::transferable::Transferable;
71use script_bindings::structuredclone::StructuredData;
72
73use super::readablestreambyobreader::ReadIntoRequest;
74use crate::dom::bindings::buffer_source::{HeapBufferSource, create_buffer_source};
75
76#[derive(Clone, Debug, Default, MallocSizeOf, PartialEq)]
78enum PipeToState {
79 #[default]
81 Starting,
82 PendingReady,
84 PendingRead,
86 ShuttingDownWithPendingWrites(Option<ShutdownAction>),
89 ShuttingDownPendingAction,
93 Finalized,
96}
97
98#[derive(Clone, Debug, MallocSizeOf, PartialEq)]
100enum ShutdownAction {
101 WritableStreamAbort,
103 ReadableStreamCancel,
105 WritableStreamDefaultWriterCloseWithErrorPropagation,
107 Abort,
109}
110
111impl js::gc::Rootable for PipeTo {}
112
113#[derive(Clone, JSTraceable, MallocSizeOf)]
122#[cfg_attr(crown, crown::unrooted_must_root_lint::must_root)]
123pub(crate) struct PipeTo {
124 reader: Dom<ReadableStreamDefaultReader>,
126
127 writer: Dom<WritableStreamDefaultWriter>,
129
130 #[ignore_malloc_size_of = "nested Rc"]
133 pending_writes: Rc<RefCell<VecDeque<TracedPromise>>>,
134
135 #[conditional_malloc_size_of]
137 #[no_trace]
138 state: Rc<RefCell<PipeToState>>,
139
140 prevent_abort: bool,
142
143 prevent_cancel: bool,
145
146 prevent_close: bool,
148
149 #[conditional_malloc_size_of]
152 shutting_down: Rc<Cell<bool>>,
153
154 #[ignore_malloc_size_of = "mozjs"]
157 abort_reason: Rc<Heap<JSVal>>,
158
159 #[ignore_malloc_size_of = "mozjs"]
162 shutdown_error: Rc<RefCell<Option<Heap<JSVal>>>>,
163
164 #[conditional_malloc_size_of]
167 shutdown_action_promise: Rc<RefCell<Option<TracedPromise>>>,
168
169 result_promise: TracedPromise,
172}
173
174impl PipeTo {
175 pub(crate) fn abort_with_reason(
178 &self,
179 cx: &mut CurrentRealm,
180 global: &GlobalScope,
181 reason: SafeHandleValue,
182 ) {
183 if self.shutting_down.get() {
185 return;
186 }
187
188 self.abort_reason.set(reason.get());
192
193 self.set_shutdown_error(reason);
198
199 self.shutdown(cx, global, Some(ShutdownAction::Abort));
205 }
206}
207
208impl Callback for PipeTo {
209 fn callback(&self, cx: &mut CurrentRealm, result: SafeHandleValue) {
218 let global = self.reader.global();
219
220 self.pending_writes.borrow_mut().retain(|p| {
226 let pending = p.is_pending();
227 if !pending {
228 p.set_promise_is_handled(cx);
229 }
230 pending
231 });
232
233 let state_before_checks = self.state.borrow().clone();
235
236 if state_before_checks == PipeToState::PendingRead {
243 let source = self.reader.get_stream().expect("Source stream must be set");
244 if source.is_closed() {
245 let dest = self
246 .writer
247 .get_stream()
248 .expect("Destination stream must be set");
249
250 if dest.is_writable() && !dest.close_queued_or_in_flight() {
253 let Ok(done) = get_read_promise_done(cx, &result) else {
254 return;
261 };
262
263 if !done {
264 self.write_chunk(cx, &global, result);
266 }
267 }
268 }
269 }
270
271 self.check_and_propagate_errors_forward(cx, &global);
272 self.check_and_propagate_errors_backward(cx, &global);
273 self.check_and_propagate_closing_forward(cx, &global);
274 self.check_and_propagate_closing_backward(cx, &global);
275
276 let state = self.state.borrow().clone();
278
279 if state != state_before_checks {
283 return;
284 }
285
286 match state {
287 PipeToState::Starting => unreachable!("PipeTo should not be in the Starting state."),
288 PipeToState::PendingReady => {
289 self.read_chunk(cx, &global);
291 },
292 PipeToState::PendingRead => {
293 self.write_chunk(cx, &global, result);
295
296 if self.shutting_down.get() {
298 return;
299 }
300
301 self.wait_for_writer_ready(cx, &global);
303 },
304 PipeToState::ShuttingDownWithPendingWrites(action) => {
305 if let Some(write) = self.pending_writes.borrow().front() {
308 self.wait_on_pending_write(cx, &global, write);
309 return;
310 }
311
312 if let Some(action) = action {
314 self.perform_action(cx, &global, action);
316 } else {
317 self.finalize(cx, &global);
319 }
320 },
321 PipeToState::ShuttingDownPendingAction => {
322 let Some(ref promise) = *self.shutdown_action_promise.borrow() else {
323 unreachable!();
324 };
325 if promise.is_pending() {
326 return;
330 }
331
332 let is_array_like = {
333 if !result.is_object() {
334 false
335 } else {
336 is_array_like::<crate::DomTypeHolder>(cx, result)
337 }
338 };
339
340 if !result.is_undefined() && !is_array_like {
342 self.set_shutdown_error(result);
352 }
353 self.finalize(cx, &global);
354 },
355 PipeToState::Finalized => {},
356 }
357 }
358}
359
360impl PipeTo {
361 fn set_shutdown_error(&self, error: SafeHandleValue) {
364 *self.shutdown_error.borrow_mut() = Some(Heap::default());
365 let Some(ref heap) = *self.shutdown_error.borrow() else {
366 unreachable!("Option set to Some(heap) above.");
367 };
368 heap.set(error.get())
369 }
370
371 fn wait_for_writer_ready(&self, cx: &mut CurrentRealm, global: &GlobalScope) {
374 {
375 let mut state = self.state.borrow_mut();
376 *state = PipeToState::PendingReady;
377 }
378
379 let ready_promise = self.writer.Ready(cx);
380 if ready_promise.is_fulfilled() {
381 self.read_chunk(cx, global);
382 } else {
383 let handler = PromiseNativeHandler::new(
384 cx,
385 global,
386 Some(Box::new(self.clone())),
387 Some(Box::new(self.clone())),
388 );
389 ready_promise.append_native_handler(cx, &handler);
390
391 let closed_promise = self.reader.Closed(cx);
395 closed_promise.append_native_handler(cx, &handler);
396 }
397 }
398
399 fn read_chunk(&self, cx: &mut CurrentRealm, global: &GlobalScope) {
401 *self.state.borrow_mut() = PipeToState::PendingRead;
402 let chunk_promise = self.reader.Read(cx);
403 let handler = PromiseNativeHandler::new(
404 cx,
405 global,
406 Some(Box::new(self.clone())),
407 Some(Box::new(self.clone())),
408 );
409 chunk_promise.append_native_handler(cx, &handler);
410
411 let ready_promise = self.writer.Closed(cx);
414 ready_promise.append_native_handler(cx, &handler);
415 }
416
417 fn write_chunk(
420 &self,
421 cx: &mut JSContext,
422 global: &GlobalScope,
423 chunk: SafeHandleValue,
424 ) -> bool {
425 if chunk.is_object() {
426 rooted!(&in(cx) let object = chunk.to_object());
427 rooted!(&in(cx) let mut bytes = UndefinedValue());
428 get_property_jsval(cx, object.handle(), c"value", bytes.handle_mut())
429 .expect("Chunk should have a value.");
430
431 let write_promise = self.writer.write(cx, global, bytes.handle());
433 self.pending_writes
434 .borrow_mut()
435 .push_back(write_promise.to_traced());
436 return true;
437 }
438 false
439 }
440
441 fn wait_on_pending_write(
445 &self,
446 cx: &mut CurrentRealm,
447 global: &GlobalScope,
448 promise: &Promise,
449 ) {
450 let handler = PromiseNativeHandler::new(
451 cx,
452 global,
453 Some(Box::new(self.clone())),
454 Some(Box::new(self.clone())),
455 );
456 promise.append_native_handler(cx, &handler);
457 }
458
459 fn check_and_propagate_errors_forward(&self, cx: &mut CurrentRealm, global: &GlobalScope) {
462 if self.shutting_down.get() {
465 return;
466 }
467
468 let source = self
470 .reader
471 .get_stream()
472 .expect("Reader should still have a stream");
473 if source.is_errored() {
474 rooted!(&in(cx) let mut source_error = UndefinedValue());
475 source.get_stored_error(source_error.handle_mut());
476 self.set_shutdown_error(source_error.handle());
477
478 if !self.prevent_abort {
480 self.shutdown(cx, global, Some(ShutdownAction::WritableStreamAbort))
483 } else {
484 self.shutdown(cx, global, None);
486 }
487 }
488 }
489
490 fn check_and_propagate_errors_backward(&self, cx: &mut CurrentRealm, global: &GlobalScope) {
493 if self.shutting_down.get() {
496 return;
497 }
498
499 let dest = self
501 .writer
502 .get_stream()
503 .expect("Writer should still have a stream");
504 if dest.is_errored() {
505 rooted!(&in(cx) let mut dest_error = UndefinedValue());
506 dest.get_stored_error(dest_error.handle_mut());
507 self.set_shutdown_error(dest_error.handle());
508
509 if !self.prevent_cancel {
511 self.shutdown(cx, global, Some(ShutdownAction::ReadableStreamCancel))
514 } else {
515 self.shutdown(cx, global, None);
517 }
518 }
519 }
520
521 fn check_and_propagate_closing_forward(&self, cx: &mut CurrentRealm, global: &GlobalScope) {
524 if self.shutting_down.get() {
527 return;
528 }
529
530 let source = self
532 .reader
533 .get_stream()
534 .expect("Reader should still have a stream");
535 if source.is_closed() {
536 if !self.prevent_close {
538 self.shutdown(
541 cx,
542 global,
543 Some(ShutdownAction::WritableStreamDefaultWriterCloseWithErrorPropagation),
544 )
545 } else {
546 self.shutdown(cx, global, None);
548 }
549 }
550 }
551
552 fn check_and_propagate_closing_backward(&self, cx: &mut CurrentRealm, global: &GlobalScope) {
555 if self.shutting_down.get() {
558 return;
559 }
560
561 let dest = self
564 .writer
565 .get_stream()
566 .expect("Writer should still have a stream");
567 if dest.close_queued_or_in_flight() || dest.is_closed() {
568 rooted!(&in(cx) let mut dest_closed = UndefinedValue());
573 let error =
574 Error::Type(c"Destination is closed or has closed queued or in flight".to_owned());
575 error.to_jsval(cx, global, dest_closed.handle_mut());
576 self.set_shutdown_error(dest_closed.handle());
577
578 if !self.prevent_cancel {
580 self.shutdown(cx, global, Some(ShutdownAction::ReadableStreamCancel))
583 } else {
584 self.shutdown(cx, global, None);
586 }
587 }
588 }
589
590 fn shutdown(
594 &self,
595 cx: &mut CurrentRealm,
596 global: &GlobalScope,
597 action: Option<ShutdownAction>,
598 ) {
599 if !self.shutting_down.replace(true) {
602 let dest = self.writer.get_stream().expect("Stream must be set");
603 if dest.is_writable() && !dest.close_queued_or_in_flight() {
606 if let Some(write) = self.pending_writes.borrow().front() {
612 *self.state.borrow_mut() = PipeToState::ShuttingDownWithPendingWrites(action);
613 self.wait_on_pending_write(cx, global, write);
614 return;
615 }
616 }
617
618 if let Some(action) = action {
620 self.perform_action(cx, global, action);
622 } else {
623 self.finalize(cx, global);
625 }
626 }
627 }
628
629 fn perform_action(&self, cx: &mut CurrentRealm, global: &GlobalScope, action: ShutdownAction) {
632 rooted!(&in(cx) let mut error = UndefinedValue());
633 if let Some(shutdown_error) = self.shutdown_error.borrow().as_ref() {
634 error.set(shutdown_error.get());
635 }
636
637 *self.state.borrow_mut() = PipeToState::ShuttingDownPendingAction;
638
639 let promise = match action {
641 ShutdownAction::WritableStreamAbort => {
642 let dest = self.writer.get_stream().expect("Stream must be set");
643 dest.abort(cx, global, error.handle())
644 },
645 ShutdownAction::ReadableStreamCancel => {
646 let source = self
647 .reader
648 .get_stream()
649 .expect("Reader should have a stream.");
650 source.cancel(cx, global, error.handle())
651 },
652 ShutdownAction::WritableStreamDefaultWriterCloseWithErrorPropagation => {
653 self.writer.close_with_error_propagation(cx, global)
654 },
655 ShutdownAction::Abort => {
656 rooted!(&in(cx) let mut error = UndefinedValue());
661 error.set(self.abort_reason.get());
662
663 let mut actions = vec![];
665
666 if !self.prevent_abort {
668 let dest = self
669 .writer
670 .get_stream()
671 .expect("Destination stream must be set");
672
673 let promise = if dest.is_writable() {
675 dest.abort(cx, global, error.handle())
677 } else {
678 Promise::new_resolved(cx, global, ())
680 };
681 actions.push(promise);
682 }
683
684 if !self.prevent_cancel {
686 let source = self.reader.get_stream().expect("Source stream must be set");
687
688 let promise = if source.is_readable() {
690 source.cancel(cx, global, error.handle())
692 } else {
693 Promise::new_resolved(cx, global, ())
695 };
696 actions.push(promise);
697 }
698
699 wait_for_all_promise(cx, global, actions)
703 },
704 };
705
706 let handler = PromiseNativeHandler::new(
709 cx,
710 global,
711 Some(Box::new(self.clone())),
712 Some(Box::new(self.clone())),
713 );
714 promise.append_native_handler(cx, &handler);
715 *self.shutdown_action_promise.borrow_mut() = Some(promise.to_traced());
716 }
717
718 fn finalize(&self, cx: &mut JSContext, global: &GlobalScope) {
720 *self.state.borrow_mut() = PipeToState::Finalized;
721
722 self.writer.release(cx, global);
724
725 self.reader
731 .release(cx)
732 .expect("Releasing the reader should not fail");
733
734 if let Some(shutdown_error) = self.shutdown_error.borrow().as_ref() {
740 rooted!(&in(cx) let mut error = UndefinedValue());
741 error.set(shutdown_error.get());
742 self.result_promise.reject_native(cx, &error.handle());
744 } else {
745 self.result_promise.resolve_native(cx, &());
747 }
748 }
749}
750
751#[derive(Clone, JSTraceable, MallocSizeOf)]
754#[cfg_attr(crown, crown::unrooted_must_root_lint::must_root)]
755struct SourceCancelPromiseFulfillmentHandler {
756 result: TracedPromise,
757}
758
759impl SourceCancelPromiseFulfillmentHandler {
760 fn new(promise: &RootedPromise) -> Box<Self> {
761 Box::new(Self {
762 result: promise.to_traced(),
763 })
764 }
765}
766
767impl Callback for SourceCancelPromiseFulfillmentHandler {
768 fn callback(&self, cx: &mut CurrentRealm, _v: SafeHandleValue) {
772 self.result.resolve_native(cx, &());
773 }
774}
775
776#[derive(Clone, JSTraceable, MallocSizeOf)]
779#[cfg_attr(crown, crown::unrooted_must_root_lint::must_root)]
780struct SourceCancelPromiseRejectionHandler {
781 result: TracedPromise,
782}
783
784impl SourceCancelPromiseRejectionHandler {
785 fn new(promise: &RootedPromise) -> Box<Self> {
786 Box::new(Self {
787 result: promise.to_traced(),
788 })
789 }
790}
791
792impl Callback for SourceCancelPromiseRejectionHandler {
793 fn callback(&self, cx: &mut CurrentRealm, v: SafeHandleValue) {
797 self.result.reject_native(cx, &v);
798 }
799}
800
801#[derive(Clone, Copy, Debug, Default, JSTraceable, MallocSizeOf, PartialEq)]
803pub(crate) enum ReadableStreamState {
804 #[default]
805 Readable,
806 Closed,
807 Errored,
808}
809
810#[derive(JSTraceable, MallocSizeOf)]
812#[cfg_attr(crown, crown::unrooted_must_root_lint::must_root)]
813pub(crate) enum ControllerType {
814 Byte(MutNullableDom<ReadableByteStreamController>),
816 Default(MutNullableDom<ReadableStreamDefaultController>),
818}
819
820#[derive(JSTraceable, MallocSizeOf)]
822#[cfg_attr(crown, crown::unrooted_must_root_lint::must_root)]
823pub(crate) enum ReaderType {
824 #[allow(clippy::upper_case_acronyms)]
826 BYOB(MutNullableDom<ReadableStreamBYOBReader>),
827 Default(MutNullableDom<ReadableStreamDefaultReader>),
829}
830
831impl js::gc::Rootable for ReaderType {}
832
833impl Eq for ReaderType {}
834impl PartialEq for ReaderType {
835 fn eq(&self, other: &Self) -> bool {
836 matches!(
837 (self, other),
838 (ReaderType::BYOB(_), ReaderType::BYOB(_)) |
839 (ReaderType::Default(_), ReaderType::Default(_))
840 )
841 }
842}
843
844pub(crate) fn create_readable_stream(
846 cx: &mut JSContext,
847 global: &GlobalScope,
848 underlying_source_type: UnderlyingSourceType,
849 queuing_strategy: Option<RootedCallback<QueuingStrategySize>>,
850 high_water_mark: Option<f64>,
851) -> DomRoot<ReadableStream> {
852 let high_water_mark = high_water_mark.unwrap_or(1.0);
854
855 let size_algorithm =
857 queuing_strategy.unwrap_or(extract_size_algorithm(cx, &QueuingStrategy::empty()));
858
859 assert!(high_water_mark >= 0.0);
861
862 let stream = ReadableStream::new_with_proto(cx, global, None);
865
866 let controller = ReadableStreamDefaultController::new(
868 cx,
869 global,
870 underlying_source_type,
871 high_water_mark,
872 size_algorithm,
873 );
874
875 controller
878 .setup(cx, &stream)
879 .expect("Setup of default controller cannot fail");
880
881 stream
883}
884
885fn readable_byte_stream_tee(
887 cx: &mut JSContext,
888 global: &GlobalScope,
889 underlying_source_type: UnderlyingSourceType,
890) -> DomRoot<ReadableStream> {
891 let tee_stream = ReadableStream::new_with_proto(cx, global, None);
894
895 let controller = ReadableByteStreamController::new(cx, underlying_source_type, 0.0, global);
897
898 controller
900 .setup(cx, global, &tee_stream)
901 .expect("Setup of byte stream controller cannot fail");
902
903 tee_stream
905}
906
907#[dom_struct]
909pub(crate) struct ReadableStream {
910 reflector_: Reflector,
911
912 controller: RefCell<Option<ControllerType>>,
916
917 #[ignore_malloc_size_of = "mozjs"]
919 stored_error: Heap<JSVal>,
920
921 disturbed: Cell<bool>,
923
924 reader: RefCell<Option<ReaderType>>,
926
927 state: Cell<ReadableStreamState>,
929}
930
931impl ReadableStream {
932 fn new_inherited() -> ReadableStream {
934 ReadableStream {
935 reflector_: Reflector::new(),
936 controller: RefCell::new(None),
937 stored_error: Heap::default(),
938 disturbed: Default::default(),
939 reader: RefCell::new(None),
940 state: Cell::new(Default::default()),
941 }
942 }
943
944 pub(crate) fn new_with_proto(
945 cx: &mut JSContext,
946 global: &GlobalScope,
947 proto: Option<SafeHandleObject>,
948 ) -> DomRoot<ReadableStream> {
949 reflect_dom_object_with_proto(cx, Box::new(ReadableStream::new_inherited()), global, proto)
950 }
951
952 pub(crate) fn set_default_controller(&self, controller: &ReadableStreamDefaultController) {
955 *self.controller.borrow_mut() = Some(ControllerType::Default(MutNullableDom::new(Some(
956 controller,
957 ))));
958 }
959
960 pub(crate) fn set_byte_controller(&self, controller: &ReadableByteStreamController) {
963 *self.controller.borrow_mut() =
964 Some(ControllerType::Byte(MutNullableDom::new(Some(controller))));
965 }
966
967 pub(crate) fn assert_no_controller(&self) {
970 let has_no_controller = self.controller.borrow().is_none();
971 assert!(has_no_controller);
972 }
973
974 pub(crate) fn new_from_bytes(
976 cx: &mut JSContext,
977 global: &GlobalScope,
978 bytes: Vec<u8>,
979 ) -> Fallible<DomRoot<ReadableStream>> {
980 let stream = ReadableStream::new_with_external_underlying_source(
981 cx,
982 global,
983 UnderlyingSourceType::Memory(bytes.len()),
984 )?;
985 stream.enqueue_native(cx, bytes);
986 stream.controller_close_native(cx);
987 Ok(stream)
988 }
989
990 pub(crate) fn new_empty(
993 cx: &mut JSContext,
994 global: &GlobalScope,
995 ) -> Fallible<DomRoot<ReadableStream>> {
996 let empty_stream = ReadableStream::new_with_external_underlying_source(
999 cx,
1000 global,
1001 UnderlyingSourceType::Memory(0),
1002 )?;
1003 empty_stream.controller_close_native(cx);
1005 Ok(empty_stream)
1007 }
1008
1009 pub(crate) fn new_from_bytes_with_byte_reading_support(
1011 cx: &mut JSContext,
1012 global: &GlobalScope,
1013 bytes: Vec<u8>,
1014 ) -> Fallible<DomRoot<ReadableStream>> {
1015 let stream = ReadableStream::new_with_external_underlying_byte_source(
1016 cx,
1017 global,
1018 UnderlyingSourceType::Memory(bytes.len()),
1019 )?;
1020 stream.enqueue_native(cx, bytes);
1021 stream.controller_close_native(cx);
1022 Ok(stream)
1023 }
1024
1025 pub(crate) fn new_with_external_underlying_source(
1028 cx: &mut JSContext,
1029 global: &GlobalScope,
1030 source: UnderlyingSourceType,
1031 ) -> Fallible<DomRoot<ReadableStream>> {
1032 assert!(source.is_native());
1033 let stream = ReadableStream::new_with_proto(cx, global, None);
1034 let strategy_size = extract_size_algorithm(cx, &QueuingStrategy::empty());
1035 let controller =
1036 ReadableStreamDefaultController::new(cx, global, source, 1.0, strategy_size);
1037 controller.setup(cx, &stream)?;
1038 Ok(stream)
1039 }
1040
1041 pub(crate) fn new_with_external_underlying_byte_source(
1043 cx: &mut JSContext,
1044 global: &GlobalScope,
1045 source: UnderlyingSourceType,
1046 ) -> Fallible<DomRoot<ReadableStream>> {
1047 assert!(source.is_native());
1048 let stream = ReadableStream::new_with_proto(cx, global, None);
1049 let controller = ReadableByteStreamController::new(cx, source, 0.0, global);
1050 controller.setup(cx, global, &stream)?;
1051 Ok(stream)
1052 }
1053
1054 pub(crate) fn perform_release_steps(&self) -> Fallible<()> {
1056 match self.controller.borrow().as_ref() {
1057 Some(ControllerType::Default(controller)) => {
1058 let controller = controller
1059 .get()
1060 .ok_or_else(|| Error::Type(c"Stream should have controller.".to_owned()))?;
1061 controller.perform_release_steps()
1062 },
1063 Some(ControllerType::Byte(controller)) => {
1064 let controller = controller
1065 .get()
1066 .ok_or_else(|| Error::Type(c"Stream should have controller.".to_owned()))?;
1067 controller.perform_release_steps()
1068 },
1069 None => Err(Error::Type(c"Stream should have controller.".to_owned())),
1070 }
1071 }
1072
1073 pub(crate) fn perform_pull_steps(&self, cx: &mut JSContext, read_request: &ReadRequest) {
1077 match self.controller.borrow().as_ref() {
1078 Some(ControllerType::Default(controller)) => controller
1079 .get()
1080 .expect("Stream should have controller.")
1081 .perform_pull_steps(cx, read_request),
1082 Some(ControllerType::Byte(controller)) => controller
1083 .get()
1084 .expect("Stream should have controller.")
1085 .perform_pull_steps(cx, read_request),
1086 None => {
1087 unreachable!("Stream does not have a controller.");
1088 },
1089 }
1090 }
1091
1092 pub(crate) fn perform_pull_into(
1096 &self,
1097 cx: &mut JSContext,
1098 read_into_request: &ReadIntoRequest,
1099 view: &HeapBufferSource<ArrayBufferViewU8>,
1100 min: u64,
1101 ) {
1102 match self.controller.borrow().as_ref() {
1103 Some(ControllerType::Byte(controller)) => controller
1104 .get()
1105 .expect("Stream should have controller.")
1106 .perform_pull_into(cx, read_into_request, view, min),
1107 _ => {
1108 unreachable!(
1109 "Pulling a chunk from a stream with a default controller using a BYOB reader"
1110 )
1111 },
1112 }
1113 }
1114
1115 pub(crate) fn add_read_request(&self, read_request: &ReadRequest) {
1117 match self.reader.borrow().as_ref() {
1118 Some(ReaderType::Default(reader)) => {
1119 let Some(reader) = reader.get() else {
1120 panic!("Attempt to add a read request without having first acquired a reader.");
1121 };
1122
1123 assert!(self.is_readable());
1125
1126 reader.add_read_request(read_request);
1128 },
1129 _ => {
1130 unreachable!("Adding a read request can only be done on a default reader.")
1131 },
1132 }
1133 }
1134
1135 pub(crate) fn add_read_into_request(&self, read_request: &ReadIntoRequest) {
1137 match self.reader.borrow().as_ref() {
1138 Some(ReaderType::BYOB(reader)) => {
1140 let Some(reader) = reader.get() else {
1141 unreachable!(
1142 "Attempt to add a read into request without having first acquired a reader."
1143 );
1144 };
1145
1146 assert!(self.is_readable() || self.is_closed());
1148
1149 reader.add_read_into_request(read_request);
1151 },
1152 _ => {
1153 unreachable!("Adding a read into request can only be done on a BYOB reader.")
1154 },
1155 }
1156 }
1157
1158 pub(crate) fn enqueue_native(&self, cx: &mut JSContext, bytes: Vec<u8>) {
1160 match self.controller.borrow().as_ref() {
1161 Some(ControllerType::Default(controller)) => controller
1162 .get()
1163 .expect("Stream should have controller.")
1164 .enqueue_native(cx, bytes),
1165 Some(ControllerType::Byte(controller)) => {
1166 if bytes.is_empty() {
1167 return;
1168 }
1169
1170 let controller = controller.get().expect("Stream should have controller.");
1171 rooted!(&in(cx) let mut chunk_object = ptr::null_mut::<JSObject>());
1172 create_buffer_source::<Uint8>(cx, &bytes, chunk_object.handle_mut())
1173 .expect("failed to create buffer source for native byte chunk.");
1174
1175 let chunk = RootedTraceableBox::new(HeapBufferSource::<ArrayBufferViewU8>::new(
1176 chunk_object.handle(),
1177 ));
1178 controller
1179 .enqueue(cx, chunk)
1180 .expect("Enqueuing a native byte chunk should not fail.");
1181 },
1182 _ => {
1183 unreachable!("Enqueueing chunk to a stream from Rust without a controller");
1184 },
1185 }
1186 }
1187
1188 pub(crate) fn error(&self, cx: &mut JSContext, e: SafeHandleValue) {
1190 assert!(self.is_readable());
1192
1193 self.state.set(ReadableStreamState::Errored);
1195
1196 self.stored_error.set(e.get());
1198
1199 let default_reader = {
1202 let reader_ref = self.reader.borrow();
1203 match reader_ref.as_ref() {
1204 Some(ReaderType::Default(reader)) => reader.get(),
1205 _ => None,
1206 }
1207 };
1208
1209 if let Some(reader) = default_reader {
1210 reader.error(cx, e);
1212 return;
1213 }
1214
1215 let byob_reader = {
1216 let reader_ref = self.reader.borrow();
1217 match reader_ref.as_ref() {
1218 Some(ReaderType::BYOB(reader)) => reader.get(),
1219 _ => None,
1220 }
1221 };
1222
1223 if let Some(reader) = byob_reader {
1224 reader.error_read_into_requests(cx, e);
1226 }
1227
1228 }
1230
1231 pub(crate) fn get_stored_error(&self, mut handle_mut: SafeMutableHandleValue) {
1233 handle_mut.set(self.stored_error.get());
1234 }
1235
1236 pub(crate) fn error_native(&self, cx: &mut JSContext, error: Error) {
1239 rooted!(&in(cx) let mut error_val = UndefinedValue());
1240 error.to_jsval(cx, &self.global(), error_val.handle_mut());
1241 self.error(cx, error_val.handle());
1242 }
1243
1244 pub(crate) fn controller_close_native(&self, cx: &mut JSContext) {
1247 match self.controller.borrow().as_ref() {
1248 Some(ControllerType::Default(controller)) => {
1249 let _ = controller
1250 .get()
1251 .expect("Stream should have controller.")
1252 .Close(cx);
1253 },
1254 Some(ControllerType::Byte(controller)) => {
1255 let _ = controller
1256 .get()
1257 .expect("Stream should have controller.")
1258 .close(cx);
1259 },
1260 _ => {
1261 unreachable!("Native closing requires a stream controller.")
1262 },
1263 }
1264 }
1265
1266 pub(crate) fn in_memory(&self) -> bool {
1269 match self.controller.borrow().as_ref() {
1270 Some(ControllerType::Default(controller)) => controller
1271 .get()
1272 .expect("Stream should have controller.")
1273 .in_memory(),
1274 Some(ControllerType::Byte(controller)) => controller
1275 .get()
1276 .expect("Stream should have controller.")
1277 .in_memory(),
1278 _ => unreachable!("Checking if source is in memory for a stream without a controller"),
1279 }
1280 }
1281
1282 pub(crate) fn get_in_memory_bytes(&self, cx: &mut JSContext) -> Option<GenericSharedMemory> {
1285 match self.controller.borrow().as_ref() {
1286 Some(ControllerType::Default(controller)) => controller
1287 .get()
1288 .expect("Stream should have controller.")
1289 .get_in_memory_bytes()
1290 .map(GenericSharedMemory::from_vec),
1291 Some(ControllerType::Byte(controller)) => controller
1292 .get()
1293 .expect("Stream should have controller.")
1294 .get_in_memory_bytes(cx)
1295 .map(GenericSharedMemory::from_vec),
1296 _ => unreachable!("Getting in-memory bytes for a stream without a controller"),
1297 }
1298 }
1299
1300 pub(crate) fn acquire_default_reader(
1305 &self,
1306 cx: &mut JSContext,
1307 ) -> Fallible<DomRoot<ReadableStreamDefaultReader>> {
1308 let reader = ReadableStreamDefaultReader::new(cx, &self.global());
1310
1311 reader.set_up(cx, self, &self.global())?;
1313
1314 Ok(reader)
1316 }
1317
1318 pub(crate) fn acquire_byob_reader(
1320 &self,
1321 cx: &mut JSContext,
1322 ) -> Fallible<DomRoot<ReadableStreamBYOBReader>> {
1323 let reader = ReadableStreamBYOBReader::new(cx, &self.global());
1325 reader.set_up(cx, self, &self.global())?;
1327
1328 Ok(reader)
1330 }
1331
1332 pub(crate) fn get_default_controller(&self) -> DomRoot<ReadableStreamDefaultController> {
1333 match self.controller.borrow().as_ref() {
1334 Some(ControllerType::Default(controller)) => {
1335 controller.get().expect("Stream should have controller.")
1336 },
1337 _ => {
1338 unreachable!(
1339 "Getting default controller for a stream with a non-default controller"
1340 )
1341 },
1342 }
1343 }
1344
1345 pub(crate) fn get_byte_controller(&self) -> DomRoot<ReadableByteStreamController> {
1346 match self.controller.borrow().as_ref() {
1347 Some(ControllerType::Byte(controller)) => {
1348 controller.get().expect("Stream should have controller.")
1349 },
1350 _ => {
1351 unreachable!("Getting byte controller for a stream with a non-byte controller")
1352 },
1353 }
1354 }
1355
1356 pub(crate) fn get_default_reader(&self) -> DomRoot<ReadableStreamDefaultReader> {
1357 match self.reader.borrow().as_ref() {
1358 Some(ReaderType::Default(reader)) => reader.get().expect("Stream should have reader."),
1359 _ => {
1360 unreachable!("Getting default reader for a stream with a non-default reader")
1361 },
1362 }
1363 }
1364
1365 pub(crate) fn read_a_chunk(&self, cx: &mut JSContext) -> RootedPromise {
1371 match self.reader.borrow().as_ref() {
1372 Some(ReaderType::Default(reader)) => {
1373 let Some(reader) = reader.get() else {
1374 unreachable!(
1375 "Attempt to read stream chunk without having first acquired a reader."
1376 );
1377 };
1378 reader.Read(cx)
1379 },
1380 _ => {
1381 unreachable!("Native reading of a chunk can only be done with a default reader.")
1382 },
1383 }
1384 }
1385
1386 pub(crate) fn stop_reading(&self, cx: &mut JSContext) {
1391 let reader_ref = self.reader.borrow();
1392
1393 match reader_ref.as_ref() {
1394 Some(ReaderType::Default(reader)) => {
1395 let Some(reader) = reader.get() else {
1396 unreachable!("Attempt to stop reading without having first acquired a reader.");
1397 };
1398
1399 drop(reader_ref);
1400 reader.release(cx).expect("Reader release cannot fail.");
1401 },
1402 _ => {
1403 unreachable!("Native stop reading can only be done with a default reader.")
1404 },
1405 }
1406 }
1407
1408 pub(crate) fn is_locked(&self) -> bool {
1410 match self.reader.borrow().as_ref() {
1411 Some(ReaderType::Default(reader)) => reader.get().is_some(),
1412 Some(ReaderType::BYOB(reader)) => reader.get().is_some(),
1413 None => false,
1414 }
1415 }
1416
1417 pub(crate) fn is_disturbed(&self) -> bool {
1418 self.disturbed.get()
1419 }
1420
1421 pub(crate) fn set_is_disturbed(&self, disturbed: bool) {
1422 self.disturbed.set(disturbed);
1423 }
1424
1425 pub(crate) fn is_closed(&self) -> bool {
1426 self.state.get() == ReadableStreamState::Closed
1427 }
1428
1429 pub(crate) fn is_errored(&self) -> bool {
1430 self.state.get() == ReadableStreamState::Errored
1431 }
1432
1433 pub(crate) fn is_readable(&self) -> bool {
1434 self.state.get() == ReadableStreamState::Readable
1435 }
1436
1437 pub(crate) fn has_default_reader(&self) -> bool {
1438 match self.reader.borrow().as_ref() {
1439 Some(ReaderType::Default(reader)) => reader.get().is_some(),
1440 _ => false,
1441 }
1442 }
1443
1444 pub(crate) fn has_byob_reader(&self) -> bool {
1445 match self.reader.borrow().as_ref() {
1446 Some(ReaderType::BYOB(reader)) => reader.get().is_some(),
1447 _ => false,
1448 }
1449 }
1450
1451 pub(crate) fn has_byte_controller(&self) -> bool {
1452 match self.controller.borrow().as_ref() {
1453 Some(ControllerType::Byte(controller)) => controller.get().is_some(),
1454 _ => false,
1455 }
1456 }
1457
1458 pub(crate) fn get_num_read_requests(&self) -> usize {
1460 match self.reader.borrow().as_ref() {
1461 Some(ReaderType::Default(reader)) => {
1462 let reader = reader
1463 .get()
1464 .expect("Stream must have a reader when getting the number of read requests.");
1465 reader.get_num_read_requests()
1466 },
1467 _ => unreachable!(
1468 "Stream must have a default reader when get num read requests is called into."
1469 ),
1470 }
1471 }
1472
1473 pub(crate) fn get_num_read_into_requests(&self) -> usize {
1475 assert!(self.has_byob_reader());
1476
1477 match self.reader.borrow().as_ref() {
1478 Some(ReaderType::BYOB(reader)) => {
1479 let Some(reader) = reader.get() else {
1480 unreachable!(
1481 "Stream must have a reader when get num read into requests is called into."
1482 );
1483 };
1484 reader.get_num_read_into_requests()
1485 },
1486 _ => {
1487 unreachable!(
1488 "Stream must have a BYOB reader when get num read into requests is called into."
1489 );
1490 },
1491 }
1492 }
1493
1494 pub(crate) fn fulfill_read_request(
1496 &self,
1497 cx: &mut JSContext,
1498 chunk: SafeHandleValue,
1499 done: bool,
1500 ) {
1501 assert!(self.has_default_reader());
1503
1504 match self.reader.borrow().as_ref() {
1505 Some(ReaderType::Default(reader)) => {
1506 let reader = reader
1508 .get()
1509 .expect("Stream must have a reader when a read request is fulfilled.");
1510 assert_ne!(reader.get_num_read_requests(), 0);
1512 rooted!(&in(cx) let request = reader.remove_read_request());
1515
1516 if done {
1517 request.close_steps(cx);
1519 } else {
1520 let result = RootedTraceableBox::new(Heap::default());
1522 result.set(*chunk);
1523 request.chunk_steps(cx, result, &self.global());
1524 }
1525 },
1526 _ => {
1527 unreachable!(
1528 "Stream must have a default reader when fulfill read requests is called into."
1529 );
1530 },
1531 }
1532 }
1533
1534 pub(crate) fn fulfill_read_into_request(
1536 &self,
1537 cx: &mut JSContext,
1538 chunk: SafeHandleValue,
1539 done: bool,
1540 ) {
1541 assert!(self.has_byob_reader());
1543
1544 match self.reader.borrow().as_ref() {
1546 Some(ReaderType::BYOB(reader)) => {
1547 let Some(reader) = reader.get() else {
1548 unreachable!(
1549 "Stream must have a reader when a read into request is fulfilled."
1550 );
1551 };
1552
1553 assert!(reader.get_num_read_into_requests() > 0);
1555
1556 rooted!(&in(cx) let read_into_request = reader.remove_read_into_request());
1559
1560 let result = RootedTraceableBox::new(Heap::default());
1562 if done {
1563 result.set(*chunk);
1564 read_into_request.close_steps(cx, Some(result));
1565 } else {
1566 result.set(*chunk);
1568 read_into_request.chunk_steps(cx, result);
1569 }
1570 },
1571 _ => {
1572 unreachable!(
1573 "Stream must have a BYOB reader when fulfill read into requests is called into."
1574 );
1575 },
1576 };
1577 }
1578
1579 pub(crate) fn close(&self, cx: &mut JSContext) {
1581 assert!(self.is_readable());
1583 self.state.set(ReadableStreamState::Closed);
1585 let default_reader = {
1591 let reader_ref = self.reader.borrow();
1592 match reader_ref.as_ref() {
1593 Some(ReaderType::Default(reader)) => reader.get(),
1594 _ => None,
1595 }
1596 };
1597
1598 if let Some(reader) = default_reader {
1599 reader.close(cx);
1601 return;
1602 }
1603
1604 let byob_reader = {
1606 let reader_ref = self.reader.borrow();
1607 match reader_ref.as_ref() {
1608 Some(ReaderType::BYOB(reader)) => reader.get(),
1609 _ => None,
1610 }
1611 };
1612
1613 if let Some(reader) = byob_reader {
1614 reader.close(cx);
1616 }
1617
1618 }
1620
1621 pub(crate) fn cancel(
1623 &self,
1624 cx: &mut JSContext,
1625 global: &GlobalScope,
1626 reason: SafeHandleValue,
1627 ) -> RootedPromise {
1628 self.disturbed.set(true);
1630
1631 if self.is_closed() {
1633 return Promise::new_resolved(cx, global, ());
1634 }
1635 if self.is_errored() {
1637 let promise = Promise::new(cx, global);
1638 rooted!(&in(cx) let mut rval = UndefinedValue());
1639 self.stored_error.to_jsval(cx, rval.handle_mut());
1640 promise.reject_native(cx, &rval.handle());
1641 return promise;
1642 }
1643 self.close(cx);
1645
1646 let byob_reader = {
1648 let reader_ref = self.reader.borrow();
1649 match reader_ref.as_ref() {
1650 Some(ReaderType::BYOB(reader)) => reader.get(),
1651 _ => None,
1652 }
1653 };
1654
1655 if let Some(reader) = byob_reader {
1656 reader.cancel(cx);
1658 }
1659
1660 let source_cancel_promise = match self.controller.borrow().as_ref() {
1663 Some(ControllerType::Default(controller)) => controller
1664 .get()
1665 .expect("Stream should have controller.")
1666 .perform_cancel_steps(cx, global, reason),
1667 Some(ControllerType::Byte(controller)) => controller
1668 .get()
1669 .expect("Stream should have controller.")
1670 .perform_cancel_steps(cx, global, reason),
1671 None => {
1672 panic!("Stream does not have a controller.");
1673 },
1674 };
1675
1676 let global = self.global();
1679 let result_promise = Promise::new(cx, &global);
1680 rooted!(&in(cx) let mut fulfillment_handler = Some(SourceCancelPromiseFulfillmentHandler::new(&result_promise)));
1681 rooted!(&in(cx) let mut rejection_handler = Some(SourceCancelPromiseRejectionHandler::new(&result_promise)));
1682 let handler = PromiseNativeHandler::new(
1683 cx,
1684 &global,
1685 fulfillment_handler
1686 .take()
1687 .map(|handler| handler as Box<dyn Callback>),
1688 rejection_handler
1689 .take()
1690 .map(|handler| handler as Box<dyn Callback>),
1691 );
1692 let mut realm = enter_auto_realm(cx, &*global);
1693 let cx = &mut realm.current_realm();
1694 source_cancel_promise.append_native_handler(cx, &handler);
1695
1696 result_promise
1699 }
1700
1701 #[cfg_attr(crown, expect(crown::unrooted_must_root))]
1702 pub(crate) fn set_reader(&self, new_reader: Option<ReaderType>) {
1703 *self.reader.borrow_mut() = new_reader;
1704 }
1705
1706 #[cfg_attr(crown, expect(crown::unrooted_must_root))]
1707 fn byte_tee(&self, cx: &mut JSContext) -> Fallible<Vec<DomRoot<ReadableStream>>> {
1709 let reader = self.acquire_default_reader(cx)?;
1714 let reader = Rc::new(RefCell::new(ReaderType::Default(MutNullableDom::new(
1715 Some(&reader),
1716 ))));
1717
1718 let reading = Rc::new(Cell::new(false));
1720
1721 let read_again_for_branch_1 = Rc::new(Cell::new(false));
1723
1724 let read_again_for_branch_2 = Rc::new(Cell::new(false));
1726
1727 let canceled_1 = Rc::new(Cell::new(false));
1729
1730 let canceled_2 = Rc::new(Cell::new(false));
1732
1733 let reason_1 = Rc::new(Heap::default());
1735
1736 let reason_2 = Rc::new(Heap::default());
1738
1739 let cancel_promise = Promise::new(cx, &self.global());
1741 let reader_version = Rc::new(Cell::new(0));
1742
1743 let byte_tee_source_1 = ByteTeeUnderlyingSource::new(
1744 cx,
1745 reader.clone(),
1746 self,
1747 reading.clone(),
1748 read_again_for_branch_1.clone(),
1749 read_again_for_branch_2.clone(),
1750 canceled_1.clone(),
1751 canceled_2.clone(),
1752 reason_1.clone(),
1753 reason_2.clone(),
1754 &cancel_promise,
1755 reader_version.clone(),
1756 ByteTeeCancelAlgorithm::Cancel1Algorithm,
1757 ByteTeePullAlgorithm::Pull1Algorithm,
1758 );
1759
1760 let byte_tee_source_2 = ByteTeeUnderlyingSource::new(
1761 cx,
1762 reader.clone(),
1763 self,
1764 reading,
1765 read_again_for_branch_1,
1766 read_again_for_branch_2,
1767 canceled_1,
1768 canceled_2,
1769 reason_1,
1770 reason_2,
1771 &cancel_promise,
1772 reader_version,
1773 ByteTeeCancelAlgorithm::Cancel2Algorithm,
1774 ByteTeePullAlgorithm::Pull2Algorithm,
1775 );
1776
1777 let branch_1 = readable_byte_stream_tee(
1779 cx,
1780 &self.global(),
1781 UnderlyingSourceType::TeeByte(&byte_tee_source_1),
1782 );
1783 byte_tee_source_1.set_branch_1(&branch_1);
1784 byte_tee_source_2.set_branch_1(&branch_1);
1785
1786 let branch_2 = readable_byte_stream_tee(
1788 cx,
1789 &self.global(),
1790 UnderlyingSourceType::TeeByte(&byte_tee_source_2),
1791 );
1792 byte_tee_source_1.set_branch_2(&branch_2);
1793 byte_tee_source_2.set_branch_2(&branch_2);
1794
1795 byte_tee_source_1.forward_reader_error(cx, reader.clone());
1797 byte_tee_source_2.forward_reader_error(cx, reader);
1798
1799 Ok(vec![branch_1, branch_2])
1801 }
1802
1803 #[cfg_attr(crown, expect(crown::unrooted_must_root))]
1805 fn default_tee(
1806 &self,
1807 cx: &mut JSContext,
1808 clone_for_branch_2: bool,
1809 ) -> Fallible<Vec<DomRoot<ReadableStream>>> {
1810 let clone_for_branch_2 = Rc::new(Cell::new(clone_for_branch_2));
1814
1815 let reader = self.acquire_default_reader(cx)?;
1817
1818 let reading = Rc::new(Cell::new(false));
1820 let read_again = Rc::new(Cell::new(false));
1822 let canceled_1 = Rc::new(Cell::new(false));
1824 let canceled_2 = Rc::new(Cell::new(false));
1826
1827 let reason_1 = Rc::new(Heap::default());
1829 let reason_2 = Rc::new(Heap::default());
1831 let cancel_promise = Promise::new(cx, &self.global());
1833
1834 let tee_source_1 = DefaultTeeUnderlyingSource::new(
1835 cx,
1836 &reader,
1837 self,
1838 reading.clone(),
1839 read_again.clone(),
1840 canceled_1.clone(),
1841 canceled_2.clone(),
1842 clone_for_branch_2.clone(),
1843 reason_1.clone(),
1844 reason_2.clone(),
1845 &cancel_promise,
1846 DefaultTeeCancelAlgorithm::Cancel1Algorithm,
1847 );
1848
1849 let underlying_source_type_branch_1 = UnderlyingSourceType::Tee(&tee_source_1);
1850
1851 let tee_source_2 = DefaultTeeUnderlyingSource::new(
1852 cx,
1853 &reader,
1854 self,
1855 reading,
1856 read_again,
1857 canceled_1.clone(),
1858 canceled_2.clone(),
1859 clone_for_branch_2,
1860 reason_1,
1861 reason_2,
1862 &cancel_promise,
1863 DefaultTeeCancelAlgorithm::Cancel2Algorithm,
1864 );
1865
1866 let underlying_source_type_branch_2 = UnderlyingSourceType::Tee(&tee_source_2);
1867
1868 let branch_1 = create_readable_stream(
1870 cx,
1871 &self.global(),
1872 underlying_source_type_branch_1,
1873 None,
1874 None,
1875 );
1876 tee_source_1.set_branch_1(&branch_1);
1877 tee_source_2.set_branch_1(&branch_1);
1878
1879 let branch_2 = create_readable_stream(
1881 cx,
1882 &self.global(),
1883 underlying_source_type_branch_2,
1884 None,
1885 None,
1886 );
1887 tee_source_1.set_branch_2(&branch_2);
1888 tee_source_2.set_branch_2(&branch_2);
1889
1890 reader.default_tee_append_native_handler_to_closed_promise(
1892 cx,
1893 &branch_1,
1894 &branch_2,
1895 canceled_1,
1896 canceled_2,
1897 &cancel_promise,
1898 );
1899
1900 Ok(vec![branch_1, branch_2])
1902 }
1903
1904 #[allow(clippy::too_many_arguments)]
1906 pub(crate) fn pipe_to(
1907 &self,
1908 cx: &mut CurrentRealm,
1909 global: &GlobalScope,
1910 dest: &WritableStream,
1911 prevent_close: bool,
1912 prevent_abort: bool,
1913 prevent_cancel: bool,
1914 signal: Option<&AbortSignal>,
1915 ) -> RootedPromise {
1916 assert!(!self.is_locked());
1927
1928 assert!(!dest.is_locked());
1930
1931 let reader = self
1939 .acquire_default_reader(cx)
1940 .expect("Acquiring a default reader for pipe_to cannot fail");
1941
1942 let writer = dest
1944 .aquire_default_writer(cx, global)
1945 .expect("Acquiring a default writer for pipe_to cannot fail");
1946
1947 self.disturbed.set(true);
1949
1950 let promise = Promise::new(cx, global);
1955
1956 rooted!(&in(cx) let pipe_to = PipeTo {
1958 reader: Dom::from_ref(&reader),
1959 writer: Dom::from_ref(&writer),
1960 pending_writes: Default::default(),
1961 state: Default::default(),
1962 prevent_abort,
1963 prevent_cancel,
1964 prevent_close,
1965 shutting_down: Default::default(),
1966 abort_reason: Default::default(),
1967 shutdown_error: Default::default(),
1968 shutdown_action_promise: Default::default(),
1969 result_promise: promise.to_traced(),
1970 });
1971
1972 if let Some(signal) = signal {
1975 rooted!(&in(cx) let abort_algorithm = AbortAlgorithm::StreamPiping(pipe_to.clone()));
1978
1979 if signal.aborted() {
1981 signal.run_abort_algorithm(cx, global, &abort_algorithm);
1982 return promise;
1983 }
1984
1985 signal.add(&abort_algorithm);
1987 }
1988
1989 pipe_to.check_and_propagate_errors_forward(cx, global);
1991 pipe_to.check_and_propagate_errors_backward(cx, global);
1992 pipe_to.check_and_propagate_closing_forward(cx, global);
1993 pipe_to.check_and_propagate_closing_backward(cx, global);
1994
1995 if *pipe_to.state.borrow() == PipeToState::Starting {
1997 pipe_to.wait_for_writer_ready(cx, global);
1999 }
2000
2001 promise
2003 }
2004
2005 pub(crate) fn tee(
2007 &self,
2008 cx: &mut JSContext,
2009 clone_for_branch_2: bool,
2010 ) -> Fallible<Vec<DomRoot<ReadableStream>>> {
2011 match self.controller.borrow().as_ref() {
2015 Some(ControllerType::Default(_)) => {
2016 self.default_tee(cx, clone_for_branch_2)
2018 },
2019 Some(ControllerType::Byte(_)) => {
2020 self.byte_tee(cx)
2023 },
2024 None => {
2025 unreachable!("Stream should have a controller.");
2026 },
2027 }
2028 }
2029
2030 fn set_up_byte_controller(
2032 &self,
2033 cx: &mut JSContext,
2034 global: &GlobalScope,
2035 underlying_source_dict: &JsUnderlyingSource,
2036 underlying_source_handle: SafeHandleObject,
2037 stream: &ReadableStream,
2038 strategy_hwm: f64,
2039 ) -> Fallible<()> {
2040 if let Some(0) = underlying_source_dict.autoAllocateChunkSize {
2056 return Err(Error::Type(c"autoAllocateChunkSize cannot be 0".to_owned()));
2057 }
2058
2059 let controller = ReadableByteStreamController::new(
2060 cx,
2061 UnderlyingSourceType::Js(underlying_source_dict),
2062 strategy_hwm,
2063 global,
2064 );
2065
2066 controller.set_underlying_source_this_object(underlying_source_handle);
2069
2070 controller.setup(cx, global, stream)
2073 }
2074
2075 pub(crate) fn setup_cross_realm_transform_readable(
2077 &self,
2078 cx: &mut JSContext,
2079 port: &MessagePort,
2080 ) {
2081 let port_id = port.message_port_id();
2082 let global = self.global();
2083
2084 let size_algorithm = extract_size_algorithm(cx, &QueuingStrategy::default());
2089
2090 let controller = ReadableStreamDefaultController::new(
2094 cx,
2095 &self.global(),
2096 UnderlyingSourceType::Transfer(port),
2097 0.,
2098 size_algorithm,
2099 );
2100
2101 rooted!(&in(cx) let cross_realm_transform_readable = CrossRealmTransformReadable {
2104 controller: Dom::from_ref(&controller),
2105 });
2106 global.note_cross_realm_transform_readable(&cross_realm_transform_readable, port_id);
2107
2108 port.Start(cx);
2110
2111 controller
2113 .setup(cx, self)
2114 .expect("Setting up controller for transfer cannot fail.");
2115 }
2116}
2117
2118impl ReadableStreamMethods<crate::DomTypeHolder> for ReadableStream {
2119 fn Constructor(
2121 cx: &mut JSContext,
2122 global: &GlobalScope,
2123 proto: Option<SafeHandleObject>,
2124 underlying_source: Option<*mut JSObject>,
2125 strategy: &QueuingStrategy,
2126 ) -> Fallible<DomRoot<Self>> {
2127 rooted!(&in(cx) let underlying_source_obj = underlying_source.unwrap_or(ptr::null_mut()));
2129 let underlying_source_dict = if !underlying_source_obj.is_null() {
2132 rooted!(&in(cx) let obj_val = ObjectValue(underlying_source_obj.get()));
2133 match JsUnderlyingSource::new(cx, obj_val.handle()) {
2134 Ok(ConversionResult::Success(val)) => val,
2135 Ok(ConversionResult::Failure(error)) => {
2136 return Err(Error::Type(error.into_owned()));
2137 },
2138 _ => {
2139 return Err(Error::JSFailed);
2140 },
2141 }
2142 } else {
2143 JsUnderlyingSource::empty()
2144 };
2145
2146 let stream = ReadableStream::new_with_proto(cx, global, proto);
2148
2149 if underlying_source_dict.type_.is_some() {
2150 if strategy.size.is_some() {
2152 return Err(Error::Range(
2153 c"size is not supported for byte streams".to_owned(),
2154 ));
2155 }
2156
2157 let strategy_hwm = extract_high_water_mark(strategy, 0.0)?;
2159
2160 stream.set_up_byte_controller(
2163 cx,
2164 global,
2165 &underlying_source_dict,
2166 underlying_source_obj.handle(),
2167 &stream,
2168 strategy_hwm,
2169 )?;
2170 } else {
2171 let high_water_mark = extract_high_water_mark(strategy, 1.0)?;
2173
2174 let size_algorithm = extract_size_algorithm(cx, strategy);
2176
2177 let controller = ReadableStreamDefaultController::new(
2178 cx,
2179 global,
2180 UnderlyingSourceType::Js(&underlying_source_dict),
2181 high_water_mark,
2182 size_algorithm,
2183 );
2184
2185 controller.set_underlying_source_this_object(underlying_source_obj.handle());
2188
2189 controller.setup(cx, &stream)?;
2191 };
2192
2193 Ok(stream)
2194 }
2195
2196 fn Locked(&self) -> bool {
2198 self.is_locked()
2199 }
2200
2201 fn Cancel(&self, cx: &mut JSContext, reason: SafeHandleValue) -> RootedPromise {
2203 let global = self.global();
2204 if self.is_locked() {
2205 let promise = Promise::new(cx, &global);
2208 promise.reject_error(cx, Error::Type(c"stream is locked".to_owned()));
2209 promise
2210 } else {
2211 self.cancel(cx, &global, reason)
2213 }
2214 }
2215
2216 fn GetReader(
2218 &self,
2219 cx: &mut JSContext,
2220 options: &ReadableStreamGetReaderOptions,
2221 ) -> Fallible<ReadableStreamReader> {
2222 if options.mode.is_none() {
2224 return Ok(ReadableStreamReader::ReadableStreamDefaultReader(
2225 self.acquire_default_reader(cx)?,
2226 ));
2227 }
2228 assert!(options.mode.unwrap() == ReadableStreamReaderMode::Byob);
2230
2231 Ok(ReadableStreamReader::ReadableStreamBYOBReader(
2233 self.acquire_byob_reader(cx)?,
2234 ))
2235 }
2236
2237 fn Tee(&self, cx: &mut JSContext) -> Fallible<Vec<DomRoot<ReadableStream>>> {
2239 self.tee(cx, false)
2241 }
2242
2243 fn PipeTo(
2245 &self,
2246 cx: &mut CurrentRealm,
2247 destination: &WritableStream,
2248 options: &StreamPipeOptions,
2249 ) -> RootedPromise {
2250 let global = self.global();
2251
2252 if self.is_locked() {
2254 let promise = Promise::new(cx, &global);
2256 promise.reject_error(cx, Error::Type(c"Source stream is locked".to_owned()));
2257 return promise;
2258 }
2259
2260 if destination.is_locked() {
2262 let promise = Promise::new(cx, &global);
2264 promise.reject_error(cx, Error::Type(c"Destination stream is locked".to_owned()));
2265 return promise;
2266 }
2267
2268 let signal = options.signal.as_deref();
2270
2271 self.pipe_to(
2273 cx,
2274 &global,
2275 destination,
2276 options.preventClose,
2277 options.preventAbort,
2278 options.preventCancel,
2279 signal,
2280 )
2281 }
2282
2283 fn PipeThrough(
2285 &self,
2286 cx: &mut CurrentRealm,
2287 transform: &ReadableWritablePair,
2288 options: &StreamPipeOptions,
2289 ) -> Fallible<DomRoot<ReadableStream>> {
2290 let global = self.global();
2291
2292 if self.is_locked() {
2294 return Err(Error::Type(c"Source stream is locked".to_owned()));
2295 }
2296
2297 if transform.writable.is_locked() {
2299 return Err(Error::Type(c"Destination stream is locked".to_owned()));
2300 }
2301
2302 let signal = options.signal.as_deref();
2304
2305 let promise = self.pipe_to(
2308 cx,
2309 &global,
2310 &transform.writable,
2311 options.preventClose,
2312 options.preventAbort,
2313 options.preventCancel,
2314 signal,
2315 );
2316
2317 promise.set_promise_is_handled(cx);
2319
2320 Ok(transform.readable.clone())
2322 }
2323}
2324
2325pub(crate) fn get_type_and_value_from_message(
2329 cx: &mut JSContext,
2330 data: SafeHandleValue,
2331 value: SafeMutableHandleValue,
2332) -> DOMString {
2333 assert!(data.is_object());
2339 rooted!(&in(cx) let data_object = data.to_object());
2340
2341 let type_ = get_property::<DOMString>(
2343 cx,
2344 data_object.handle(),
2345 c"type",
2346 StringificationBehavior::Empty,
2347 );
2348
2349 get_property_jsval(cx, data_object.handle(), c"value", value)
2351 .expect("Getting the value should not fail.");
2352
2353 type_
2355 .expect("The type of the message should be a string")
2356 .expect("Property should be present")
2357}
2358
2359impl js::gc::Rootable for CrossRealmTransformReadable {}
2360
2361#[derive(Clone, JSTraceable, MallocSizeOf)]
2365#[cfg_attr(crown, crown::unrooted_must_root_lint::must_root)]
2366pub(crate) struct CrossRealmTransformReadable {
2367 controller: Dom<ReadableStreamDefaultController>,
2369}
2370
2371impl CrossRealmTransformReadable {
2372 pub(crate) fn handle_message(
2375 &self,
2376 cx: &mut CurrentRealm,
2377 global: &GlobalScope,
2378 port: &MessagePort,
2379 message: SafeHandleValue,
2380 ) {
2381 rooted!(&in(cx) let mut value = UndefinedValue());
2382 let type_string = get_type_and_value_from_message(cx, message, value.handle_mut());
2383
2384 if type_string == "chunk" {
2386 self.controller
2388 .enqueue(cx, value.handle())
2389 .expect("Enqueing a chunk should not fail.");
2390 }
2391
2392 if type_string == "close" {
2394 self.controller.close(cx);
2396
2397 global.disentangle_port(cx, port);
2399 }
2400
2401 if type_string == "error" {
2403 self.controller.error(cx, value.handle());
2405
2406 global.disentangle_port(cx, port);
2408 }
2409 }
2410
2411 pub(crate) fn handle_error(
2414 &self,
2415 cx: &mut CurrentRealm,
2416 global: &GlobalScope,
2417 port: &MessagePort,
2418 ) {
2419 let error = DOMException::new(cx, global, DOMErrorName::DataCloneError);
2421 rooted!(&in(cx) let mut rooted_error = UndefinedValue());
2422 error.to_jsval(cx, rooted_error.handle_mut());
2423
2424 port.cross_realm_transform_send_error(cx, rooted_error.handle());
2426
2427 self.controller.error(cx, rooted_error.handle());
2429
2430 global.disentangle_port(cx, port);
2432 }
2433}
2434
2435pub(crate) fn get_read_promise_done(
2437 cx: &mut JSContext,
2438 v: &SafeHandleValue,
2439) -> Result<bool, Error> {
2440 if !v.is_object() {
2441 return Err(Error::Type(c"Unknown format for done property.".to_owned()));
2442 }
2443
2444 rooted!(&in(cx) let object = v.to_object());
2445 get_property::<bool>(cx, object.handle(), c"done", ())?
2446 .ok_or(Error::Type(c"Promise has no done property.".to_owned()))
2447}
2448
2449pub(crate) fn get_read_promise_bytes(
2451 cx: &mut JSContext,
2452 v: &SafeHandleValue,
2453) -> Result<Vec<u8>, Error> {
2454 if !v.is_object() {
2455 return Err(Error::Type(
2456 c"Unknown format for for bytes read.".to_owned(),
2457 ));
2458 }
2459
2460 rooted!(&in(cx) let object = v.to_object());
2461 get_property::<Vec<u8>>(
2462 cx,
2463 object.handle(),
2464 c"value",
2465 ConversionBehavior::EnforceRange,
2466 )?
2467 .ok_or(Error::Type(c"Promise has no value property.".to_owned()))
2468}
2469
2470impl Transferable for ReadableStream {
2472 type Index = MessagePortIndex;
2473 type Data = MessagePortImpl;
2474
2475 fn transfer(&self, cx: &mut JSContext) -> Fallible<(MessagePortId, MessagePortImpl)> {
2477 if self.is_locked() {
2480 return Err(Error::DataClone(None));
2481 }
2482
2483 let global = self.global();
2484 let mut realm = enter_auto_realm(cx, &*global);
2485 let mut realm = realm.current_realm();
2486 let cx = &mut realm;
2487
2488 let port_1 = MessagePort::new(cx, &global);
2490 global.track_message_port(&port_1, None);
2491
2492 let port_2 = MessagePort::new(cx, &global);
2494 global.track_message_port(&port_2, None);
2495
2496 global.entangle_ports(*port_1.message_port_id(), *port_2.message_port_id());
2498
2499 let writable = WritableStream::new_with_proto(cx, &global, None);
2501
2502 writable.setup_cross_realm_transform_writable(cx, &port_1);
2504
2505 let promise = self.pipe_to(cx, &global, &writable, false, false, false, None);
2507
2508 promise.set_promise_is_handled(cx);
2510
2511 port_2.transfer(cx)
2513 }
2514
2515 fn transfer_receive(
2517 cx: &mut JSContext,
2518 owner: &GlobalScope,
2519 id: MessagePortId,
2520 port_impl: MessagePortImpl,
2521 ) -> Result<DomRoot<Self>, ()> {
2522 let value = ReadableStream::new_with_proto(cx, owner, None);
2525
2526 let transferred_port = MessagePort::transfer_receive(cx, owner, id, port_impl)?;
2533
2534 value.setup_cross_realm_transform_readable(cx, &transferred_port);
2536 Ok(value)
2537 }
2538
2539 fn serialized_storage<'a>(
2541 data: StructuredData<'a, '_>,
2542 ) -> &'a mut Option<FxHashMap<MessagePortId, Self::Data>> {
2543 match data {
2544 StructuredData::Reader(r) => &mut r.port_impls,
2545 StructuredData::Writer(w) => &mut w.ports,
2546 }
2547 }
2548}
2549
2550pub(crate) fn pipe_through(
2557 source: &ReadableStream,
2558 cx: &mut JSContext,
2559 global: &GlobalScope,
2560 transform: &TextDecoderStream,
2561) -> DomRoot<ReadableStream> {
2562 let mut realm = CurrentRealm::assert(cx);
2568 let promise = source.pipe_to(
2571 &mut realm,
2572 global,
2573 &transform.Writable(),
2574 false, false, false, None, );
2579
2580 promise.set_promise_is_handled(cx);
2582 transform.Readable()
2584}