1use std::cell::{Cell, RefCell};
6use std::collections::VecDeque;
7use std::ptr::{self};
8use std::rc::Rc;
9
10use dom_struct::dom_struct;
11use js::context::JSContext;
12use js::conversions::{FromJSValConvertible, ToJSValConvertible};
13use js::jsapi::{Heap, JSObject};
14use js::jsval::{JSVal, ObjectValue, UndefinedValue};
15use js::realm::CurrentRealm;
16use js::rust::{
17 HandleObject as SafeHandleObject, HandleValue as SafeHandleValue,
18 MutableHandleValue as SafeMutableHandleValue,
19};
20use js::typedarray::{ArrayBufferViewU8, Uint8};
21use rustc_hash::FxHashMap;
22use servo_base::generic_channel::GenericSharedMemory;
23use servo_base::id::{MessagePortId, MessagePortIndex};
24use servo_constellation_traits::MessagePortImpl;
25
26use crate::dom::bindings::codegen::Bindings::QueuingStrategyBinding::QueuingStrategy;
27use crate::dom::bindings::codegen::Bindings::ReadableStreamBinding::{
28 ReadableStreamGetReaderOptions, ReadableStreamMethods, ReadableStreamReaderMode,
29 ReadableWritablePair, StreamPipeOptions,
30};
31use script_bindings::str::DOMString;
32use crate::dom::domexception::{DOMErrorName, DOMException};
33use crate::dom::encoding::textdecoderstream::TextDecoderStream;
34use script_bindings::codegen::GenericBindings::TextDecoderStreamBinding::TextDecoderStreamMethods;
35use script_bindings::conversions::{is_array_like, StringificationBehavior};
36use crate::dom::bindings::codegen::Bindings::QueuingStrategyBinding::QueuingStrategySize;
37use crate::dom::abortsignal::{AbortAlgorithm, AbortSignal};
38use crate::dom::bindings::codegen::Bindings::ReadableStreamDefaultReaderBinding::ReadableStreamDefaultReaderMethods;
39use crate::dom::bindings::codegen::Bindings::ReadableStreamDefaultControllerBinding::ReadableStreamDefaultController_Binding::ReadableStreamDefaultControllerMethods;
40use crate::dom::bindings::codegen::Bindings::UnderlyingSourceBinding::UnderlyingSource as JsUnderlyingSource;
41use crate::dom::bindings::conversions::{ConversionBehavior, ConversionResult, get_property, get_property_jsval};
42use crate::dom::bindings::error::{Error, ErrorToJsval, Fallible};
43use crate::dom::bindings::codegen::GenericBindings::WritableStreamDefaultWriterBinding::WritableStreamDefaultWriter_Binding::WritableStreamDefaultWriterMethods;
44use crate::dom::stream::writablestream::WritableStream;
45use crate::dom::bindings::codegen::UnionTypes::ReadableStreamDefaultReaderOrReadableStreamBYOBReader as ReadableStreamReader;
46use crate::dom::bindings::reflector::DomGlobal;
47use script_bindings::reflector::{Reflector, reflect_dom_object_with_proto};
48use crate::dom::bindings::root::{DomRoot, MutNullableDom, Dom};
49use crate::dom::bindings::trace::RootedTraceableBox;
50use crate::dom::stream::byteteeunderlyingsource::{ByteTeeCancelAlgorithm, ByteTeePullAlgorithm, ByteTeeUnderlyingSource};
51use crate::dom::stream::countqueuingstrategy::{extract_high_water_mark, extract_size_algorithm};
52use crate::dom::stream::readablestreamgenericreader::ReadableStreamGenericReader;
53use crate::dom::globalscope::GlobalScope;
54use crate::dom::promise::{wait_for_all_promise, Promise, RootedPromise, TracedPromise};
55use crate::dom::stream::readablebytestreamcontroller::ReadableByteStreamController;
56use crate::dom::stream::readablestreambyobreader::ReadableStreamBYOBReader;
57use crate::dom::stream::readablestreamdefaultcontroller::ReadableStreamDefaultController;
58use crate::dom::stream::readablestreamdefaultreader::{ReadRequest, ReadableStreamDefaultReader};
59use crate::dom::stream::defaultteeunderlyingsource::DefaultTeeCancelAlgorithm;
60use crate::dom::types::DefaultTeeUnderlyingSource;
61use crate::dom::stream::underlyingsourcecontainer::UnderlyingSourceType;
62use crate::dom::stream::writablestreamdefaultwriter::WritableStreamDefaultWriter;
63use script_bindings::codegen::GenericBindings::MessagePortBinding::MessagePortMethods;
64use crate::dom::messageport::MessagePort;
65use crate::realms::{enter_auto_realm};
66use crate::dom::promisenativehandler::{Callback, PromiseNativeHandler};
67use crate::dom::bindings::transferable::Transferable;
68use crate::dom::bindings::structuredclone::StructuredData;
69
70use super::readablestreambyobreader::ReadIntoRequest;
71use crate::dom::bindings::buffer_source::{HeapBufferSource, create_buffer_source};
72
73#[derive(Clone, Debug, Default, MallocSizeOf, PartialEq)]
75enum PipeToState {
76 #[default]
78 Starting,
79 PendingReady,
81 PendingRead,
83 ShuttingDownWithPendingWrites(Option<ShutdownAction>),
86 ShuttingDownPendingAction,
90 Finalized,
93}
94
95#[derive(Clone, Debug, MallocSizeOf, PartialEq)]
97enum ShutdownAction {
98 WritableStreamAbort,
100 ReadableStreamCancel,
102 WritableStreamDefaultWriterCloseWithErrorPropagation,
104 Abort,
106}
107
108impl js::gc::Rootable for PipeTo {}
109
110#[derive(Clone, JSTraceable, MallocSizeOf)]
119#[cfg_attr(crown, crown::unrooted_must_root_lint::must_root)]
120pub(crate) struct PipeTo {
121 reader: Dom<ReadableStreamDefaultReader>,
123
124 writer: Dom<WritableStreamDefaultWriter>,
126
127 #[ignore_malloc_size_of = "nested Rc"]
130 pending_writes: Rc<RefCell<VecDeque<TracedPromise>>>,
131
132 #[conditional_malloc_size_of]
134 #[no_trace]
135 state: Rc<RefCell<PipeToState>>,
136
137 prevent_abort: bool,
139
140 prevent_cancel: bool,
142
143 prevent_close: bool,
145
146 #[conditional_malloc_size_of]
149 shutting_down: Rc<Cell<bool>>,
150
151 #[ignore_malloc_size_of = "mozjs"]
154 abort_reason: Rc<Heap<JSVal>>,
155
156 #[ignore_malloc_size_of = "mozjs"]
159 shutdown_error: Rc<RefCell<Option<Heap<JSVal>>>>,
160
161 #[conditional_malloc_size_of]
164 shutdown_action_promise: Rc<RefCell<Option<TracedPromise>>>,
165
166 result_promise: TracedPromise,
169}
170
171impl PipeTo {
172 pub(crate) fn abort_with_reason(
175 &self,
176 cx: &mut CurrentRealm,
177 global: &GlobalScope,
178 reason: SafeHandleValue,
179 ) {
180 if self.shutting_down.get() {
182 return;
183 }
184
185 self.abort_reason.set(reason.get());
189
190 self.set_shutdown_error(reason);
195
196 self.shutdown(cx, global, Some(ShutdownAction::Abort));
202 }
203}
204
205impl Callback for PipeTo {
206 fn callback(&self, cx: &mut CurrentRealm, result: SafeHandleValue) {
215 let global = self.reader.global();
216
217 self.pending_writes.borrow_mut().retain(|p| {
223 let pending = p.is_pending();
224 if !pending {
225 p.set_promise_is_handled(cx);
226 }
227 pending
228 });
229
230 let state_before_checks = self.state.borrow().clone();
232
233 if state_before_checks == PipeToState::PendingRead {
240 let source = self.reader.get_stream().expect("Source stream must be set");
241 if source.is_closed() {
242 let dest = self
243 .writer
244 .get_stream()
245 .expect("Destination stream must be set");
246
247 if dest.is_writable() && !dest.close_queued_or_in_flight() {
250 let Ok(done) = get_read_promise_done(cx, &result) else {
251 return;
258 };
259
260 if !done {
261 self.write_chunk(cx, &global, result);
263 }
264 }
265 }
266 }
267
268 self.check_and_propagate_errors_forward(cx, &global);
269 self.check_and_propagate_errors_backward(cx, &global);
270 self.check_and_propagate_closing_forward(cx, &global);
271 self.check_and_propagate_closing_backward(cx, &global);
272
273 let state = self.state.borrow().clone();
275
276 if state != state_before_checks {
280 return;
281 }
282
283 match state {
284 PipeToState::Starting => unreachable!("PipeTo should not be in the Starting state."),
285 PipeToState::PendingReady => {
286 self.read_chunk(cx, &global);
288 },
289 PipeToState::PendingRead => {
290 self.write_chunk(cx, &global, result);
292
293 if self.shutting_down.get() {
295 return;
296 }
297
298 self.wait_for_writer_ready(cx, &global);
300 },
301 PipeToState::ShuttingDownWithPendingWrites(action) => {
302 if let Some(write) = self.pending_writes.borrow().front() {
305 self.wait_on_pending_write(cx, &global, write);
306 return;
307 }
308
309 if let Some(action) = action {
311 self.perform_action(cx, &global, action);
313 } else {
314 self.finalize(cx, &global);
316 }
317 },
318 PipeToState::ShuttingDownPendingAction => {
319 let Some(ref promise) = *self.shutdown_action_promise.borrow() else {
320 unreachable!();
321 };
322 if promise.is_pending() {
323 return;
327 }
328
329 let is_array_like = {
330 if !result.is_object() {
331 false
332 } else {
333 is_array_like::<crate::DomTypeHolder>(cx, result)
334 }
335 };
336
337 if !result.is_undefined() && !is_array_like {
339 self.set_shutdown_error(result);
349 }
350 self.finalize(cx, &global);
351 },
352 PipeToState::Finalized => {},
353 }
354 }
355}
356
357impl PipeTo {
358 fn set_shutdown_error(&self, error: SafeHandleValue) {
361 *self.shutdown_error.borrow_mut() = Some(Heap::default());
362 let Some(ref heap) = *self.shutdown_error.borrow() else {
363 unreachable!("Option set to Some(heap) above.");
364 };
365 heap.set(error.get())
366 }
367
368 fn wait_for_writer_ready(&self, cx: &mut CurrentRealm, global: &GlobalScope) {
371 {
372 let mut state = self.state.borrow_mut();
373 *state = PipeToState::PendingReady;
374 }
375
376 let ready_promise = self.writer.Ready();
377 if ready_promise.is_fulfilled() {
378 self.read_chunk(cx, global);
379 } else {
380 let handler = PromiseNativeHandler::new(
381 cx,
382 global,
383 Some(Box::new(self.clone())),
384 Some(Box::new(self.clone())),
385 );
386 ready_promise.append_native_handler(cx, &handler);
387
388 let closed_promise = self.reader.Closed();
392 closed_promise.append_native_handler(cx, &handler);
393 }
394 }
395
396 fn read_chunk(&self, cx: &mut CurrentRealm, global: &GlobalScope) {
398 *self.state.borrow_mut() = PipeToState::PendingRead;
399 let chunk_promise = self.reader.Read(cx);
400 let handler = PromiseNativeHandler::new(
401 cx,
402 global,
403 Some(Box::new(self.clone())),
404 Some(Box::new(self.clone())),
405 );
406 chunk_promise.append_native_handler(cx, &handler);
407
408 let ready_promise = self.writer.Closed();
411 ready_promise.append_native_handler(cx, &handler);
412 }
413
414 fn write_chunk(
417 &self,
418 cx: &mut JSContext,
419 global: &GlobalScope,
420 chunk: SafeHandleValue,
421 ) -> bool {
422 if chunk.is_object() {
423 rooted!(&in(cx) let object = chunk.to_object());
424 rooted!(&in(cx) let mut bytes = UndefinedValue());
425 get_property_jsval(cx, object.handle(), c"value", bytes.handle_mut())
426 .expect("Chunk should have a value.");
427
428 let write_promise = self.writer.write(cx, global, bytes.handle());
430 self.pending_writes
431 .borrow_mut()
432 .push_back(write_promise.to_traced());
433 return true;
434 }
435 false
436 }
437
438 fn wait_on_pending_write(
442 &self,
443 cx: &mut CurrentRealm,
444 global: &GlobalScope,
445 promise: &Promise,
446 ) {
447 let handler = PromiseNativeHandler::new(
448 cx,
449 global,
450 Some(Box::new(self.clone())),
451 Some(Box::new(self.clone())),
452 );
453 promise.append_native_handler(cx, &handler);
454 }
455
456 fn check_and_propagate_errors_forward(&self, cx: &mut CurrentRealm, global: &GlobalScope) {
459 if self.shutting_down.get() {
462 return;
463 }
464
465 let source = self
467 .reader
468 .get_stream()
469 .expect("Reader should still have a stream");
470 if source.is_errored() {
471 rooted!(&in(cx) let mut source_error = UndefinedValue());
472 source.get_stored_error(source_error.handle_mut());
473 self.set_shutdown_error(source_error.handle());
474
475 if !self.prevent_abort {
477 self.shutdown(cx, global, Some(ShutdownAction::WritableStreamAbort))
480 } else {
481 self.shutdown(cx, global, None);
483 }
484 }
485 }
486
487 fn check_and_propagate_errors_backward(&self, cx: &mut CurrentRealm, global: &GlobalScope) {
490 if self.shutting_down.get() {
493 return;
494 }
495
496 let dest = self
498 .writer
499 .get_stream()
500 .expect("Writer should still have a stream");
501 if dest.is_errored() {
502 rooted!(&in(cx) let mut dest_error = UndefinedValue());
503 dest.get_stored_error(dest_error.handle_mut());
504 self.set_shutdown_error(dest_error.handle());
505
506 if !self.prevent_cancel {
508 self.shutdown(cx, global, Some(ShutdownAction::ReadableStreamCancel))
511 } else {
512 self.shutdown(cx, global, None);
514 }
515 }
516 }
517
518 fn check_and_propagate_closing_forward(&self, cx: &mut CurrentRealm, global: &GlobalScope) {
521 if self.shutting_down.get() {
524 return;
525 }
526
527 let source = self
529 .reader
530 .get_stream()
531 .expect("Reader should still have a stream");
532 if source.is_closed() {
533 if !self.prevent_close {
535 self.shutdown(
538 cx,
539 global,
540 Some(ShutdownAction::WritableStreamDefaultWriterCloseWithErrorPropagation),
541 )
542 } else {
543 self.shutdown(cx, global, None);
545 }
546 }
547 }
548
549 fn check_and_propagate_closing_backward(&self, cx: &mut CurrentRealm, global: &GlobalScope) {
552 if self.shutting_down.get() {
555 return;
556 }
557
558 let dest = self
561 .writer
562 .get_stream()
563 .expect("Writer should still have a stream");
564 if dest.close_queued_or_in_flight() || dest.is_closed() {
565 rooted!(&in(cx) let mut dest_closed = UndefinedValue());
570 let error =
571 Error::Type(c"Destination is closed or has closed queued or in flight".to_owned());
572 error.to_jsval(cx, global, dest_closed.handle_mut());
573 self.set_shutdown_error(dest_closed.handle());
574
575 if !self.prevent_cancel {
577 self.shutdown(cx, global, Some(ShutdownAction::ReadableStreamCancel))
580 } else {
581 self.shutdown(cx, global, None);
583 }
584 }
585 }
586
587 fn shutdown(
591 &self,
592 cx: &mut CurrentRealm,
593 global: &GlobalScope,
594 action: Option<ShutdownAction>,
595 ) {
596 if !self.shutting_down.replace(true) {
599 let dest = self.writer.get_stream().expect("Stream must be set");
600 if dest.is_writable() && !dest.close_queued_or_in_flight() {
603 if let Some(write) = self.pending_writes.borrow().front() {
609 *self.state.borrow_mut() = PipeToState::ShuttingDownWithPendingWrites(action);
610 self.wait_on_pending_write(cx, global, write);
611 return;
612 }
613 }
614
615 if let Some(action) = action {
617 self.perform_action(cx, global, action);
619 } else {
620 self.finalize(cx, global);
622 }
623 }
624 }
625
626 fn perform_action(&self, cx: &mut CurrentRealm, global: &GlobalScope, action: ShutdownAction) {
629 rooted!(&in(cx) let mut error = UndefinedValue());
630 if let Some(shutdown_error) = self.shutdown_error.borrow().as_ref() {
631 error.set(shutdown_error.get());
632 }
633
634 *self.state.borrow_mut() = PipeToState::ShuttingDownPendingAction;
635
636 let promise = match action {
638 ShutdownAction::WritableStreamAbort => {
639 let dest = self.writer.get_stream().expect("Stream must be set");
640 dest.abort(cx, global, error.handle())
641 },
642 ShutdownAction::ReadableStreamCancel => {
643 let source = self
644 .reader
645 .get_stream()
646 .expect("Reader should have a stream.");
647 source.cancel(cx, global, error.handle())
648 },
649 ShutdownAction::WritableStreamDefaultWriterCloseWithErrorPropagation => {
650 self.writer.close_with_error_propagation(cx, global)
651 },
652 ShutdownAction::Abort => {
653 rooted!(&in(cx) let mut error = UndefinedValue());
658 error.set(self.abort_reason.get());
659
660 let mut actions = vec![];
662
663 if !self.prevent_abort {
665 let dest = self
666 .writer
667 .get_stream()
668 .expect("Destination stream must be set");
669
670 let promise = if dest.is_writable() {
672 dest.abort(cx, global, error.handle())
674 } else {
675 Promise::new_resolved_rooted(cx, global, ())
677 };
678 actions.push(promise);
679 }
680
681 if !self.prevent_cancel {
683 let source = self.reader.get_stream().expect("Source stream must be set");
684
685 let promise = if source.is_readable() {
687 source.cancel(cx, global, error.handle())
689 } else {
690 Promise::new_resolved_rooted(cx, global, ())
692 };
693 actions.push(promise);
694 }
695
696 wait_for_all_promise(cx, global, actions)
700 },
701 };
702
703 let handler = PromiseNativeHandler::new(
706 cx,
707 global,
708 Some(Box::new(self.clone())),
709 Some(Box::new(self.clone())),
710 );
711 promise.append_native_handler(cx, &handler);
712 *self.shutdown_action_promise.borrow_mut() = Some(promise.to_traced());
713 }
714
715 fn finalize(&self, cx: &mut JSContext, global: &GlobalScope) {
717 *self.state.borrow_mut() = PipeToState::Finalized;
718
719 self.writer.release(cx, global);
721
722 self.reader
728 .release(cx)
729 .expect("Releasing the reader should not fail");
730
731 if let Some(shutdown_error) = self.shutdown_error.borrow().as_ref() {
737 rooted!(&in(cx) let mut error = UndefinedValue());
738 error.set(shutdown_error.get());
739 self.result_promise.reject_native(cx, &error.handle());
741 } else {
742 self.result_promise.resolve_native(cx, &());
744 }
745 }
746}
747
748#[derive(Clone, JSTraceable, MallocSizeOf)]
751#[cfg_attr(crown, crown::unrooted_must_root_lint::must_root)]
752struct SourceCancelPromiseFulfillmentHandler {
753 result: TracedPromise,
754}
755
756impl SourceCancelPromiseFulfillmentHandler {
757 fn new(promise: &RootedPromise) -> Box<Self> {
758 Box::new(Self {
759 result: promise.to_traced(),
760 })
761 }
762}
763
764impl Callback for SourceCancelPromiseFulfillmentHandler {
765 fn callback(&self, cx: &mut CurrentRealm, _v: SafeHandleValue) {
769 self.result.resolve_native(cx, &());
770 }
771}
772
773#[derive(Clone, JSTraceable, MallocSizeOf)]
776#[cfg_attr(crown, crown::unrooted_must_root_lint::must_root)]
777struct SourceCancelPromiseRejectionHandler {
778 result: TracedPromise,
779}
780
781impl SourceCancelPromiseRejectionHandler {
782 fn new(promise: &RootedPromise) -> Box<Self> {
783 Box::new(Self {
784 result: promise.to_traced(),
785 })
786 }
787}
788
789impl Callback for SourceCancelPromiseRejectionHandler {
790 fn callback(&self, cx: &mut CurrentRealm, v: SafeHandleValue) {
794 self.result.reject_native(cx, &v);
795 }
796}
797
798#[derive(Clone, Copy, Debug, Default, JSTraceable, MallocSizeOf, PartialEq)]
800pub(crate) enum ReadableStreamState {
801 #[default]
802 Readable,
803 Closed,
804 Errored,
805}
806
807#[derive(JSTraceable, MallocSizeOf)]
809#[cfg_attr(crown, crown::unrooted_must_root_lint::must_root)]
810pub(crate) enum ControllerType {
811 Byte(MutNullableDom<ReadableByteStreamController>),
813 Default(MutNullableDom<ReadableStreamDefaultController>),
815}
816
817#[derive(JSTraceable, MallocSizeOf)]
819#[cfg_attr(crown, crown::unrooted_must_root_lint::must_root)]
820pub(crate) enum ReaderType {
821 #[allow(clippy::upper_case_acronyms)]
823 BYOB(MutNullableDom<ReadableStreamBYOBReader>),
824 Default(MutNullableDom<ReadableStreamDefaultReader>),
826}
827
828impl js::gc::Rootable for ReaderType {}
829
830impl Eq for ReaderType {}
831impl PartialEq for ReaderType {
832 fn eq(&self, other: &Self) -> bool {
833 matches!(
834 (self, other),
835 (ReaderType::BYOB(_), ReaderType::BYOB(_)) |
836 (ReaderType::Default(_), ReaderType::Default(_))
837 )
838 }
839}
840
841pub(crate) fn create_readable_stream(
843 cx: &mut JSContext,
844 global: &GlobalScope,
845 underlying_source_type: UnderlyingSourceType,
846 queuing_strategy: Option<Rc<QueuingStrategySize>>,
847 high_water_mark: Option<f64>,
848) -> DomRoot<ReadableStream> {
849 let high_water_mark = high_water_mark.unwrap_or(1.0);
851
852 let size_algorithm =
854 queuing_strategy.unwrap_or(extract_size_algorithm(cx, &QueuingStrategy::empty()));
855
856 assert!(high_water_mark >= 0.0);
858
859 let stream = ReadableStream::new_with_proto(cx, global, None);
862
863 let controller = ReadableStreamDefaultController::new(
865 cx,
866 global,
867 underlying_source_type,
868 high_water_mark,
869 size_algorithm,
870 );
871
872 controller
875 .setup(cx, &stream)
876 .expect("Setup of default controller cannot fail");
877
878 stream
880}
881
882fn readable_byte_stream_tee(
884 cx: &mut JSContext,
885 global: &GlobalScope,
886 underlying_source_type: UnderlyingSourceType,
887) -> DomRoot<ReadableStream> {
888 let tee_stream = ReadableStream::new_with_proto(cx, global, None);
891
892 let controller = ReadableByteStreamController::new(cx, underlying_source_type, 0.0, global);
894
895 controller
897 .setup(cx, global, &tee_stream)
898 .expect("Setup of byte stream controller cannot fail");
899
900 tee_stream
902}
903
904#[dom_struct]
906pub(crate) struct ReadableStream {
907 reflector_: Reflector,
908
909 controller: RefCell<Option<ControllerType>>,
913
914 #[ignore_malloc_size_of = "mozjs"]
916 stored_error: Heap<JSVal>,
917
918 disturbed: Cell<bool>,
920
921 reader: RefCell<Option<ReaderType>>,
923
924 state: Cell<ReadableStreamState>,
926}
927
928impl ReadableStream {
929 fn new_inherited() -> ReadableStream {
931 ReadableStream {
932 reflector_: Reflector::new(),
933 controller: RefCell::new(None),
934 stored_error: Heap::default(),
935 disturbed: Default::default(),
936 reader: RefCell::new(None),
937 state: Cell::new(Default::default()),
938 }
939 }
940
941 pub(crate) fn new_with_proto(
942 cx: &mut JSContext,
943 global: &GlobalScope,
944 proto: Option<SafeHandleObject>,
945 ) -> DomRoot<ReadableStream> {
946 reflect_dom_object_with_proto(cx, Box::new(ReadableStream::new_inherited()), global, proto)
947 }
948
949 pub(crate) fn set_default_controller(&self, controller: &ReadableStreamDefaultController) {
952 *self.controller.borrow_mut() = Some(ControllerType::Default(MutNullableDom::new(Some(
953 controller,
954 ))));
955 }
956
957 pub(crate) fn set_byte_controller(&self, controller: &ReadableByteStreamController) {
960 *self.controller.borrow_mut() =
961 Some(ControllerType::Byte(MutNullableDom::new(Some(controller))));
962 }
963
964 pub(crate) fn assert_no_controller(&self) {
967 let has_no_controller = self.controller.borrow().is_none();
968 assert!(has_no_controller);
969 }
970
971 pub(crate) fn new_from_bytes(
973 cx: &mut JSContext,
974 global: &GlobalScope,
975 bytes: Vec<u8>,
976 ) -> Fallible<DomRoot<ReadableStream>> {
977 let stream = ReadableStream::new_with_external_underlying_source(
978 cx,
979 global,
980 UnderlyingSourceType::Memory(bytes.len()),
981 )?;
982 stream.enqueue_native(cx, bytes);
983 stream.controller_close_native(cx);
984 Ok(stream)
985 }
986
987 pub(crate) fn new_empty(
990 cx: &mut JSContext,
991 global: &GlobalScope,
992 ) -> Fallible<DomRoot<ReadableStream>> {
993 let empty_stream = ReadableStream::new_with_external_underlying_source(
996 cx,
997 global,
998 UnderlyingSourceType::Memory(0),
999 )?;
1000 empty_stream.controller_close_native(cx);
1002 Ok(empty_stream)
1004 }
1005
1006 pub(crate) fn new_from_bytes_with_byte_reading_support(
1008 cx: &mut JSContext,
1009 global: &GlobalScope,
1010 bytes: Vec<u8>,
1011 ) -> Fallible<DomRoot<ReadableStream>> {
1012 let stream = ReadableStream::new_with_external_underlying_byte_source(
1013 cx,
1014 global,
1015 UnderlyingSourceType::Memory(bytes.len()),
1016 )?;
1017 stream.enqueue_native(cx, bytes);
1018 stream.controller_close_native(cx);
1019 Ok(stream)
1020 }
1021
1022 pub(crate) fn new_with_external_underlying_source(
1025 cx: &mut JSContext,
1026 global: &GlobalScope,
1027 source: UnderlyingSourceType,
1028 ) -> Fallible<DomRoot<ReadableStream>> {
1029 assert!(source.is_native());
1030 let stream = ReadableStream::new_with_proto(cx, global, None);
1031 let strategy_size = extract_size_algorithm(cx, &QueuingStrategy::empty());
1032 let controller =
1033 ReadableStreamDefaultController::new(cx, global, source, 1.0, strategy_size);
1034 controller.setup(cx, &stream)?;
1035 Ok(stream)
1036 }
1037
1038 pub(crate) fn new_with_external_underlying_byte_source(
1040 cx: &mut JSContext,
1041 global: &GlobalScope,
1042 source: UnderlyingSourceType,
1043 ) -> Fallible<DomRoot<ReadableStream>> {
1044 assert!(source.is_native());
1045 let stream = ReadableStream::new_with_proto(cx, global, None);
1046 let controller = ReadableByteStreamController::new(cx, source, 0.0, global);
1047 controller.setup(cx, global, &stream)?;
1048 Ok(stream)
1049 }
1050
1051 pub(crate) fn perform_release_steps(&self) -> Fallible<()> {
1053 match self.controller.borrow().as_ref() {
1054 Some(ControllerType::Default(controller)) => {
1055 let controller = controller
1056 .get()
1057 .ok_or_else(|| Error::Type(c"Stream should have controller.".to_owned()))?;
1058 controller.perform_release_steps()
1059 },
1060 Some(ControllerType::Byte(controller)) => {
1061 let controller = controller
1062 .get()
1063 .ok_or_else(|| Error::Type(c"Stream should have controller.".to_owned()))?;
1064 controller.perform_release_steps()
1065 },
1066 None => Err(Error::Type(c"Stream should have controller.".to_owned())),
1067 }
1068 }
1069
1070 pub(crate) fn perform_pull_steps(&self, cx: &mut JSContext, read_request: &ReadRequest) {
1074 match self.controller.borrow().as_ref() {
1075 Some(ControllerType::Default(controller)) => controller
1076 .get()
1077 .expect("Stream should have controller.")
1078 .perform_pull_steps(cx, read_request),
1079 Some(ControllerType::Byte(controller)) => controller
1080 .get()
1081 .expect("Stream should have controller.")
1082 .perform_pull_steps(cx, read_request),
1083 None => {
1084 unreachable!("Stream does not have a controller.");
1085 },
1086 }
1087 }
1088
1089 pub(crate) fn perform_pull_into(
1093 &self,
1094 cx: &mut JSContext,
1095 read_into_request: &ReadIntoRequest,
1096 view: &HeapBufferSource<ArrayBufferViewU8>,
1097 min: u64,
1098 ) {
1099 match self.controller.borrow().as_ref() {
1100 Some(ControllerType::Byte(controller)) => controller
1101 .get()
1102 .expect("Stream should have controller.")
1103 .perform_pull_into(cx, read_into_request, view, min),
1104 _ => {
1105 unreachable!(
1106 "Pulling a chunk from a stream with a default controller using a BYOB reader"
1107 )
1108 },
1109 }
1110 }
1111
1112 pub(crate) fn add_read_request(&self, read_request: &ReadRequest) {
1114 match self.reader.borrow().as_ref() {
1115 Some(ReaderType::Default(reader)) => {
1116 let Some(reader) = reader.get() else {
1117 panic!("Attempt to add a read request without having first acquired a reader.");
1118 };
1119
1120 assert!(self.is_readable());
1122
1123 reader.add_read_request(read_request);
1125 },
1126 _ => {
1127 unreachable!("Adding a read request can only be done on a default reader.")
1128 },
1129 }
1130 }
1131
1132 pub(crate) fn add_read_into_request(&self, read_request: &ReadIntoRequest) {
1134 match self.reader.borrow().as_ref() {
1135 Some(ReaderType::BYOB(reader)) => {
1137 let Some(reader) = reader.get() else {
1138 unreachable!(
1139 "Attempt to add a read into request without having first acquired a reader."
1140 );
1141 };
1142
1143 assert!(self.is_readable() || self.is_closed());
1145
1146 reader.add_read_into_request(read_request);
1148 },
1149 _ => {
1150 unreachable!("Adding a read into request can only be done on a BYOB reader.")
1151 },
1152 }
1153 }
1154
1155 pub(crate) fn enqueue_native(&self, cx: &mut JSContext, bytes: Vec<u8>) {
1157 match self.controller.borrow().as_ref() {
1158 Some(ControllerType::Default(controller)) => controller
1159 .get()
1160 .expect("Stream should have controller.")
1161 .enqueue_native(cx, bytes),
1162 Some(ControllerType::Byte(controller)) => {
1163 if bytes.is_empty() {
1164 return;
1165 }
1166
1167 let controller = controller.get().expect("Stream should have controller.");
1168 rooted!(&in(cx) let mut chunk_object = ptr::null_mut::<JSObject>());
1169 create_buffer_source::<Uint8>(cx, &bytes, chunk_object.handle_mut())
1170 .expect("failed to create buffer source for native byte chunk.");
1171
1172 let chunk = RootedTraceableBox::new(HeapBufferSource::<ArrayBufferViewU8>::new(
1173 chunk_object.handle(),
1174 ));
1175 controller
1176 .enqueue(cx, chunk)
1177 .expect("Enqueuing a native byte chunk should not fail.");
1178 },
1179 _ => {
1180 unreachable!("Enqueueing chunk to a stream from Rust without a controller");
1181 },
1182 }
1183 }
1184
1185 pub(crate) fn error(&self, cx: &mut JSContext, e: SafeHandleValue) {
1187 assert!(self.is_readable());
1189
1190 self.state.set(ReadableStreamState::Errored);
1192
1193 self.stored_error.set(e.get());
1195
1196 let default_reader = {
1199 let reader_ref = self.reader.borrow();
1200 match reader_ref.as_ref() {
1201 Some(ReaderType::Default(reader)) => reader.get(),
1202 _ => None,
1203 }
1204 };
1205
1206 if let Some(reader) = default_reader {
1207 reader.error(cx, e);
1209 return;
1210 }
1211
1212 let byob_reader = {
1213 let reader_ref = self.reader.borrow();
1214 match reader_ref.as_ref() {
1215 Some(ReaderType::BYOB(reader)) => reader.get(),
1216 _ => None,
1217 }
1218 };
1219
1220 if let Some(reader) = byob_reader {
1221 reader.error_read_into_requests(cx, e);
1223 }
1224
1225 }
1227
1228 pub(crate) fn get_stored_error(&self, mut handle_mut: SafeMutableHandleValue) {
1230 handle_mut.set(self.stored_error.get());
1231 }
1232
1233 pub(crate) fn error_native(&self, cx: &mut JSContext, error: Error) {
1236 rooted!(&in(cx) let mut error_val = UndefinedValue());
1237 error.to_jsval(cx, &self.global(), error_val.handle_mut());
1238 self.error(cx, error_val.handle());
1239 }
1240
1241 pub(crate) fn controller_close_native(&self, cx: &mut JSContext) {
1244 match self.controller.borrow().as_ref() {
1245 Some(ControllerType::Default(controller)) => {
1246 let _ = controller
1247 .get()
1248 .expect("Stream should have controller.")
1249 .Close(cx);
1250 },
1251 Some(ControllerType::Byte(controller)) => {
1252 let _ = controller
1253 .get()
1254 .expect("Stream should have controller.")
1255 .close(cx);
1256 },
1257 _ => {
1258 unreachable!("Native closing requires a stream controller.")
1259 },
1260 }
1261 }
1262
1263 pub(crate) fn in_memory(&self) -> bool {
1266 match self.controller.borrow().as_ref() {
1267 Some(ControllerType::Default(controller)) => controller
1268 .get()
1269 .expect("Stream should have controller.")
1270 .in_memory(),
1271 Some(ControllerType::Byte(controller)) => controller
1272 .get()
1273 .expect("Stream should have controller.")
1274 .in_memory(),
1275 _ => unreachable!("Checking if source is in memory for a stream without a controller"),
1276 }
1277 }
1278
1279 pub(crate) fn get_in_memory_bytes(&self, cx: &mut JSContext) -> Option<GenericSharedMemory> {
1282 match self.controller.borrow().as_ref() {
1283 Some(ControllerType::Default(controller)) => controller
1284 .get()
1285 .expect("Stream should have controller.")
1286 .get_in_memory_bytes()
1287 .map(GenericSharedMemory::from_vec),
1288 Some(ControllerType::Byte(controller)) => controller
1289 .get()
1290 .expect("Stream should have controller.")
1291 .get_in_memory_bytes(cx)
1292 .map(GenericSharedMemory::from_vec),
1293 _ => unreachable!("Getting in-memory bytes for a stream without a controller"),
1294 }
1295 }
1296
1297 pub(crate) fn acquire_default_reader(
1302 &self,
1303 cx: &mut JSContext,
1304 ) -> Fallible<DomRoot<ReadableStreamDefaultReader>> {
1305 let reader = ReadableStreamDefaultReader::new(cx, &self.global());
1307
1308 reader.set_up(cx, self, &self.global())?;
1310
1311 Ok(reader)
1313 }
1314
1315 pub(crate) fn acquire_byob_reader(
1317 &self,
1318 cx: &mut JSContext,
1319 ) -> Fallible<DomRoot<ReadableStreamBYOBReader>> {
1320 let reader = ReadableStreamBYOBReader::new(cx, &self.global());
1322 reader.set_up(cx, self, &self.global())?;
1324
1325 Ok(reader)
1327 }
1328
1329 pub(crate) fn get_default_controller(&self) -> DomRoot<ReadableStreamDefaultController> {
1330 match self.controller.borrow().as_ref() {
1331 Some(ControllerType::Default(controller)) => {
1332 controller.get().expect("Stream should have controller.")
1333 },
1334 _ => {
1335 unreachable!(
1336 "Getting default controller for a stream with a non-default controller"
1337 )
1338 },
1339 }
1340 }
1341
1342 pub(crate) fn get_byte_controller(&self) -> DomRoot<ReadableByteStreamController> {
1343 match self.controller.borrow().as_ref() {
1344 Some(ControllerType::Byte(controller)) => {
1345 controller.get().expect("Stream should have controller.")
1346 },
1347 _ => {
1348 unreachable!("Getting byte controller for a stream with a non-byte controller")
1349 },
1350 }
1351 }
1352
1353 pub(crate) fn get_default_reader(&self) -> DomRoot<ReadableStreamDefaultReader> {
1354 match self.reader.borrow().as_ref() {
1355 Some(ReaderType::Default(reader)) => reader.get().expect("Stream should have reader."),
1356 _ => {
1357 unreachable!("Getting default reader for a stream with a non-default reader")
1358 },
1359 }
1360 }
1361
1362 pub(crate) fn read_a_chunk(&self, cx: &mut JSContext) -> Rc<Promise> {
1368 match self.reader.borrow().as_ref() {
1369 Some(ReaderType::Default(reader)) => {
1370 let Some(reader) = reader.get() else {
1371 unreachable!(
1372 "Attempt to read stream chunk without having first acquired a reader."
1373 );
1374 };
1375 reader.Read(cx)
1376 },
1377 _ => {
1378 unreachable!("Native reading of a chunk can only be done with a default reader.")
1379 },
1380 }
1381 }
1382
1383 pub(crate) fn stop_reading(&self, cx: &mut JSContext) {
1388 let reader_ref = self.reader.borrow();
1389
1390 match reader_ref.as_ref() {
1391 Some(ReaderType::Default(reader)) => {
1392 let Some(reader) = reader.get() else {
1393 unreachable!("Attempt to stop reading without having first acquired a reader.");
1394 };
1395
1396 drop(reader_ref);
1397 reader.release(cx).expect("Reader release cannot fail.");
1398 },
1399 _ => {
1400 unreachable!("Native stop reading can only be done with a default reader.")
1401 },
1402 }
1403 }
1404
1405 pub(crate) fn is_locked(&self) -> bool {
1407 match self.reader.borrow().as_ref() {
1408 Some(ReaderType::Default(reader)) => reader.get().is_some(),
1409 Some(ReaderType::BYOB(reader)) => reader.get().is_some(),
1410 None => false,
1411 }
1412 }
1413
1414 pub(crate) fn is_disturbed(&self) -> bool {
1415 self.disturbed.get()
1416 }
1417
1418 pub(crate) fn set_is_disturbed(&self, disturbed: bool) {
1419 self.disturbed.set(disturbed);
1420 }
1421
1422 pub(crate) fn is_closed(&self) -> bool {
1423 self.state.get() == ReadableStreamState::Closed
1424 }
1425
1426 pub(crate) fn is_errored(&self) -> bool {
1427 self.state.get() == ReadableStreamState::Errored
1428 }
1429
1430 pub(crate) fn is_readable(&self) -> bool {
1431 self.state.get() == ReadableStreamState::Readable
1432 }
1433
1434 pub(crate) fn has_default_reader(&self) -> bool {
1435 match self.reader.borrow().as_ref() {
1436 Some(ReaderType::Default(reader)) => reader.get().is_some(),
1437 _ => false,
1438 }
1439 }
1440
1441 pub(crate) fn has_byob_reader(&self) -> bool {
1442 match self.reader.borrow().as_ref() {
1443 Some(ReaderType::BYOB(reader)) => reader.get().is_some(),
1444 _ => false,
1445 }
1446 }
1447
1448 pub(crate) fn has_byte_controller(&self) -> bool {
1449 match self.controller.borrow().as_ref() {
1450 Some(ControllerType::Byte(controller)) => controller.get().is_some(),
1451 _ => false,
1452 }
1453 }
1454
1455 pub(crate) fn get_num_read_requests(&self) -> usize {
1457 match self.reader.borrow().as_ref() {
1458 Some(ReaderType::Default(reader)) => {
1459 let reader = reader
1460 .get()
1461 .expect("Stream must have a reader when getting the number of read requests.");
1462 reader.get_num_read_requests()
1463 },
1464 _ => unreachable!(
1465 "Stream must have a default reader when get num read requests is called into."
1466 ),
1467 }
1468 }
1469
1470 pub(crate) fn get_num_read_into_requests(&self) -> usize {
1472 assert!(self.has_byob_reader());
1473
1474 match self.reader.borrow().as_ref() {
1475 Some(ReaderType::BYOB(reader)) => {
1476 let Some(reader) = reader.get() else {
1477 unreachable!(
1478 "Stream must have a reader when get num read into requests is called into."
1479 );
1480 };
1481 reader.get_num_read_into_requests()
1482 },
1483 _ => {
1484 unreachable!(
1485 "Stream must have a BYOB reader when get num read into requests is called into."
1486 );
1487 },
1488 }
1489 }
1490
1491 pub(crate) fn fulfill_read_request(
1493 &self,
1494 cx: &mut JSContext,
1495 chunk: SafeHandleValue,
1496 done: bool,
1497 ) {
1498 assert!(self.has_default_reader());
1500
1501 match self.reader.borrow().as_ref() {
1502 Some(ReaderType::Default(reader)) => {
1503 let reader = reader
1505 .get()
1506 .expect("Stream must have a reader when a read request is fulfilled.");
1507 assert_ne!(reader.get_num_read_requests(), 0);
1509 rooted!(&in(cx) let request = reader.remove_read_request());
1512
1513 if done {
1514 request.close_steps(cx);
1516 } else {
1517 let result = RootedTraceableBox::new(Heap::default());
1519 result.set(*chunk);
1520 request.chunk_steps(cx, result, &self.global());
1521 }
1522 },
1523 _ => {
1524 unreachable!(
1525 "Stream must have a default reader when fulfill read requests is called into."
1526 );
1527 },
1528 }
1529 }
1530
1531 pub(crate) fn fulfill_read_into_request(
1533 &self,
1534 cx: &mut JSContext,
1535 chunk: SafeHandleValue,
1536 done: bool,
1537 ) {
1538 assert!(self.has_byob_reader());
1540
1541 match self.reader.borrow().as_ref() {
1543 Some(ReaderType::BYOB(reader)) => {
1544 let Some(reader) = reader.get() else {
1545 unreachable!(
1546 "Stream must have a reader when a read into request is fulfilled."
1547 );
1548 };
1549
1550 assert!(reader.get_num_read_into_requests() > 0);
1552
1553 let read_into_request = reader.remove_read_into_request();
1556
1557 let result = RootedTraceableBox::new(Heap::default());
1559 if done {
1560 result.set(*chunk);
1561 read_into_request.close_steps(cx, Some(result));
1562 } else {
1563 result.set(*chunk);
1565 read_into_request.chunk_steps(cx, result);
1566 }
1567 },
1568 _ => {
1569 unreachable!(
1570 "Stream must have a BYOB reader when fulfill read into requests is called into."
1571 );
1572 },
1573 };
1574 }
1575
1576 pub(crate) fn close(&self, cx: &mut JSContext) {
1578 assert!(self.is_readable());
1580 self.state.set(ReadableStreamState::Closed);
1582 let default_reader = {
1588 let reader_ref = self.reader.borrow();
1589 match reader_ref.as_ref() {
1590 Some(ReaderType::Default(reader)) => reader.get(),
1591 _ => None,
1592 }
1593 };
1594
1595 if let Some(reader) = default_reader {
1596 reader.close(cx);
1598 return;
1599 }
1600
1601 let byob_reader = {
1603 let reader_ref = self.reader.borrow();
1604 match reader_ref.as_ref() {
1605 Some(ReaderType::BYOB(reader)) => reader.get(),
1606 _ => None,
1607 }
1608 };
1609
1610 if let Some(reader) = byob_reader {
1611 reader.close(cx);
1613 }
1614
1615 }
1617
1618 pub(crate) fn cancel(
1620 &self,
1621 cx: &mut JSContext,
1622 global: &GlobalScope,
1623 reason: SafeHandleValue,
1624 ) -> RootedPromise {
1625 self.disturbed.set(true);
1627
1628 if self.is_closed() {
1630 return Promise::new_resolved_rooted(cx, global, ());
1631 }
1632 if self.is_errored() {
1634 let promise = Promise::new_rooted(cx, global);
1635 rooted!(&in(cx) let mut rval = UndefinedValue());
1636 self.stored_error.to_jsval(cx, rval.handle_mut());
1637 promise.reject_native(cx, &rval.handle());
1638 return promise;
1639 }
1640 self.close(cx);
1642
1643 let byob_reader = {
1645 let reader_ref = self.reader.borrow();
1646 match reader_ref.as_ref() {
1647 Some(ReaderType::BYOB(reader)) => reader.get(),
1648 _ => None,
1649 }
1650 };
1651
1652 if let Some(reader) = byob_reader {
1653 reader.cancel(cx);
1655 }
1656
1657 let source_cancel_promise = match self.controller.borrow().as_ref() {
1660 Some(ControllerType::Default(controller)) => controller
1661 .get()
1662 .expect("Stream should have controller.")
1663 .perform_cancel_steps(cx, global, reason),
1664 Some(ControllerType::Byte(controller)) => controller
1665 .get()
1666 .expect("Stream should have controller.")
1667 .perform_cancel_steps(cx, global, reason),
1668 None => {
1669 panic!("Stream does not have a controller.");
1670 },
1671 };
1672
1673 let global = self.global();
1676 let result_promise = Promise::new_rooted(cx, &global);
1677 rooted!(&in(cx) let mut fulfillment_handler = Some(SourceCancelPromiseFulfillmentHandler::new(&result_promise)));
1678 rooted!(&in(cx) let mut rejection_handler = Some(SourceCancelPromiseRejectionHandler::new(&result_promise)));
1679 let handler = PromiseNativeHandler::new(
1680 cx,
1681 &global,
1682 fulfillment_handler
1683 .take()
1684 .map(|handler| handler as Box<dyn Callback>),
1685 rejection_handler
1686 .take()
1687 .map(|handler| handler as Box<dyn Callback>),
1688 );
1689 let mut realm = enter_auto_realm(cx, &*global);
1690 let cx = &mut realm.current_realm();
1691 source_cancel_promise.append_native_handler(cx, &handler);
1692
1693 result_promise
1696 }
1697
1698 #[cfg_attr(crown, expect(crown::unrooted_must_root))]
1699 pub(crate) fn set_reader(&self, new_reader: Option<ReaderType>) {
1700 *self.reader.borrow_mut() = new_reader;
1701 }
1702
1703 #[cfg_attr(crown, expect(crown::unrooted_must_root))]
1704 fn byte_tee(&self, cx: &mut JSContext) -> Fallible<Vec<DomRoot<ReadableStream>>> {
1706 let reader = self.acquire_default_reader(cx)?;
1711 let reader = Rc::new(RefCell::new(ReaderType::Default(MutNullableDom::new(
1712 Some(&reader),
1713 ))));
1714
1715 let reading = Rc::new(Cell::new(false));
1717
1718 let read_again_for_branch_1 = Rc::new(Cell::new(false));
1720
1721 let read_again_for_branch_2 = Rc::new(Cell::new(false));
1723
1724 let canceled_1 = Rc::new(Cell::new(false));
1726
1727 let canceled_2 = Rc::new(Cell::new(false));
1729
1730 let reason_1 = Rc::new(Heap::default());
1732
1733 let reason_2 = Rc::new(Heap::default());
1735
1736 let cancel_promise = Promise::new(cx, &self.global());
1738 let reader_version = Rc::new(Cell::new(0));
1739
1740 let byte_tee_source_1 = ByteTeeUnderlyingSource::new(
1741 cx,
1742 reader.clone(),
1743 self,
1744 reading.clone(),
1745 read_again_for_branch_1.clone(),
1746 read_again_for_branch_2.clone(),
1747 canceled_1.clone(),
1748 canceled_2.clone(),
1749 reason_1.clone(),
1750 reason_2.clone(),
1751 cancel_promise.clone(),
1752 reader_version.clone(),
1753 ByteTeeCancelAlgorithm::Cancel1Algorithm,
1754 ByteTeePullAlgorithm::Pull1Algorithm,
1755 );
1756
1757 let byte_tee_source_2 = ByteTeeUnderlyingSource::new(
1758 cx,
1759 reader.clone(),
1760 self,
1761 reading,
1762 read_again_for_branch_1,
1763 read_again_for_branch_2,
1764 canceled_1,
1765 canceled_2,
1766 reason_1,
1767 reason_2,
1768 cancel_promise,
1769 reader_version,
1770 ByteTeeCancelAlgorithm::Cancel2Algorithm,
1771 ByteTeePullAlgorithm::Pull2Algorithm,
1772 );
1773
1774 let branch_1 = readable_byte_stream_tee(
1776 cx,
1777 &self.global(),
1778 UnderlyingSourceType::TeeByte(&byte_tee_source_1),
1779 );
1780 byte_tee_source_1.set_branch_1(&branch_1);
1781 byte_tee_source_2.set_branch_1(&branch_1);
1782
1783 let branch_2 = readable_byte_stream_tee(
1785 cx,
1786 &self.global(),
1787 UnderlyingSourceType::TeeByte(&byte_tee_source_2),
1788 );
1789 byte_tee_source_1.set_branch_2(&branch_2);
1790 byte_tee_source_2.set_branch_2(&branch_2);
1791
1792 byte_tee_source_1.forward_reader_error(cx, reader.clone());
1794 byte_tee_source_2.forward_reader_error(cx, reader);
1795
1796 Ok(vec![branch_1, branch_2])
1798 }
1799
1800 #[cfg_attr(crown, expect(crown::unrooted_must_root))]
1802 fn default_tee(
1803 &self,
1804 cx: &mut JSContext,
1805 clone_for_branch_2: bool,
1806 ) -> Fallible<Vec<DomRoot<ReadableStream>>> {
1807 let clone_for_branch_2 = Rc::new(Cell::new(clone_for_branch_2));
1811
1812 let reader = self.acquire_default_reader(cx)?;
1814
1815 let reading = Rc::new(Cell::new(false));
1817 let read_again = Rc::new(Cell::new(false));
1819 let canceled_1 = Rc::new(Cell::new(false));
1821 let canceled_2 = Rc::new(Cell::new(false));
1823
1824 let reason_1 = Rc::new(Heap::default());
1826 let reason_2 = Rc::new(Heap::default());
1828 let cancel_promise = Promise::new(cx, &self.global());
1830
1831 let tee_source_1 = DefaultTeeUnderlyingSource::new(
1832 cx,
1833 &reader,
1834 self,
1835 reading.clone(),
1836 read_again.clone(),
1837 canceled_1.clone(),
1838 canceled_2.clone(),
1839 clone_for_branch_2.clone(),
1840 reason_1.clone(),
1841 reason_2.clone(),
1842 cancel_promise.clone(),
1843 DefaultTeeCancelAlgorithm::Cancel1Algorithm,
1844 );
1845
1846 let underlying_source_type_branch_1 = UnderlyingSourceType::Tee(&tee_source_1);
1847
1848 let tee_source_2 = DefaultTeeUnderlyingSource::new(
1849 cx,
1850 &reader,
1851 self,
1852 reading,
1853 read_again,
1854 canceled_1.clone(),
1855 canceled_2.clone(),
1856 clone_for_branch_2,
1857 reason_1,
1858 reason_2,
1859 cancel_promise.clone(),
1860 DefaultTeeCancelAlgorithm::Cancel2Algorithm,
1861 );
1862
1863 let underlying_source_type_branch_2 = UnderlyingSourceType::Tee(&tee_source_2);
1864
1865 let branch_1 = create_readable_stream(
1867 cx,
1868 &self.global(),
1869 underlying_source_type_branch_1,
1870 None,
1871 None,
1872 );
1873 tee_source_1.set_branch_1(&branch_1);
1874 tee_source_2.set_branch_1(&branch_1);
1875
1876 let branch_2 = create_readable_stream(
1878 cx,
1879 &self.global(),
1880 underlying_source_type_branch_2,
1881 None,
1882 None,
1883 );
1884 tee_source_1.set_branch_2(&branch_2);
1885 tee_source_2.set_branch_2(&branch_2);
1886
1887 reader.default_tee_append_native_handler_to_closed_promise(
1889 cx,
1890 &branch_1,
1891 &branch_2,
1892 canceled_1,
1893 canceled_2,
1894 cancel_promise,
1895 );
1896
1897 Ok(vec![branch_1, branch_2])
1899 }
1900
1901 #[allow(clippy::too_many_arguments)]
1903 pub(crate) fn pipe_to(
1904 &self,
1905 cx: &mut CurrentRealm,
1906 global: &GlobalScope,
1907 dest: &WritableStream,
1908 prevent_close: bool,
1909 prevent_abort: bool,
1910 prevent_cancel: bool,
1911 signal: Option<&AbortSignal>,
1912 ) -> RootedPromise {
1913 assert!(!self.is_locked());
1924
1925 assert!(!dest.is_locked());
1927
1928 let reader = self
1936 .acquire_default_reader(cx)
1937 .expect("Acquiring a default reader for pipe_to cannot fail");
1938
1939 let writer = dest
1941 .aquire_default_writer(cx, global)
1942 .expect("Acquiring a default writer for pipe_to cannot fail");
1943
1944 self.disturbed.set(true);
1946
1947 let promise = Promise::new_rooted(cx, global);
1952
1953 rooted!(&in(cx) let pipe_to = PipeTo {
1955 reader: Dom::from_ref(&reader),
1956 writer: Dom::from_ref(&writer),
1957 pending_writes: Default::default(),
1958 state: Default::default(),
1959 prevent_abort,
1960 prevent_cancel,
1961 prevent_close,
1962 shutting_down: Default::default(),
1963 abort_reason: Default::default(),
1964 shutdown_error: Default::default(),
1965 shutdown_action_promise: Default::default(),
1966 result_promise: promise.to_traced(),
1967 });
1968
1969 if let Some(signal) = signal {
1972 rooted!(&in(cx) let abort_algorithm = AbortAlgorithm::StreamPiping(pipe_to.clone()));
1975
1976 if signal.aborted() {
1978 signal.run_abort_algorithm(cx, global, &abort_algorithm);
1979 return promise;
1980 }
1981
1982 signal.add(&abort_algorithm);
1984 }
1985
1986 pipe_to.check_and_propagate_errors_forward(cx, global);
1988 pipe_to.check_and_propagate_errors_backward(cx, global);
1989 pipe_to.check_and_propagate_closing_forward(cx, global);
1990 pipe_to.check_and_propagate_closing_backward(cx, global);
1991
1992 if *pipe_to.state.borrow() == PipeToState::Starting {
1994 pipe_to.wait_for_writer_ready(cx, global);
1996 }
1997
1998 promise
2000 }
2001
2002 pub(crate) fn tee(
2004 &self,
2005 cx: &mut JSContext,
2006 clone_for_branch_2: bool,
2007 ) -> Fallible<Vec<DomRoot<ReadableStream>>> {
2008 match self.controller.borrow().as_ref() {
2012 Some(ControllerType::Default(_)) => {
2013 self.default_tee(cx, clone_for_branch_2)
2015 },
2016 Some(ControllerType::Byte(_)) => {
2017 self.byte_tee(cx)
2020 },
2021 None => {
2022 unreachable!("Stream should have a controller.");
2023 },
2024 }
2025 }
2026
2027 fn set_up_byte_controller(
2029 &self,
2030 cx: &mut JSContext,
2031 global: &GlobalScope,
2032 underlying_source_dict: JsUnderlyingSource,
2033 underlying_source_handle: SafeHandleObject,
2034 stream: &ReadableStream,
2035 strategy_hwm: f64,
2036 ) -> Fallible<()> {
2037 if let Some(0) = underlying_source_dict.autoAllocateChunkSize {
2053 return Err(Error::Type(c"autoAllocateChunkSize cannot be 0".to_owned()));
2054 }
2055
2056 let controller = ReadableByteStreamController::new(
2057 cx,
2058 UnderlyingSourceType::Js(underlying_source_dict),
2059 strategy_hwm,
2060 global,
2061 );
2062
2063 controller.set_underlying_source_this_object(underlying_source_handle);
2066
2067 controller.setup(cx, global, stream)
2070 }
2071
2072 pub(crate) fn setup_cross_realm_transform_readable(
2074 &self,
2075 cx: &mut JSContext,
2076 port: &MessagePort,
2077 ) {
2078 let port_id = port.message_port_id();
2079 let global = self.global();
2080
2081 let size_algorithm = extract_size_algorithm(cx, &QueuingStrategy::default());
2086
2087 let controller = ReadableStreamDefaultController::new(
2091 cx,
2092 &self.global(),
2093 UnderlyingSourceType::Transfer(port),
2094 0.,
2095 size_algorithm,
2096 );
2097
2098 rooted!(&in(cx) let cross_realm_transform_readable = CrossRealmTransformReadable {
2101 controller: Dom::from_ref(&controller),
2102 });
2103 global.note_cross_realm_transform_readable(&cross_realm_transform_readable, port_id);
2104
2105 port.Start(cx);
2107
2108 controller
2110 .setup(cx, self)
2111 .expect("Setting up controller for transfer cannot fail.");
2112 }
2113}
2114
2115impl ReadableStreamMethods<crate::DomTypeHolder> for ReadableStream {
2116 fn Constructor(
2118 cx: &mut JSContext,
2119 global: &GlobalScope,
2120 proto: Option<SafeHandleObject>,
2121 underlying_source: Option<*mut JSObject>,
2122 strategy: &QueuingStrategy,
2123 ) -> Fallible<DomRoot<Self>> {
2124 rooted!(&in(cx) let underlying_source_obj = underlying_source.unwrap_or(ptr::null_mut()));
2126 let underlying_source_dict = if !underlying_source_obj.is_null() {
2129 rooted!(&in(cx) let obj_val = ObjectValue(underlying_source_obj.get()));
2130 match JsUnderlyingSource::new(cx, obj_val.handle()) {
2131 Ok(ConversionResult::Success(val)) => val,
2132 Ok(ConversionResult::Failure(error)) => {
2133 return Err(Error::Type(error.into_owned()));
2134 },
2135 _ => {
2136 return Err(Error::JSFailed);
2137 },
2138 }
2139 } else {
2140 JsUnderlyingSource::empty()
2141 };
2142
2143 let stream = ReadableStream::new_with_proto(cx, global, proto);
2145
2146 if underlying_source_dict.type_.is_some() {
2147 if strategy.size.is_some() {
2149 return Err(Error::Range(
2150 c"size is not supported for byte streams".to_owned(),
2151 ));
2152 }
2153
2154 let strategy_hwm = extract_high_water_mark(strategy, 0.0)?;
2156
2157 stream.set_up_byte_controller(
2160 cx,
2161 global,
2162 underlying_source_dict,
2163 underlying_source_obj.handle(),
2164 &stream,
2165 strategy_hwm,
2166 )?;
2167 } else {
2168 let high_water_mark = extract_high_water_mark(strategy, 1.0)?;
2170
2171 let size_algorithm = extract_size_algorithm(cx, strategy);
2173
2174 let controller = ReadableStreamDefaultController::new(
2175 cx,
2176 global,
2177 UnderlyingSourceType::Js(underlying_source_dict),
2178 high_water_mark,
2179 size_algorithm,
2180 );
2181
2182 controller.set_underlying_source_this_object(underlying_source_obj.handle());
2185
2186 controller.setup(cx, &stream)?;
2188 };
2189
2190 Ok(stream)
2191 }
2192
2193 fn Locked(&self) -> bool {
2195 self.is_locked()
2196 }
2197
2198 fn Cancel(&self, cx: &mut JSContext, reason: SafeHandleValue) -> Rc<Promise> {
2200 let global = self.global();
2201 if self.is_locked() {
2202 let promise = Promise::new(cx, &global);
2205 promise.reject_error(cx, Error::Type(c"stream is locked".to_owned()));
2206 promise
2207 } else {
2208 self.cancel(cx, &global, reason).into()
2210 }
2211 }
2212
2213 fn GetReader(
2215 &self,
2216 cx: &mut JSContext,
2217 options: &ReadableStreamGetReaderOptions,
2218 ) -> Fallible<ReadableStreamReader> {
2219 if options.mode.is_none() {
2221 return Ok(ReadableStreamReader::ReadableStreamDefaultReader(
2222 self.acquire_default_reader(cx)?,
2223 ));
2224 }
2225 assert!(options.mode.unwrap() == ReadableStreamReaderMode::Byob);
2227
2228 Ok(ReadableStreamReader::ReadableStreamBYOBReader(
2230 self.acquire_byob_reader(cx)?,
2231 ))
2232 }
2233
2234 fn Tee(&self, cx: &mut JSContext) -> Fallible<Vec<DomRoot<ReadableStream>>> {
2236 self.tee(cx, false)
2238 }
2239
2240 fn PipeTo(
2242 &self,
2243 cx: &mut CurrentRealm,
2244 destination: &WritableStream,
2245 options: &StreamPipeOptions,
2246 ) -> Rc<Promise> {
2247 let global = self.global();
2248
2249 if self.is_locked() {
2251 let promise = Promise::new(cx, &global);
2253 promise.reject_error(cx, Error::Type(c"Source stream is locked".to_owned()));
2254 return promise;
2255 }
2256
2257 if destination.is_locked() {
2259 let promise = Promise::new(cx, &global);
2261 promise.reject_error(cx, Error::Type(c"Destination stream is locked".to_owned()));
2262 return promise;
2263 }
2264
2265 let signal = options.signal.as_deref();
2267
2268 self.pipe_to(
2270 cx,
2271 &global,
2272 destination,
2273 options.preventClose,
2274 options.preventAbort,
2275 options.preventCancel,
2276 signal,
2277 )
2278 .into()
2279 }
2280
2281 fn PipeThrough(
2283 &self,
2284 cx: &mut CurrentRealm,
2285 transform: &ReadableWritablePair,
2286 options: &StreamPipeOptions,
2287 ) -> Fallible<DomRoot<ReadableStream>> {
2288 let global = self.global();
2289
2290 if self.is_locked() {
2292 return Err(Error::Type(c"Source stream is locked".to_owned()));
2293 }
2294
2295 if transform.writable.is_locked() {
2297 return Err(Error::Type(c"Destination stream is locked".to_owned()));
2298 }
2299
2300 let signal = options.signal.as_deref();
2302
2303 let promise = self.pipe_to(
2306 cx,
2307 &global,
2308 &transform.writable,
2309 options.preventClose,
2310 options.preventAbort,
2311 options.preventCancel,
2312 signal,
2313 );
2314
2315 promise.set_promise_is_handled(cx);
2317
2318 Ok(transform.readable.clone())
2320 }
2321}
2322
2323pub(crate) fn get_type_and_value_from_message(
2327 cx: &mut JSContext,
2328 data: SafeHandleValue,
2329 value: SafeMutableHandleValue,
2330) -> DOMString {
2331 assert!(data.is_object());
2337 rooted!(&in(cx) let data_object = data.to_object());
2338
2339 let type_ = get_property::<DOMString>(
2341 cx,
2342 data_object.handle(),
2343 c"type",
2344 StringificationBehavior::Empty,
2345 );
2346
2347 get_property_jsval(cx, data_object.handle(), c"value", value)
2349 .expect("Getting the value should not fail.");
2350
2351 type_
2353 .expect("The type of the message should be a string")
2354 .expect("Property should be present")
2355}
2356
2357impl js::gc::Rootable for CrossRealmTransformReadable {}
2358
2359#[derive(Clone, JSTraceable, MallocSizeOf)]
2363#[cfg_attr(crown, crown::unrooted_must_root_lint::must_root)]
2364pub(crate) struct CrossRealmTransformReadable {
2365 controller: Dom<ReadableStreamDefaultController>,
2367}
2368
2369impl CrossRealmTransformReadable {
2370 pub(crate) fn handle_message(
2373 &self,
2374 cx: &mut CurrentRealm,
2375 global: &GlobalScope,
2376 port: &MessagePort,
2377 message: SafeHandleValue,
2378 ) {
2379 rooted!(&in(cx) let mut value = UndefinedValue());
2380 let type_string = get_type_and_value_from_message(cx, message, value.handle_mut());
2381
2382 if type_string == "chunk" {
2384 self.controller
2386 .enqueue(cx, value.handle())
2387 .expect("Enqueing a chunk should not fail.");
2388 }
2389
2390 if type_string == "close" {
2392 self.controller.close(cx);
2394
2395 global.disentangle_port(cx, port);
2397 }
2398
2399 if type_string == "error" {
2401 self.controller.error(cx, value.handle());
2403
2404 global.disentangle_port(cx, port);
2406 }
2407 }
2408
2409 pub(crate) fn handle_error(
2412 &self,
2413 cx: &mut CurrentRealm,
2414 global: &GlobalScope,
2415 port: &MessagePort,
2416 ) {
2417 let error = DOMException::new(cx, global, DOMErrorName::DataCloneError);
2419 rooted!(&in(cx) let mut rooted_error = UndefinedValue());
2420 error.to_jsval(cx, rooted_error.handle_mut());
2421
2422 port.cross_realm_transform_send_error(cx, rooted_error.handle());
2424
2425 self.controller.error(cx, rooted_error.handle());
2427
2428 global.disentangle_port(cx, port);
2430 }
2431}
2432
2433pub(crate) fn get_read_promise_done(
2435 cx: &mut JSContext,
2436 v: &SafeHandleValue,
2437) -> Result<bool, Error> {
2438 if !v.is_object() {
2439 return Err(Error::Type(c"Unknown format for done property.".to_owned()));
2440 }
2441
2442 rooted!(&in(cx) let object = v.to_object());
2443 get_property::<bool>(cx, object.handle(), c"done", ())?
2444 .ok_or(Error::Type(c"Promise has no done property.".to_owned()))
2445}
2446
2447pub(crate) fn get_read_promise_bytes(
2449 cx: &mut JSContext,
2450 v: &SafeHandleValue,
2451) -> Result<Vec<u8>, Error> {
2452 if !v.is_object() {
2453 return Err(Error::Type(
2454 c"Unknown format for for bytes read.".to_owned(),
2455 ));
2456 }
2457
2458 rooted!(&in(cx) let object = v.to_object());
2459 get_property::<Vec<u8>>(
2460 cx,
2461 object.handle(),
2462 c"value",
2463 ConversionBehavior::EnforceRange,
2464 )?
2465 .ok_or(Error::Type(c"Promise has no value property.".to_owned()))
2466}
2467
2468pub(crate) fn bytes_from_chunk_jsval(
2472 cx: &mut JSContext,
2473 chunk: &RootedTraceableBox<Heap<JSVal>>,
2474) -> Result<Vec<u8>, Error> {
2475 match Vec::<u8>::from_jsval(cx, chunk.handle(), ConversionBehavior::EnforceRange) {
2476 Ok(ConversionResult::Success(vec)) => Ok(vec),
2477 Ok(ConversionResult::Failure(error)) => Err(Error::Type(error.into_owned())),
2478 _ => Err(Error::Type(c"Unknown format for bytes read.".to_owned())),
2479 }
2480}
2481
2482impl Transferable for ReadableStream {
2484 type Index = MessagePortIndex;
2485 type Data = MessagePortImpl;
2486
2487 fn transfer(&self, cx: &mut JSContext) -> Fallible<(MessagePortId, MessagePortImpl)> {
2489 if self.is_locked() {
2492 return Err(Error::DataClone(None));
2493 }
2494
2495 let global = self.global();
2496 let mut realm = enter_auto_realm(cx, &*global);
2497 let mut realm = realm.current_realm();
2498 let cx = &mut realm;
2499
2500 let port_1 = MessagePort::new(cx, &global);
2502 global.track_message_port(&port_1, None);
2503
2504 let port_2 = MessagePort::new(cx, &global);
2506 global.track_message_port(&port_2, None);
2507
2508 global.entangle_ports(*port_1.message_port_id(), *port_2.message_port_id());
2510
2511 let writable = WritableStream::new_with_proto(cx, &global, None);
2513
2514 writable.setup_cross_realm_transform_writable(cx, &port_1);
2516
2517 let promise = self.pipe_to(cx, &global, &writable, false, false, false, None);
2519
2520 promise.set_promise_is_handled(cx);
2522
2523 port_2.transfer(cx)
2525 }
2526
2527 fn transfer_receive(
2529 cx: &mut JSContext,
2530 owner: &GlobalScope,
2531 id: MessagePortId,
2532 port_impl: MessagePortImpl,
2533 ) -> Result<DomRoot<Self>, ()> {
2534 let value = ReadableStream::new_with_proto(cx, owner, None);
2537
2538 let transferred_port = MessagePort::transfer_receive(cx, owner, id, port_impl)?;
2545
2546 value.setup_cross_realm_transform_readable(cx, &transferred_port);
2548 Ok(value)
2549 }
2550
2551 fn serialized_storage<'a>(
2553 data: StructuredData<'a, '_>,
2554 ) -> &'a mut Option<FxHashMap<MessagePortId, Self::Data>> {
2555 match data {
2556 StructuredData::Reader(r) => &mut r.port_impls,
2557 StructuredData::Writer(w) => &mut w.ports,
2558 }
2559 }
2560}
2561
2562pub(crate) fn pipe_through(
2569 source: &ReadableStream,
2570 cx: &mut JSContext,
2571 global: &GlobalScope,
2572 transform: &TextDecoderStream,
2573) -> DomRoot<ReadableStream> {
2574 let mut realm = CurrentRealm::assert(cx);
2580 let promise = source.pipe_to(
2583 &mut realm,
2584 global,
2585 &transform.Writable(),
2586 false, false, false, None, );
2591
2592 promise.set_promise_is_handled(cx);
2594 transform.Readable()
2596}