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::{FromJSValConvertible, 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::codegen::Bindings::QueuingStrategyBinding::QueuingStrategySize;
39use crate::dom::abortsignal::{AbortAlgorithm, AbortSignal};
40use crate::dom::bindings::codegen::Bindings::ReadableStreamDefaultReaderBinding::ReadableStreamDefaultReaderMethods;
41use crate::dom::bindings::codegen::Bindings::ReadableStreamDefaultControllerBinding::ReadableStreamDefaultController_Binding::ReadableStreamDefaultControllerMethods;
42use crate::dom::bindings::codegen::Bindings::UnderlyingSourceBinding::UnderlyingSource as JsUnderlyingSource;
43use crate::dom::bindings::conversions::{ConversionBehavior, ConversionResult, get_property, get_property_jsval};
44use crate::dom::bindings::error::{Error, ErrorToJsval, Fallible};
45use crate::dom::bindings::codegen::GenericBindings::WritableStreamDefaultWriterBinding::WritableStreamDefaultWriter_Binding::WritableStreamDefaultWriterMethods;
46use crate::dom::stream::writablestream::WritableStream;
47use crate::dom::bindings::codegen::UnionTypes::ReadableStreamDefaultReaderOrReadableStreamBYOBReader as ReadableStreamReader;
48use crate::dom::bindings::reflector::DomGlobal;
49use script_bindings::reflector::{Reflector, reflect_dom_object_with_proto};
50use crate::dom::bindings::root::{DomRoot, MutNullableDom, Dom};
51use crate::dom::bindings::trace::RootedTraceableBox;
52use crate::dom::stream::byteteeunderlyingsource::{ByteTeeCancelAlgorithm, ByteTeePullAlgorithm, ByteTeeUnderlyingSource};
53use crate::dom::stream::countqueuingstrategy::{extract_high_water_mark, extract_size_algorithm};
54use crate::dom::stream::readablestreamgenericreader::ReadableStreamGenericReader;
55use crate::dom::globalscope::GlobalScope;
56use crate::dom::promise::{wait_for_all_promise, Promise, RootedPromise, TracedPromise};
57use crate::dom::stream::readablebytestreamcontroller::ReadableByteStreamController;
58use crate::dom::stream::readablestreambyobreader::ReadableStreamBYOBReader;
59use crate::dom::stream::readablestreamdefaultcontroller::ReadableStreamDefaultController;
60use crate::dom::stream::readablestreamdefaultreader::{ReadRequest, ReadableStreamDefaultReader};
61use crate::dom::stream::defaultteeunderlyingsource::DefaultTeeCancelAlgorithm;
62use crate::dom::types::DefaultTeeUnderlyingSource;
63use crate::dom::stream::underlyingsourcecontainer::UnderlyingSourceType;
64use crate::dom::stream::writablestreamdefaultwriter::WritableStreamDefaultWriter;
65use script_bindings::codegen::GenericBindings::MessagePortBinding::MessagePortMethods;
66use crate::dom::messageport::MessagePort;
67use crate::realms::{enter_auto_realm};
68use crate::dom::promisenativehandler::{Callback, PromiseNativeHandler};
69use crate::dom::bindings::transferable::Transferable;
70use crate::dom::bindings::structuredclone::StructuredData;
71
72use super::readablestreambyobreader::ReadIntoRequest;
73use crate::dom::bindings::buffer_source::{HeapBufferSource, create_buffer_source};
74
75#[derive(Clone, Debug, Default, MallocSizeOf, PartialEq)]
77enum PipeToState {
78 #[default]
80 Starting,
81 PendingReady,
83 PendingRead,
85 ShuttingDownWithPendingWrites(Option<ShutdownAction>),
88 ShuttingDownPendingAction,
92 Finalized,
95}
96
97#[derive(Clone, Debug, MallocSizeOf, PartialEq)]
99enum ShutdownAction {
100 WritableStreamAbort,
102 ReadableStreamCancel,
104 WritableStreamDefaultWriterCloseWithErrorPropagation,
106 Abort,
108}
109
110impl js::gc::Rootable for PipeTo {}
111
112#[derive(Clone, JSTraceable, MallocSizeOf)]
121#[cfg_attr(crown, crown::unrooted_must_root_lint::must_root)]
122pub(crate) struct PipeTo {
123 reader: Dom<ReadableStreamDefaultReader>,
125
126 writer: Dom<WritableStreamDefaultWriter>,
128
129 #[ignore_malloc_size_of = "nested Rc"]
132 pending_writes: Rc<RefCell<VecDeque<TracedPromise>>>,
133
134 #[conditional_malloc_size_of]
136 #[no_trace]
137 state: Rc<RefCell<PipeToState>>,
138
139 prevent_abort: bool,
141
142 prevent_cancel: bool,
144
145 prevent_close: bool,
147
148 #[conditional_malloc_size_of]
151 shutting_down: Rc<Cell<bool>>,
152
153 #[ignore_malloc_size_of = "mozjs"]
156 abort_reason: Rc<Heap<JSVal>>,
157
158 #[ignore_malloc_size_of = "mozjs"]
161 shutdown_error: Rc<RefCell<Option<Heap<JSVal>>>>,
162
163 #[conditional_malloc_size_of]
166 shutdown_action_promise: Rc<RefCell<Option<TracedPromise>>>,
167
168 result_promise: TracedPromise,
171}
172
173impl PipeTo {
174 pub(crate) fn abort_with_reason(
177 &self,
178 cx: &mut CurrentRealm,
179 global: &GlobalScope,
180 reason: SafeHandleValue,
181 ) {
182 if self.shutting_down.get() {
184 return;
185 }
186
187 self.abort_reason.set(reason.get());
191
192 self.set_shutdown_error(reason);
197
198 self.shutdown(cx, global, Some(ShutdownAction::Abort));
204 }
205}
206
207impl Callback for PipeTo {
208 fn callback(&self, cx: &mut CurrentRealm, result: SafeHandleValue) {
217 let global = self.reader.global();
218
219 self.pending_writes.borrow_mut().retain(|p| {
225 let pending = p.is_pending();
226 if !pending {
227 p.set_promise_is_handled(cx);
228 }
229 pending
230 });
231
232 let state_before_checks = self.state.borrow().clone();
234
235 if state_before_checks == PipeToState::PendingRead {
242 let source = self.reader.get_stream().expect("Source stream must be set");
243 if source.is_closed() {
244 let dest = self
245 .writer
246 .get_stream()
247 .expect("Destination stream must be set");
248
249 if dest.is_writable() && !dest.close_queued_or_in_flight() {
252 let Ok(done) = get_read_promise_done(cx, &result) else {
253 return;
260 };
261
262 if !done {
263 self.write_chunk(cx, &global, result);
265 }
266 }
267 }
268 }
269
270 self.check_and_propagate_errors_forward(cx, &global);
271 self.check_and_propagate_errors_backward(cx, &global);
272 self.check_and_propagate_closing_forward(cx, &global);
273 self.check_and_propagate_closing_backward(cx, &global);
274
275 let state = self.state.borrow().clone();
277
278 if state != state_before_checks {
282 return;
283 }
284
285 match state {
286 PipeToState::Starting => unreachable!("PipeTo should not be in the Starting state."),
287 PipeToState::PendingReady => {
288 self.read_chunk(cx, &global);
290 },
291 PipeToState::PendingRead => {
292 self.write_chunk(cx, &global, result);
294
295 if self.shutting_down.get() {
297 return;
298 }
299
300 self.wait_for_writer_ready(cx, &global);
302 },
303 PipeToState::ShuttingDownWithPendingWrites(action) => {
304 if let Some(write) = self.pending_writes.borrow().front() {
307 self.wait_on_pending_write(cx, &global, write);
308 return;
309 }
310
311 if let Some(action) = action {
313 self.perform_action(cx, &global, action);
315 } else {
316 self.finalize(cx, &global);
318 }
319 },
320 PipeToState::ShuttingDownPendingAction => {
321 let Some(ref promise) = *self.shutdown_action_promise.borrow() else {
322 unreachable!();
323 };
324 if promise.is_pending() {
325 return;
329 }
330
331 let is_array_like = {
332 if !result.is_object() {
333 false
334 } else {
335 is_array_like::<crate::DomTypeHolder>(cx, result)
336 }
337 };
338
339 if !result.is_undefined() && !is_array_like {
341 self.set_shutdown_error(result);
351 }
352 self.finalize(cx, &global);
353 },
354 PipeToState::Finalized => {},
355 }
356 }
357}
358
359impl PipeTo {
360 fn set_shutdown_error(&self, error: SafeHandleValue) {
363 *self.shutdown_error.borrow_mut() = Some(Heap::default());
364 let Some(ref heap) = *self.shutdown_error.borrow() else {
365 unreachable!("Option set to Some(heap) above.");
366 };
367 heap.set(error.get())
368 }
369
370 fn wait_for_writer_ready(&self, cx: &mut CurrentRealm, global: &GlobalScope) {
373 {
374 let mut state = self.state.borrow_mut();
375 *state = PipeToState::PendingReady;
376 }
377
378 let ready_promise = self.writer.Ready(cx);
379 if ready_promise.is_fulfilled() {
380 self.read_chunk(cx, global);
381 } else {
382 let handler = PromiseNativeHandler::new(
383 cx,
384 global,
385 Some(Box::new(self.clone())),
386 Some(Box::new(self.clone())),
387 );
388 ready_promise.append_native_handler(cx, &handler);
389
390 let closed_promise = self.reader.Closed(cx);
394 closed_promise.append_native_handler(cx, &handler);
395 }
396 }
397
398 fn read_chunk(&self, cx: &mut CurrentRealm, global: &GlobalScope) {
400 *self.state.borrow_mut() = PipeToState::PendingRead;
401 let chunk_promise = self.reader.Read(cx);
402 let handler = PromiseNativeHandler::new(
403 cx,
404 global,
405 Some(Box::new(self.clone())),
406 Some(Box::new(self.clone())),
407 );
408 chunk_promise.append_native_handler(cx, &handler);
409
410 let ready_promise = self.writer.Closed(cx);
413 ready_promise.append_native_handler(cx, &handler);
414 }
415
416 fn write_chunk(
419 &self,
420 cx: &mut JSContext,
421 global: &GlobalScope,
422 chunk: SafeHandleValue,
423 ) -> bool {
424 if chunk.is_object() {
425 rooted!(&in(cx) let object = chunk.to_object());
426 rooted!(&in(cx) let mut bytes = UndefinedValue());
427 get_property_jsval(cx, object.handle(), c"value", bytes.handle_mut())
428 .expect("Chunk should have a value.");
429
430 let write_promise = self.writer.write(cx, global, bytes.handle());
432 self.pending_writes
433 .borrow_mut()
434 .push_back(write_promise.to_traced());
435 return true;
436 }
437 false
438 }
439
440 fn wait_on_pending_write(
444 &self,
445 cx: &mut CurrentRealm,
446 global: &GlobalScope,
447 promise: &Promise,
448 ) {
449 let handler = PromiseNativeHandler::new(
450 cx,
451 global,
452 Some(Box::new(self.clone())),
453 Some(Box::new(self.clone())),
454 );
455 promise.append_native_handler(cx, &handler);
456 }
457
458 fn check_and_propagate_errors_forward(&self, cx: &mut CurrentRealm, global: &GlobalScope) {
461 if self.shutting_down.get() {
464 return;
465 }
466
467 let source = self
469 .reader
470 .get_stream()
471 .expect("Reader should still have a stream");
472 if source.is_errored() {
473 rooted!(&in(cx) let mut source_error = UndefinedValue());
474 source.get_stored_error(source_error.handle_mut());
475 self.set_shutdown_error(source_error.handle());
476
477 if !self.prevent_abort {
479 self.shutdown(cx, global, Some(ShutdownAction::WritableStreamAbort))
482 } else {
483 self.shutdown(cx, global, None);
485 }
486 }
487 }
488
489 fn check_and_propagate_errors_backward(&self, cx: &mut CurrentRealm, global: &GlobalScope) {
492 if self.shutting_down.get() {
495 return;
496 }
497
498 let dest = self
500 .writer
501 .get_stream()
502 .expect("Writer should still have a stream");
503 if dest.is_errored() {
504 rooted!(&in(cx) let mut dest_error = UndefinedValue());
505 dest.get_stored_error(dest_error.handle_mut());
506 self.set_shutdown_error(dest_error.handle());
507
508 if !self.prevent_cancel {
510 self.shutdown(cx, global, Some(ShutdownAction::ReadableStreamCancel))
513 } else {
514 self.shutdown(cx, global, None);
516 }
517 }
518 }
519
520 fn check_and_propagate_closing_forward(&self, cx: &mut CurrentRealm, global: &GlobalScope) {
523 if self.shutting_down.get() {
526 return;
527 }
528
529 let source = self
531 .reader
532 .get_stream()
533 .expect("Reader should still have a stream");
534 if source.is_closed() {
535 if !self.prevent_close {
537 self.shutdown(
540 cx,
541 global,
542 Some(ShutdownAction::WritableStreamDefaultWriterCloseWithErrorPropagation),
543 )
544 } else {
545 self.shutdown(cx, global, None);
547 }
548 }
549 }
550
551 fn check_and_propagate_closing_backward(&self, cx: &mut CurrentRealm, global: &GlobalScope) {
554 if self.shutting_down.get() {
557 return;
558 }
559
560 let dest = self
563 .writer
564 .get_stream()
565 .expect("Writer should still have a stream");
566 if dest.close_queued_or_in_flight() || dest.is_closed() {
567 rooted!(&in(cx) let mut dest_closed = UndefinedValue());
572 let error =
573 Error::Type(c"Destination is closed or has closed queued or in flight".to_owned());
574 error.to_jsval(cx, global, dest_closed.handle_mut());
575 self.set_shutdown_error(dest_closed.handle());
576
577 if !self.prevent_cancel {
579 self.shutdown(cx, global, Some(ShutdownAction::ReadableStreamCancel))
582 } else {
583 self.shutdown(cx, global, None);
585 }
586 }
587 }
588
589 fn shutdown(
593 &self,
594 cx: &mut CurrentRealm,
595 global: &GlobalScope,
596 action: Option<ShutdownAction>,
597 ) {
598 if !self.shutting_down.replace(true) {
601 let dest = self.writer.get_stream().expect("Stream must be set");
602 if dest.is_writable() && !dest.close_queued_or_in_flight() {
605 if let Some(write) = self.pending_writes.borrow().front() {
611 *self.state.borrow_mut() = PipeToState::ShuttingDownWithPendingWrites(action);
612 self.wait_on_pending_write(cx, global, write);
613 return;
614 }
615 }
616
617 if let Some(action) = action {
619 self.perform_action(cx, global, action);
621 } else {
622 self.finalize(cx, global);
624 }
625 }
626 }
627
628 fn perform_action(&self, cx: &mut CurrentRealm, global: &GlobalScope, action: ShutdownAction) {
631 rooted!(&in(cx) let mut error = UndefinedValue());
632 if let Some(shutdown_error) = self.shutdown_error.borrow().as_ref() {
633 error.set(shutdown_error.get());
634 }
635
636 *self.state.borrow_mut() = PipeToState::ShuttingDownPendingAction;
637
638 let promise = match action {
640 ShutdownAction::WritableStreamAbort => {
641 let dest = self.writer.get_stream().expect("Stream must be set");
642 dest.abort(cx, global, error.handle())
643 },
644 ShutdownAction::ReadableStreamCancel => {
645 let source = self
646 .reader
647 .get_stream()
648 .expect("Reader should have a stream.");
649 source.cancel(cx, global, error.handle())
650 },
651 ShutdownAction::WritableStreamDefaultWriterCloseWithErrorPropagation => {
652 self.writer.close_with_error_propagation(cx, global)
653 },
654 ShutdownAction::Abort => {
655 rooted!(&in(cx) let mut error = UndefinedValue());
660 error.set(self.abort_reason.get());
661
662 let mut actions = vec![];
664
665 if !self.prevent_abort {
667 let dest = self
668 .writer
669 .get_stream()
670 .expect("Destination stream must be set");
671
672 let promise = if dest.is_writable() {
674 dest.abort(cx, global, error.handle())
676 } else {
677 Promise::new_resolved_rooted(cx, global, ())
679 };
680 actions.push(promise);
681 }
682
683 if !self.prevent_cancel {
685 let source = self.reader.get_stream().expect("Source stream must be set");
686
687 let promise = if source.is_readable() {
689 source.cancel(cx, global, error.handle())
691 } else {
692 Promise::new_resolved_rooted(cx, global, ())
694 };
695 actions.push(promise);
696 }
697
698 wait_for_all_promise(cx, global, actions)
702 },
703 };
704
705 let handler = PromiseNativeHandler::new(
708 cx,
709 global,
710 Some(Box::new(self.clone())),
711 Some(Box::new(self.clone())),
712 );
713 promise.append_native_handler(cx, &handler);
714 *self.shutdown_action_promise.borrow_mut() = Some(promise.to_traced());
715 }
716
717 fn finalize(&self, cx: &mut JSContext, global: &GlobalScope) {
719 *self.state.borrow_mut() = PipeToState::Finalized;
720
721 self.writer.release(cx, global);
723
724 self.reader
730 .release(cx)
731 .expect("Releasing the reader should not fail");
732
733 if let Some(shutdown_error) = self.shutdown_error.borrow().as_ref() {
739 rooted!(&in(cx) let mut error = UndefinedValue());
740 error.set(shutdown_error.get());
741 self.result_promise.reject_native(cx, &error.handle());
743 } else {
744 self.result_promise.resolve_native(cx, &());
746 }
747 }
748}
749
750#[derive(Clone, JSTraceable, MallocSizeOf)]
753#[cfg_attr(crown, crown::unrooted_must_root_lint::must_root)]
754struct SourceCancelPromiseFulfillmentHandler {
755 result: TracedPromise,
756}
757
758impl SourceCancelPromiseFulfillmentHandler {
759 fn new(promise: &RootedPromise) -> Box<Self> {
760 Box::new(Self {
761 result: promise.to_traced(),
762 })
763 }
764}
765
766impl Callback for SourceCancelPromiseFulfillmentHandler {
767 fn callback(&self, cx: &mut CurrentRealm, _v: SafeHandleValue) {
771 self.result.resolve_native(cx, &());
772 }
773}
774
775#[derive(Clone, JSTraceable, MallocSizeOf)]
778#[cfg_attr(crown, crown::unrooted_must_root_lint::must_root)]
779struct SourceCancelPromiseRejectionHandler {
780 result: TracedPromise,
781}
782
783impl SourceCancelPromiseRejectionHandler {
784 fn new(promise: &RootedPromise) -> Box<Self> {
785 Box::new(Self {
786 result: promise.to_traced(),
787 })
788 }
789}
790
791impl Callback for SourceCancelPromiseRejectionHandler {
792 fn callback(&self, cx: &mut CurrentRealm, v: SafeHandleValue) {
796 self.result.reject_native(cx, &v);
797 }
798}
799
800#[derive(Clone, Copy, Debug, Default, JSTraceable, MallocSizeOf, PartialEq)]
802pub(crate) enum ReadableStreamState {
803 #[default]
804 Readable,
805 Closed,
806 Errored,
807}
808
809#[derive(JSTraceable, MallocSizeOf)]
811#[cfg_attr(crown, crown::unrooted_must_root_lint::must_root)]
812pub(crate) enum ControllerType {
813 Byte(MutNullableDom<ReadableByteStreamController>),
815 Default(MutNullableDom<ReadableStreamDefaultController>),
817}
818
819#[derive(JSTraceable, MallocSizeOf)]
821#[cfg_attr(crown, crown::unrooted_must_root_lint::must_root)]
822pub(crate) enum ReaderType {
823 #[allow(clippy::upper_case_acronyms)]
825 BYOB(MutNullableDom<ReadableStreamBYOBReader>),
826 Default(MutNullableDom<ReadableStreamDefaultReader>),
828}
829
830impl js::gc::Rootable for ReaderType {}
831
832impl Eq for ReaderType {}
833impl PartialEq for ReaderType {
834 fn eq(&self, other: &Self) -> bool {
835 matches!(
836 (self, other),
837 (ReaderType::BYOB(_), ReaderType::BYOB(_)) |
838 (ReaderType::Default(_), ReaderType::Default(_))
839 )
840 }
841}
842
843pub(crate) fn create_readable_stream(
845 cx: &mut JSContext,
846 global: &GlobalScope,
847 underlying_source_type: UnderlyingSourceType,
848 queuing_strategy: Option<Rc<QueuingStrategySize>>,
849 high_water_mark: Option<f64>,
850) -> DomRoot<ReadableStream> {
851 let high_water_mark = high_water_mark.unwrap_or(1.0);
853
854 let size_algorithm =
856 queuing_strategy.unwrap_or(extract_size_algorithm(cx, &QueuingStrategy::empty()));
857
858 assert!(high_water_mark >= 0.0);
860
861 let stream = ReadableStream::new_with_proto(cx, global, None);
864
865 let controller = ReadableStreamDefaultController::new(
867 cx,
868 global,
869 underlying_source_type,
870 high_water_mark,
871 size_algorithm,
872 );
873
874 controller
877 .setup(cx, &stream)
878 .expect("Setup of default controller cannot fail");
879
880 stream
882}
883
884fn readable_byte_stream_tee(
886 cx: &mut JSContext,
887 global: &GlobalScope,
888 underlying_source_type: UnderlyingSourceType,
889) -> DomRoot<ReadableStream> {
890 let tee_stream = ReadableStream::new_with_proto(cx, global, None);
893
894 let controller = ReadableByteStreamController::new(cx, underlying_source_type, 0.0, global);
896
897 controller
899 .setup(cx, global, &tee_stream)
900 .expect("Setup of byte stream controller cannot fail");
901
902 tee_stream
904}
905
906#[dom_struct]
908pub(crate) struct ReadableStream {
909 reflector_: Reflector,
910
911 controller: RefCell<Option<ControllerType>>,
915
916 #[ignore_malloc_size_of = "mozjs"]
918 stored_error: Heap<JSVal>,
919
920 disturbed: Cell<bool>,
922
923 reader: RefCell<Option<ReaderType>>,
925
926 state: Cell<ReadableStreamState>,
928}
929
930impl ReadableStream {
931 fn new_inherited() -> ReadableStream {
933 ReadableStream {
934 reflector_: Reflector::new(),
935 controller: RefCell::new(None),
936 stored_error: Heap::default(),
937 disturbed: Default::default(),
938 reader: RefCell::new(None),
939 state: Cell::new(Default::default()),
940 }
941 }
942
943 pub(crate) fn new_with_proto(
944 cx: &mut JSContext,
945 global: &GlobalScope,
946 proto: Option<SafeHandleObject>,
947 ) -> DomRoot<ReadableStream> {
948 reflect_dom_object_with_proto(cx, Box::new(ReadableStream::new_inherited()), global, proto)
949 }
950
951 pub(crate) fn set_default_controller(&self, controller: &ReadableStreamDefaultController) {
954 *self.controller.borrow_mut() = Some(ControllerType::Default(MutNullableDom::new(Some(
955 controller,
956 ))));
957 }
958
959 pub(crate) fn set_byte_controller(&self, controller: &ReadableByteStreamController) {
962 *self.controller.borrow_mut() =
963 Some(ControllerType::Byte(MutNullableDom::new(Some(controller))));
964 }
965
966 pub(crate) fn assert_no_controller(&self) {
969 let has_no_controller = self.controller.borrow().is_none();
970 assert!(has_no_controller);
971 }
972
973 pub(crate) fn new_from_bytes(
975 cx: &mut JSContext,
976 global: &GlobalScope,
977 bytes: Vec<u8>,
978 ) -> Fallible<DomRoot<ReadableStream>> {
979 let stream = ReadableStream::new_with_external_underlying_source(
980 cx,
981 global,
982 UnderlyingSourceType::Memory(bytes.len()),
983 )?;
984 stream.enqueue_native(cx, bytes);
985 stream.controller_close_native(cx);
986 Ok(stream)
987 }
988
989 pub(crate) fn new_empty(
992 cx: &mut JSContext,
993 global: &GlobalScope,
994 ) -> Fallible<DomRoot<ReadableStream>> {
995 let empty_stream = ReadableStream::new_with_external_underlying_source(
998 cx,
999 global,
1000 UnderlyingSourceType::Memory(0),
1001 )?;
1002 empty_stream.controller_close_native(cx);
1004 Ok(empty_stream)
1006 }
1007
1008 pub(crate) fn new_from_bytes_with_byte_reading_support(
1010 cx: &mut JSContext,
1011 global: &GlobalScope,
1012 bytes: Vec<u8>,
1013 ) -> Fallible<DomRoot<ReadableStream>> {
1014 let stream = ReadableStream::new_with_external_underlying_byte_source(
1015 cx,
1016 global,
1017 UnderlyingSourceType::Memory(bytes.len()),
1018 )?;
1019 stream.enqueue_native(cx, bytes);
1020 stream.controller_close_native(cx);
1021 Ok(stream)
1022 }
1023
1024 pub(crate) fn new_with_external_underlying_source(
1027 cx: &mut JSContext,
1028 global: &GlobalScope,
1029 source: UnderlyingSourceType,
1030 ) -> Fallible<DomRoot<ReadableStream>> {
1031 assert!(source.is_native());
1032 let stream = ReadableStream::new_with_proto(cx, global, None);
1033 let strategy_size = extract_size_algorithm(cx, &QueuingStrategy::empty());
1034 let controller =
1035 ReadableStreamDefaultController::new(cx, global, source, 1.0, strategy_size);
1036 controller.setup(cx, &stream)?;
1037 Ok(stream)
1038 }
1039
1040 pub(crate) fn new_with_external_underlying_byte_source(
1042 cx: &mut JSContext,
1043 global: &GlobalScope,
1044 source: UnderlyingSourceType,
1045 ) -> Fallible<DomRoot<ReadableStream>> {
1046 assert!(source.is_native());
1047 let stream = ReadableStream::new_with_proto(cx, global, None);
1048 let controller = ReadableByteStreamController::new(cx, source, 0.0, global);
1049 controller.setup(cx, global, &stream)?;
1050 Ok(stream)
1051 }
1052
1053 pub(crate) fn perform_release_steps(&self) -> Fallible<()> {
1055 match self.controller.borrow().as_ref() {
1056 Some(ControllerType::Default(controller)) => {
1057 let controller = controller
1058 .get()
1059 .ok_or_else(|| Error::Type(c"Stream should have controller.".to_owned()))?;
1060 controller.perform_release_steps()
1061 },
1062 Some(ControllerType::Byte(controller)) => {
1063 let controller = controller
1064 .get()
1065 .ok_or_else(|| Error::Type(c"Stream should have controller.".to_owned()))?;
1066 controller.perform_release_steps()
1067 },
1068 None => Err(Error::Type(c"Stream should have controller.".to_owned())),
1069 }
1070 }
1071
1072 pub(crate) fn perform_pull_steps(&self, cx: &mut JSContext, read_request: &ReadRequest) {
1076 match self.controller.borrow().as_ref() {
1077 Some(ControllerType::Default(controller)) => controller
1078 .get()
1079 .expect("Stream should have controller.")
1080 .perform_pull_steps(cx, read_request),
1081 Some(ControllerType::Byte(controller)) => controller
1082 .get()
1083 .expect("Stream should have controller.")
1084 .perform_pull_steps(cx, read_request),
1085 None => {
1086 unreachable!("Stream does not have a controller.");
1087 },
1088 }
1089 }
1090
1091 pub(crate) fn perform_pull_into(
1095 &self,
1096 cx: &mut JSContext,
1097 read_into_request: &ReadIntoRequest,
1098 view: &HeapBufferSource<ArrayBufferViewU8>,
1099 min: u64,
1100 ) {
1101 match self.controller.borrow().as_ref() {
1102 Some(ControllerType::Byte(controller)) => controller
1103 .get()
1104 .expect("Stream should have controller.")
1105 .perform_pull_into(cx, read_into_request, view, min),
1106 _ => {
1107 unreachable!(
1108 "Pulling a chunk from a stream with a default controller using a BYOB reader"
1109 )
1110 },
1111 }
1112 }
1113
1114 pub(crate) fn add_read_request(&self, read_request: &ReadRequest) {
1116 match self.reader.borrow().as_ref() {
1117 Some(ReaderType::Default(reader)) => {
1118 let Some(reader) = reader.get() else {
1119 panic!("Attempt to add a read request without having first acquired a reader.");
1120 };
1121
1122 assert!(self.is_readable());
1124
1125 reader.add_read_request(read_request);
1127 },
1128 _ => {
1129 unreachable!("Adding a read request can only be done on a default reader.")
1130 },
1131 }
1132 }
1133
1134 pub(crate) fn add_read_into_request(&self, read_request: &ReadIntoRequest) {
1136 match self.reader.borrow().as_ref() {
1137 Some(ReaderType::BYOB(reader)) => {
1139 let Some(reader) = reader.get() else {
1140 unreachable!(
1141 "Attempt to add a read into request without having first acquired a reader."
1142 );
1143 };
1144
1145 assert!(self.is_readable() || self.is_closed());
1147
1148 reader.add_read_into_request(read_request);
1150 },
1151 _ => {
1152 unreachable!("Adding a read into request can only be done on a BYOB reader.")
1153 },
1154 }
1155 }
1156
1157 pub(crate) fn enqueue_native(&self, cx: &mut JSContext, bytes: Vec<u8>) {
1159 match self.controller.borrow().as_ref() {
1160 Some(ControllerType::Default(controller)) => controller
1161 .get()
1162 .expect("Stream should have controller.")
1163 .enqueue_native(cx, bytes),
1164 Some(ControllerType::Byte(controller)) => {
1165 if bytes.is_empty() {
1166 return;
1167 }
1168
1169 let controller = controller.get().expect("Stream should have controller.");
1170 rooted!(&in(cx) let mut chunk_object = ptr::null_mut::<JSObject>());
1171 create_buffer_source::<Uint8>(cx, &bytes, chunk_object.handle_mut())
1172 .expect("failed to create buffer source for native byte chunk.");
1173
1174 let chunk = RootedTraceableBox::new(HeapBufferSource::<ArrayBufferViewU8>::new(
1175 chunk_object.handle(),
1176 ));
1177 controller
1178 .enqueue(cx, chunk)
1179 .expect("Enqueuing a native byte chunk should not fail.");
1180 },
1181 _ => {
1182 unreachable!("Enqueueing chunk to a stream from Rust without a controller");
1183 },
1184 }
1185 }
1186
1187 pub(crate) fn error(&self, cx: &mut JSContext, e: SafeHandleValue) {
1189 assert!(self.is_readable());
1191
1192 self.state.set(ReadableStreamState::Errored);
1194
1195 self.stored_error.set(e.get());
1197
1198 let default_reader = {
1201 let reader_ref = self.reader.borrow();
1202 match reader_ref.as_ref() {
1203 Some(ReaderType::Default(reader)) => reader.get(),
1204 _ => None,
1205 }
1206 };
1207
1208 if let Some(reader) = default_reader {
1209 reader.error(cx, e);
1211 return;
1212 }
1213
1214 let byob_reader = {
1215 let reader_ref = self.reader.borrow();
1216 match reader_ref.as_ref() {
1217 Some(ReaderType::BYOB(reader)) => reader.get(),
1218 _ => None,
1219 }
1220 };
1221
1222 if let Some(reader) = byob_reader {
1223 reader.error_read_into_requests(cx, e);
1225 }
1226
1227 }
1229
1230 pub(crate) fn get_stored_error(&self, mut handle_mut: SafeMutableHandleValue) {
1232 handle_mut.set(self.stored_error.get());
1233 }
1234
1235 pub(crate) fn error_native(&self, cx: &mut JSContext, error: Error) {
1238 rooted!(&in(cx) let mut error_val = UndefinedValue());
1239 error.to_jsval(cx, &self.global(), error_val.handle_mut());
1240 self.error(cx, error_val.handle());
1241 }
1242
1243 pub(crate) fn controller_close_native(&self, cx: &mut JSContext) {
1246 match self.controller.borrow().as_ref() {
1247 Some(ControllerType::Default(controller)) => {
1248 let _ = controller
1249 .get()
1250 .expect("Stream should have controller.")
1251 .Close(cx);
1252 },
1253 Some(ControllerType::Byte(controller)) => {
1254 let _ = controller
1255 .get()
1256 .expect("Stream should have controller.")
1257 .close(cx);
1258 },
1259 _ => {
1260 unreachable!("Native closing requires a stream controller.")
1261 },
1262 }
1263 }
1264
1265 pub(crate) fn in_memory(&self) -> bool {
1268 match self.controller.borrow().as_ref() {
1269 Some(ControllerType::Default(controller)) => controller
1270 .get()
1271 .expect("Stream should have controller.")
1272 .in_memory(),
1273 Some(ControllerType::Byte(controller)) => controller
1274 .get()
1275 .expect("Stream should have controller.")
1276 .in_memory(),
1277 _ => unreachable!("Checking if source is in memory for a stream without a controller"),
1278 }
1279 }
1280
1281 pub(crate) fn get_in_memory_bytes(&self, cx: &mut JSContext) -> Option<GenericSharedMemory> {
1284 match self.controller.borrow().as_ref() {
1285 Some(ControllerType::Default(controller)) => controller
1286 .get()
1287 .expect("Stream should have controller.")
1288 .get_in_memory_bytes()
1289 .map(GenericSharedMemory::from_vec),
1290 Some(ControllerType::Byte(controller)) => controller
1291 .get()
1292 .expect("Stream should have controller.")
1293 .get_in_memory_bytes(cx)
1294 .map(GenericSharedMemory::from_vec),
1295 _ => unreachable!("Getting in-memory bytes for a stream without a controller"),
1296 }
1297 }
1298
1299 pub(crate) fn acquire_default_reader(
1304 &self,
1305 cx: &mut JSContext,
1306 ) -> Fallible<DomRoot<ReadableStreamDefaultReader>> {
1307 let reader = ReadableStreamDefaultReader::new(cx, &self.global());
1309
1310 reader.set_up(cx, self, &self.global())?;
1312
1313 Ok(reader)
1315 }
1316
1317 pub(crate) fn acquire_byob_reader(
1319 &self,
1320 cx: &mut JSContext,
1321 ) -> Fallible<DomRoot<ReadableStreamBYOBReader>> {
1322 let reader = ReadableStreamBYOBReader::new(cx, &self.global());
1324 reader.set_up(cx, self, &self.global())?;
1326
1327 Ok(reader)
1329 }
1330
1331 pub(crate) fn get_default_controller(&self) -> DomRoot<ReadableStreamDefaultController> {
1332 match self.controller.borrow().as_ref() {
1333 Some(ControllerType::Default(controller)) => {
1334 controller.get().expect("Stream should have controller.")
1335 },
1336 _ => {
1337 unreachable!(
1338 "Getting default controller for a stream with a non-default controller"
1339 )
1340 },
1341 }
1342 }
1343
1344 pub(crate) fn get_byte_controller(&self) -> DomRoot<ReadableByteStreamController> {
1345 match self.controller.borrow().as_ref() {
1346 Some(ControllerType::Byte(controller)) => {
1347 controller.get().expect("Stream should have controller.")
1348 },
1349 _ => {
1350 unreachable!("Getting byte controller for a stream with a non-byte controller")
1351 },
1352 }
1353 }
1354
1355 pub(crate) fn get_default_reader(&self) -> DomRoot<ReadableStreamDefaultReader> {
1356 match self.reader.borrow().as_ref() {
1357 Some(ReaderType::Default(reader)) => reader.get().expect("Stream should have reader."),
1358 _ => {
1359 unreachable!("Getting default reader for a stream with a non-default reader")
1360 },
1361 }
1362 }
1363
1364 pub(crate) fn read_a_chunk(&self, cx: &mut JSContext) -> RootedPromise {
1370 match self.reader.borrow().as_ref() {
1371 Some(ReaderType::Default(reader)) => {
1372 let Some(reader) = reader.get() else {
1373 unreachable!(
1374 "Attempt to read stream chunk without having first acquired a reader."
1375 );
1376 };
1377 reader.Read(cx)
1378 },
1379 _ => {
1380 unreachable!("Native reading of a chunk can only be done with a default reader.")
1381 },
1382 }
1383 }
1384
1385 pub(crate) fn stop_reading(&self, cx: &mut JSContext) {
1390 let reader_ref = self.reader.borrow();
1391
1392 match reader_ref.as_ref() {
1393 Some(ReaderType::Default(reader)) => {
1394 let Some(reader) = reader.get() else {
1395 unreachable!("Attempt to stop reading without having first acquired a reader.");
1396 };
1397
1398 drop(reader_ref);
1399 reader.release(cx).expect("Reader release cannot fail.");
1400 },
1401 _ => {
1402 unreachable!("Native stop reading can only be done with a default reader.")
1403 },
1404 }
1405 }
1406
1407 pub(crate) fn is_locked(&self) -> bool {
1409 match self.reader.borrow().as_ref() {
1410 Some(ReaderType::Default(reader)) => reader.get().is_some(),
1411 Some(ReaderType::BYOB(reader)) => reader.get().is_some(),
1412 None => false,
1413 }
1414 }
1415
1416 pub(crate) fn is_disturbed(&self) -> bool {
1417 self.disturbed.get()
1418 }
1419
1420 pub(crate) fn set_is_disturbed(&self, disturbed: bool) {
1421 self.disturbed.set(disturbed);
1422 }
1423
1424 pub(crate) fn is_closed(&self) -> bool {
1425 self.state.get() == ReadableStreamState::Closed
1426 }
1427
1428 pub(crate) fn is_errored(&self) -> bool {
1429 self.state.get() == ReadableStreamState::Errored
1430 }
1431
1432 pub(crate) fn is_readable(&self) -> bool {
1433 self.state.get() == ReadableStreamState::Readable
1434 }
1435
1436 pub(crate) fn has_default_reader(&self) -> bool {
1437 match self.reader.borrow().as_ref() {
1438 Some(ReaderType::Default(reader)) => reader.get().is_some(),
1439 _ => false,
1440 }
1441 }
1442
1443 pub(crate) fn has_byob_reader(&self) -> bool {
1444 match self.reader.borrow().as_ref() {
1445 Some(ReaderType::BYOB(reader)) => reader.get().is_some(),
1446 _ => false,
1447 }
1448 }
1449
1450 pub(crate) fn has_byte_controller(&self) -> bool {
1451 match self.controller.borrow().as_ref() {
1452 Some(ControllerType::Byte(controller)) => controller.get().is_some(),
1453 _ => false,
1454 }
1455 }
1456
1457 pub(crate) fn get_num_read_requests(&self) -> usize {
1459 match self.reader.borrow().as_ref() {
1460 Some(ReaderType::Default(reader)) => {
1461 let reader = reader
1462 .get()
1463 .expect("Stream must have a reader when getting the number of read requests.");
1464 reader.get_num_read_requests()
1465 },
1466 _ => unreachable!(
1467 "Stream must have a default reader when get num read requests is called into."
1468 ),
1469 }
1470 }
1471
1472 pub(crate) fn get_num_read_into_requests(&self) -> usize {
1474 assert!(self.has_byob_reader());
1475
1476 match self.reader.borrow().as_ref() {
1477 Some(ReaderType::BYOB(reader)) => {
1478 let Some(reader) = reader.get() else {
1479 unreachable!(
1480 "Stream must have a reader when get num read into requests is called into."
1481 );
1482 };
1483 reader.get_num_read_into_requests()
1484 },
1485 _ => {
1486 unreachable!(
1487 "Stream must have a BYOB reader when get num read into requests is called into."
1488 );
1489 },
1490 }
1491 }
1492
1493 pub(crate) fn fulfill_read_request(
1495 &self,
1496 cx: &mut JSContext,
1497 chunk: SafeHandleValue,
1498 done: bool,
1499 ) {
1500 assert!(self.has_default_reader());
1502
1503 match self.reader.borrow().as_ref() {
1504 Some(ReaderType::Default(reader)) => {
1505 let reader = reader
1507 .get()
1508 .expect("Stream must have a reader when a read request is fulfilled.");
1509 assert_ne!(reader.get_num_read_requests(), 0);
1511 rooted!(&in(cx) let request = reader.remove_read_request());
1514
1515 if done {
1516 request.close_steps(cx);
1518 } else {
1519 let result = RootedTraceableBox::new(Heap::default());
1521 result.set(*chunk);
1522 request.chunk_steps(cx, result, &self.global());
1523 }
1524 },
1525 _ => {
1526 unreachable!(
1527 "Stream must have a default reader when fulfill read requests is called into."
1528 );
1529 },
1530 }
1531 }
1532
1533 pub(crate) fn fulfill_read_into_request(
1535 &self,
1536 cx: &mut JSContext,
1537 chunk: SafeHandleValue,
1538 done: bool,
1539 ) {
1540 assert!(self.has_byob_reader());
1542
1543 match self.reader.borrow().as_ref() {
1545 Some(ReaderType::BYOB(reader)) => {
1546 let Some(reader) = reader.get() else {
1547 unreachable!(
1548 "Stream must have a reader when a read into request is fulfilled."
1549 );
1550 };
1551
1552 assert!(reader.get_num_read_into_requests() > 0);
1554
1555 rooted!(&in(cx) let read_into_request = reader.remove_read_into_request());
1558
1559 let result = RootedTraceableBox::new(Heap::default());
1561 if done {
1562 result.set(*chunk);
1563 read_into_request.close_steps(cx, Some(result));
1564 } else {
1565 result.set(*chunk);
1567 read_into_request.chunk_steps(cx, result);
1568 }
1569 },
1570 _ => {
1571 unreachable!(
1572 "Stream must have a BYOB reader when fulfill read into requests is called into."
1573 );
1574 },
1575 };
1576 }
1577
1578 pub(crate) fn close(&self, cx: &mut JSContext) {
1580 assert!(self.is_readable());
1582 self.state.set(ReadableStreamState::Closed);
1584 let default_reader = {
1590 let reader_ref = self.reader.borrow();
1591 match reader_ref.as_ref() {
1592 Some(ReaderType::Default(reader)) => reader.get(),
1593 _ => None,
1594 }
1595 };
1596
1597 if let Some(reader) = default_reader {
1598 reader.close(cx);
1600 return;
1601 }
1602
1603 let byob_reader = {
1605 let reader_ref = self.reader.borrow();
1606 match reader_ref.as_ref() {
1607 Some(ReaderType::BYOB(reader)) => reader.get(),
1608 _ => None,
1609 }
1610 };
1611
1612 if let Some(reader) = byob_reader {
1613 reader.close(cx);
1615 }
1616
1617 }
1619
1620 pub(crate) fn cancel(
1622 &self,
1623 cx: &mut JSContext,
1624 global: &GlobalScope,
1625 reason: SafeHandleValue,
1626 ) -> RootedPromise {
1627 self.disturbed.set(true);
1629
1630 if self.is_closed() {
1632 return Promise::new_resolved_rooted(cx, global, ());
1633 }
1634 if self.is_errored() {
1636 let promise = Promise::new_rooted(cx, global);
1637 rooted!(&in(cx) let mut rval = UndefinedValue());
1638 self.stored_error.to_jsval(cx, rval.handle_mut());
1639 promise.reject_native(cx, &rval.handle());
1640 return promise;
1641 }
1642 self.close(cx);
1644
1645 let byob_reader = {
1647 let reader_ref = self.reader.borrow();
1648 match reader_ref.as_ref() {
1649 Some(ReaderType::BYOB(reader)) => reader.get(),
1650 _ => None,
1651 }
1652 };
1653
1654 if let Some(reader) = byob_reader {
1655 reader.cancel(cx);
1657 }
1658
1659 let source_cancel_promise = match self.controller.borrow().as_ref() {
1662 Some(ControllerType::Default(controller)) => controller
1663 .get()
1664 .expect("Stream should have controller.")
1665 .perform_cancel_steps(cx, global, reason),
1666 Some(ControllerType::Byte(controller)) => controller
1667 .get()
1668 .expect("Stream should have controller.")
1669 .perform_cancel_steps(cx, global, reason),
1670 None => {
1671 panic!("Stream does not have a controller.");
1672 },
1673 };
1674
1675 let global = self.global();
1678 let result_promise = Promise::new_rooted(cx, &global);
1679 rooted!(&in(cx) let mut fulfillment_handler = Some(SourceCancelPromiseFulfillmentHandler::new(&result_promise)));
1680 rooted!(&in(cx) let mut rejection_handler = Some(SourceCancelPromiseRejectionHandler::new(&result_promise)));
1681 let handler = PromiseNativeHandler::new(
1682 cx,
1683 &global,
1684 fulfillment_handler
1685 .take()
1686 .map(|handler| handler as Box<dyn Callback>),
1687 rejection_handler
1688 .take()
1689 .map(|handler| handler as Box<dyn Callback>),
1690 );
1691 let mut realm = enter_auto_realm(cx, &*global);
1692 let cx = &mut realm.current_realm();
1693 source_cancel_promise.append_native_handler(cx, &handler);
1694
1695 result_promise
1698 }
1699
1700 #[cfg_attr(crown, expect(crown::unrooted_must_root))]
1701 pub(crate) fn set_reader(&self, new_reader: Option<ReaderType>) {
1702 *self.reader.borrow_mut() = new_reader;
1703 }
1704
1705 #[cfg_attr(crown, expect(crown::unrooted_must_root))]
1706 fn byte_tee(&self, cx: &mut JSContext) -> Fallible<Vec<DomRoot<ReadableStream>>> {
1708 let reader = self.acquire_default_reader(cx)?;
1713 let reader = Rc::new(RefCell::new(ReaderType::Default(MutNullableDom::new(
1714 Some(&reader),
1715 ))));
1716
1717 let reading = Rc::new(Cell::new(false));
1719
1720 let read_again_for_branch_1 = Rc::new(Cell::new(false));
1722
1723 let read_again_for_branch_2 = Rc::new(Cell::new(false));
1725
1726 let canceled_1 = Rc::new(Cell::new(false));
1728
1729 let canceled_2 = Rc::new(Cell::new(false));
1731
1732 let reason_1 = Rc::new(Heap::default());
1734
1735 let reason_2 = Rc::new(Heap::default());
1737
1738 let cancel_promise = Promise::new_rooted(cx, &self.global());
1740 let reader_version = Rc::new(Cell::new(0));
1741
1742 let byte_tee_source_1 = ByteTeeUnderlyingSource::new(
1743 cx,
1744 reader.clone(),
1745 self,
1746 reading.clone(),
1747 read_again_for_branch_1.clone(),
1748 read_again_for_branch_2.clone(),
1749 canceled_1.clone(),
1750 canceled_2.clone(),
1751 reason_1.clone(),
1752 reason_2.clone(),
1753 &cancel_promise,
1754 reader_version.clone(),
1755 ByteTeeCancelAlgorithm::Cancel1Algorithm,
1756 ByteTeePullAlgorithm::Pull1Algorithm,
1757 );
1758
1759 let byte_tee_source_2 = ByteTeeUnderlyingSource::new(
1760 cx,
1761 reader.clone(),
1762 self,
1763 reading,
1764 read_again_for_branch_1,
1765 read_again_for_branch_2,
1766 canceled_1,
1767 canceled_2,
1768 reason_1,
1769 reason_2,
1770 &cancel_promise,
1771 reader_version,
1772 ByteTeeCancelAlgorithm::Cancel2Algorithm,
1773 ByteTeePullAlgorithm::Pull2Algorithm,
1774 );
1775
1776 let branch_1 = readable_byte_stream_tee(
1778 cx,
1779 &self.global(),
1780 UnderlyingSourceType::TeeByte(&byte_tee_source_1),
1781 );
1782 byte_tee_source_1.set_branch_1(&branch_1);
1783 byte_tee_source_2.set_branch_1(&branch_1);
1784
1785 let branch_2 = readable_byte_stream_tee(
1787 cx,
1788 &self.global(),
1789 UnderlyingSourceType::TeeByte(&byte_tee_source_2),
1790 );
1791 byte_tee_source_1.set_branch_2(&branch_2);
1792 byte_tee_source_2.set_branch_2(&branch_2);
1793
1794 byte_tee_source_1.forward_reader_error(cx, reader.clone());
1796 byte_tee_source_2.forward_reader_error(cx, reader);
1797
1798 Ok(vec![branch_1, branch_2])
1800 }
1801
1802 #[cfg_attr(crown, expect(crown::unrooted_must_root))]
1804 fn default_tee(
1805 &self,
1806 cx: &mut JSContext,
1807 clone_for_branch_2: bool,
1808 ) -> Fallible<Vec<DomRoot<ReadableStream>>> {
1809 let clone_for_branch_2 = Rc::new(Cell::new(clone_for_branch_2));
1813
1814 let reader = self.acquire_default_reader(cx)?;
1816
1817 let reading = Rc::new(Cell::new(false));
1819 let read_again = Rc::new(Cell::new(false));
1821 let canceled_1 = Rc::new(Cell::new(false));
1823 let canceled_2 = Rc::new(Cell::new(false));
1825
1826 let reason_1 = Rc::new(Heap::default());
1828 let reason_2 = Rc::new(Heap::default());
1830 let cancel_promise = Promise::new_rooted(cx, &self.global());
1832
1833 let tee_source_1 = DefaultTeeUnderlyingSource::new(
1834 cx,
1835 &reader,
1836 self,
1837 reading.clone(),
1838 read_again.clone(),
1839 canceled_1.clone(),
1840 canceled_2.clone(),
1841 clone_for_branch_2.clone(),
1842 reason_1.clone(),
1843 reason_2.clone(),
1844 &cancel_promise,
1845 DefaultTeeCancelAlgorithm::Cancel1Algorithm,
1846 );
1847
1848 let underlying_source_type_branch_1 = UnderlyingSourceType::Tee(&tee_source_1);
1849
1850 let tee_source_2 = DefaultTeeUnderlyingSource::new(
1851 cx,
1852 &reader,
1853 self,
1854 reading,
1855 read_again,
1856 canceled_1.clone(),
1857 canceled_2.clone(),
1858 clone_for_branch_2,
1859 reason_1,
1860 reason_2,
1861 &cancel_promise,
1862 DefaultTeeCancelAlgorithm::Cancel2Algorithm,
1863 );
1864
1865 let underlying_source_type_branch_2 = UnderlyingSourceType::Tee(&tee_source_2);
1866
1867 let branch_1 = create_readable_stream(
1869 cx,
1870 &self.global(),
1871 underlying_source_type_branch_1,
1872 None,
1873 None,
1874 );
1875 tee_source_1.set_branch_1(&branch_1);
1876 tee_source_2.set_branch_1(&branch_1);
1877
1878 let branch_2 = create_readable_stream(
1880 cx,
1881 &self.global(),
1882 underlying_source_type_branch_2,
1883 None,
1884 None,
1885 );
1886 tee_source_1.set_branch_2(&branch_2);
1887 tee_source_2.set_branch_2(&branch_2);
1888
1889 reader.default_tee_append_native_handler_to_closed_promise(
1891 cx,
1892 &branch_1,
1893 &branch_2,
1894 canceled_1,
1895 canceled_2,
1896 &cancel_promise,
1897 );
1898
1899 Ok(vec![branch_1, branch_2])
1901 }
1902
1903 #[allow(clippy::too_many_arguments)]
1905 pub(crate) fn pipe_to(
1906 &self,
1907 cx: &mut CurrentRealm,
1908 global: &GlobalScope,
1909 dest: &WritableStream,
1910 prevent_close: bool,
1911 prevent_abort: bool,
1912 prevent_cancel: bool,
1913 signal: Option<&AbortSignal>,
1914 ) -> RootedPromise {
1915 assert!(!self.is_locked());
1926
1927 assert!(!dest.is_locked());
1929
1930 let reader = self
1938 .acquire_default_reader(cx)
1939 .expect("Acquiring a default reader for pipe_to cannot fail");
1940
1941 let writer = dest
1943 .aquire_default_writer(cx, global)
1944 .expect("Acquiring a default writer for pipe_to cannot fail");
1945
1946 self.disturbed.set(true);
1948
1949 let promise = Promise::new_rooted(cx, global);
1954
1955 rooted!(&in(cx) let pipe_to = PipeTo {
1957 reader: Dom::from_ref(&reader),
1958 writer: Dom::from_ref(&writer),
1959 pending_writes: Default::default(),
1960 state: Default::default(),
1961 prevent_abort,
1962 prevent_cancel,
1963 prevent_close,
1964 shutting_down: Default::default(),
1965 abort_reason: Default::default(),
1966 shutdown_error: Default::default(),
1967 shutdown_action_promise: Default::default(),
1968 result_promise: promise.to_traced(),
1969 });
1970
1971 if let Some(signal) = signal {
1974 rooted!(&in(cx) let abort_algorithm = AbortAlgorithm::StreamPiping(pipe_to.clone()));
1977
1978 if signal.aborted() {
1980 signal.run_abort_algorithm(cx, global, &abort_algorithm);
1981 return promise;
1982 }
1983
1984 signal.add(&abort_algorithm);
1986 }
1987
1988 pipe_to.check_and_propagate_errors_forward(cx, global);
1990 pipe_to.check_and_propagate_errors_backward(cx, global);
1991 pipe_to.check_and_propagate_closing_forward(cx, global);
1992 pipe_to.check_and_propagate_closing_backward(cx, global);
1993
1994 if *pipe_to.state.borrow() == PipeToState::Starting {
1996 pipe_to.wait_for_writer_ready(cx, global);
1998 }
1999
2000 promise
2002 }
2003
2004 pub(crate) fn tee(
2006 &self,
2007 cx: &mut JSContext,
2008 clone_for_branch_2: bool,
2009 ) -> Fallible<Vec<DomRoot<ReadableStream>>> {
2010 match self.controller.borrow().as_ref() {
2014 Some(ControllerType::Default(_)) => {
2015 self.default_tee(cx, clone_for_branch_2)
2017 },
2018 Some(ControllerType::Byte(_)) => {
2019 self.byte_tee(cx)
2022 },
2023 None => {
2024 unreachable!("Stream should have a controller.");
2025 },
2026 }
2027 }
2028
2029 fn set_up_byte_controller(
2031 &self,
2032 cx: &mut JSContext,
2033 global: &GlobalScope,
2034 underlying_source_dict: JsUnderlyingSource,
2035 underlying_source_handle: SafeHandleObject,
2036 stream: &ReadableStream,
2037 strategy_hwm: f64,
2038 ) -> Fallible<()> {
2039 if let Some(0) = underlying_source_dict.autoAllocateChunkSize {
2055 return Err(Error::Type(c"autoAllocateChunkSize cannot be 0".to_owned()));
2056 }
2057
2058 let controller = ReadableByteStreamController::new(
2059 cx,
2060 UnderlyingSourceType::Js(underlying_source_dict),
2061 strategy_hwm,
2062 global,
2063 );
2064
2065 controller.set_underlying_source_this_object(underlying_source_handle);
2068
2069 controller.setup(cx, global, stream)
2072 }
2073
2074 pub(crate) fn setup_cross_realm_transform_readable(
2076 &self,
2077 cx: &mut JSContext,
2078 port: &MessagePort,
2079 ) {
2080 let port_id = port.message_port_id();
2081 let global = self.global();
2082
2083 let size_algorithm = extract_size_algorithm(cx, &QueuingStrategy::default());
2088
2089 let controller = ReadableStreamDefaultController::new(
2093 cx,
2094 &self.global(),
2095 UnderlyingSourceType::Transfer(port),
2096 0.,
2097 size_algorithm,
2098 );
2099
2100 rooted!(&in(cx) let cross_realm_transform_readable = CrossRealmTransformReadable {
2103 controller: Dom::from_ref(&controller),
2104 });
2105 global.note_cross_realm_transform_readable(&cross_realm_transform_readable, port_id);
2106
2107 port.Start(cx);
2109
2110 controller
2112 .setup(cx, self)
2113 .expect("Setting up controller for transfer cannot fail.");
2114 }
2115}
2116
2117impl ReadableStreamMethods<crate::DomTypeHolder> for ReadableStream {
2118 fn Constructor(
2120 cx: &mut JSContext,
2121 global: &GlobalScope,
2122 proto: Option<SafeHandleObject>,
2123 underlying_source: Option<*mut JSObject>,
2124 strategy: &QueuingStrategy,
2125 ) -> Fallible<DomRoot<Self>> {
2126 rooted!(&in(cx) let underlying_source_obj = underlying_source.unwrap_or(ptr::null_mut()));
2128 let underlying_source_dict = if !underlying_source_obj.is_null() {
2131 rooted!(&in(cx) let obj_val = ObjectValue(underlying_source_obj.get()));
2132 match JsUnderlyingSource::new(cx, obj_val.handle()) {
2133 Ok(ConversionResult::Success(val)) => val,
2134 Ok(ConversionResult::Failure(error)) => {
2135 return Err(Error::Type(error.into_owned()));
2136 },
2137 _ => {
2138 return Err(Error::JSFailed);
2139 },
2140 }
2141 } else {
2142 JsUnderlyingSource::empty()
2143 };
2144
2145 let stream = ReadableStream::new_with_proto(cx, global, proto);
2147
2148 if underlying_source_dict.type_.is_some() {
2149 if strategy.size.is_some() {
2151 return Err(Error::Range(
2152 c"size is not supported for byte streams".to_owned(),
2153 ));
2154 }
2155
2156 let strategy_hwm = extract_high_water_mark(strategy, 0.0)?;
2158
2159 stream.set_up_byte_controller(
2162 cx,
2163 global,
2164 underlying_source_dict,
2165 underlying_source_obj.handle(),
2166 &stream,
2167 strategy_hwm,
2168 )?;
2169 } else {
2170 let high_water_mark = extract_high_water_mark(strategy, 1.0)?;
2172
2173 let size_algorithm = extract_size_algorithm(cx, strategy);
2175
2176 let controller = ReadableStreamDefaultController::new(
2177 cx,
2178 global,
2179 UnderlyingSourceType::Js(underlying_source_dict),
2180 high_water_mark,
2181 size_algorithm,
2182 );
2183
2184 controller.set_underlying_source_this_object(underlying_source_obj.handle());
2187
2188 controller.setup(cx, &stream)?;
2190 };
2191
2192 Ok(stream)
2193 }
2194
2195 fn Locked(&self) -> bool {
2197 self.is_locked()
2198 }
2199
2200 fn Cancel(&self, cx: &mut JSContext, reason: SafeHandleValue) -> RootedPromise {
2202 let global = self.global();
2203 if self.is_locked() {
2204 let promise = Promise::new_rooted(cx, &global);
2207 promise.reject_error(cx, Error::Type(c"stream is locked".to_owned()));
2208 promise
2209 } else {
2210 self.cancel(cx, &global, reason)
2212 }
2213 }
2214
2215 fn GetReader(
2217 &self,
2218 cx: &mut JSContext,
2219 options: &ReadableStreamGetReaderOptions,
2220 ) -> Fallible<ReadableStreamReader> {
2221 if options.mode.is_none() {
2223 return Ok(ReadableStreamReader::ReadableStreamDefaultReader(
2224 self.acquire_default_reader(cx)?,
2225 ));
2226 }
2227 assert!(options.mode.unwrap() == ReadableStreamReaderMode::Byob);
2229
2230 Ok(ReadableStreamReader::ReadableStreamBYOBReader(
2232 self.acquire_byob_reader(cx)?,
2233 ))
2234 }
2235
2236 fn Tee(&self, cx: &mut JSContext) -> Fallible<Vec<DomRoot<ReadableStream>>> {
2238 self.tee(cx, false)
2240 }
2241
2242 fn PipeTo(
2244 &self,
2245 cx: &mut CurrentRealm,
2246 destination: &WritableStream,
2247 options: &StreamPipeOptions,
2248 ) -> RootedPromise {
2249 let global = self.global();
2250
2251 if self.is_locked() {
2253 let promise = Promise::new_rooted(cx, &global);
2255 promise.reject_error(cx, Error::Type(c"Source stream is locked".to_owned()));
2256 return promise;
2257 }
2258
2259 if destination.is_locked() {
2261 let promise = Promise::new_rooted(cx, &global);
2263 promise.reject_error(cx, Error::Type(c"Destination stream is locked".to_owned()));
2264 return promise;
2265 }
2266
2267 let signal = options.signal.as_deref();
2269
2270 self.pipe_to(
2272 cx,
2273 &global,
2274 destination,
2275 options.preventClose,
2276 options.preventAbort,
2277 options.preventCancel,
2278 signal,
2279 )
2280 }
2281
2282 fn PipeThrough(
2284 &self,
2285 cx: &mut CurrentRealm,
2286 transform: &ReadableWritablePair,
2287 options: &StreamPipeOptions,
2288 ) -> Fallible<DomRoot<ReadableStream>> {
2289 let global = self.global();
2290
2291 if self.is_locked() {
2293 return Err(Error::Type(c"Source stream is locked".to_owned()));
2294 }
2295
2296 if transform.writable.is_locked() {
2298 return Err(Error::Type(c"Destination stream is locked".to_owned()));
2299 }
2300
2301 let signal = options.signal.as_deref();
2303
2304 let promise = self.pipe_to(
2307 cx,
2308 &global,
2309 &transform.writable,
2310 options.preventClose,
2311 options.preventAbort,
2312 options.preventCancel,
2313 signal,
2314 );
2315
2316 promise.set_promise_is_handled(cx);
2318
2319 Ok(transform.readable.clone())
2321 }
2322}
2323
2324pub(crate) fn get_type_and_value_from_message(
2328 cx: &mut JSContext,
2329 data: SafeHandleValue,
2330 value: SafeMutableHandleValue,
2331) -> DOMString {
2332 assert!(data.is_object());
2338 rooted!(&in(cx) let data_object = data.to_object());
2339
2340 let type_ = get_property::<DOMString>(
2342 cx,
2343 data_object.handle(),
2344 c"type",
2345 StringificationBehavior::Empty,
2346 );
2347
2348 get_property_jsval(cx, data_object.handle(), c"value", value)
2350 .expect("Getting the value should not fail.");
2351
2352 type_
2354 .expect("The type of the message should be a string")
2355 .expect("Property should be present")
2356}
2357
2358impl js::gc::Rootable for CrossRealmTransformReadable {}
2359
2360#[derive(Clone, JSTraceable, MallocSizeOf)]
2364#[cfg_attr(crown, crown::unrooted_must_root_lint::must_root)]
2365pub(crate) struct CrossRealmTransformReadable {
2366 controller: Dom<ReadableStreamDefaultController>,
2368}
2369
2370impl CrossRealmTransformReadable {
2371 pub(crate) fn handle_message(
2374 &self,
2375 cx: &mut CurrentRealm,
2376 global: &GlobalScope,
2377 port: &MessagePort,
2378 message: SafeHandleValue,
2379 ) {
2380 rooted!(&in(cx) let mut value = UndefinedValue());
2381 let type_string = get_type_and_value_from_message(cx, message, value.handle_mut());
2382
2383 if type_string == "chunk" {
2385 self.controller
2387 .enqueue(cx, value.handle())
2388 .expect("Enqueing a chunk should not fail.");
2389 }
2390
2391 if type_string == "close" {
2393 self.controller.close(cx);
2395
2396 global.disentangle_port(cx, port);
2398 }
2399
2400 if type_string == "error" {
2402 self.controller.error(cx, value.handle());
2404
2405 global.disentangle_port(cx, port);
2407 }
2408 }
2409
2410 pub(crate) fn handle_error(
2413 &self,
2414 cx: &mut CurrentRealm,
2415 global: &GlobalScope,
2416 port: &MessagePort,
2417 ) {
2418 let error = DOMException::new(cx, global, DOMErrorName::DataCloneError);
2420 rooted!(&in(cx) let mut rooted_error = UndefinedValue());
2421 error.to_jsval(cx, rooted_error.handle_mut());
2422
2423 port.cross_realm_transform_send_error(cx, rooted_error.handle());
2425
2426 self.controller.error(cx, rooted_error.handle());
2428
2429 global.disentangle_port(cx, port);
2431 }
2432}
2433
2434pub(crate) fn get_read_promise_done(
2436 cx: &mut JSContext,
2437 v: &SafeHandleValue,
2438) -> Result<bool, Error> {
2439 if !v.is_object() {
2440 return Err(Error::Type(c"Unknown format for done property.".to_owned()));
2441 }
2442
2443 rooted!(&in(cx) let object = v.to_object());
2444 get_property::<bool>(cx, object.handle(), c"done", ())?
2445 .ok_or(Error::Type(c"Promise has no done property.".to_owned()))
2446}
2447
2448pub(crate) fn get_read_promise_bytes(
2450 cx: &mut JSContext,
2451 v: &SafeHandleValue,
2452) -> Result<Vec<u8>, Error> {
2453 if !v.is_object() {
2454 return Err(Error::Type(
2455 c"Unknown format for for bytes read.".to_owned(),
2456 ));
2457 }
2458
2459 rooted!(&in(cx) let object = v.to_object());
2460 get_property::<Vec<u8>>(
2461 cx,
2462 object.handle(),
2463 c"value",
2464 ConversionBehavior::EnforceRange,
2465 )?
2466 .ok_or(Error::Type(c"Promise has no value property.".to_owned()))
2467}
2468
2469pub(crate) fn bytes_from_chunk_jsval(
2473 cx: &mut JSContext,
2474 chunk: &RootedTraceableBox<Heap<JSVal>>,
2475) -> Result<Vec<u8>, Error> {
2476 match Vec::<u8>::from_jsval(cx, chunk.handle(), ConversionBehavior::EnforceRange) {
2477 Ok(ConversionResult::Success(vec)) => Ok(vec),
2478 Ok(ConversionResult::Failure(error)) => Err(Error::Type(error.into_owned())),
2479 _ => Err(Error::Type(c"Unknown format for bytes read.".to_owned())),
2480 }
2481}
2482
2483impl Transferable for ReadableStream {
2485 type Index = MessagePortIndex;
2486 type Data = MessagePortImpl;
2487
2488 fn transfer(&self, cx: &mut JSContext) -> Fallible<(MessagePortId, MessagePortImpl)> {
2490 if self.is_locked() {
2493 return Err(Error::DataClone(None));
2494 }
2495
2496 let global = self.global();
2497 let mut realm = enter_auto_realm(cx, &*global);
2498 let mut realm = realm.current_realm();
2499 let cx = &mut realm;
2500
2501 let port_1 = MessagePort::new(cx, &global);
2503 global.track_message_port(&port_1, None);
2504
2505 let port_2 = MessagePort::new(cx, &global);
2507 global.track_message_port(&port_2, None);
2508
2509 global.entangle_ports(*port_1.message_port_id(), *port_2.message_port_id());
2511
2512 let writable = WritableStream::new_with_proto(cx, &global, None);
2514
2515 writable.setup_cross_realm_transform_writable(cx, &port_1);
2517
2518 let promise = self.pipe_to(cx, &global, &writable, false, false, false, None);
2520
2521 promise.set_promise_is_handled(cx);
2523
2524 port_2.transfer(cx)
2526 }
2527
2528 fn transfer_receive(
2530 cx: &mut JSContext,
2531 owner: &GlobalScope,
2532 id: MessagePortId,
2533 port_impl: MessagePortImpl,
2534 ) -> Result<DomRoot<Self>, ()> {
2535 let value = ReadableStream::new_with_proto(cx, owner, None);
2538
2539 let transferred_port = MessagePort::transfer_receive(cx, owner, id, port_impl)?;
2546
2547 value.setup_cross_realm_transform_readable(cx, &transferred_port);
2549 Ok(value)
2550 }
2551
2552 fn serialized_storage<'a>(
2554 data: StructuredData<'a, '_>,
2555 ) -> &'a mut Option<FxHashMap<MessagePortId, Self::Data>> {
2556 match data {
2557 StructuredData::Reader(r) => &mut r.port_impls,
2558 StructuredData::Writer(w) => &mut w.ports,
2559 }
2560 }
2561}
2562
2563pub(crate) fn pipe_through(
2570 source: &ReadableStream,
2571 cx: &mut JSContext,
2572 global: &GlobalScope,
2573 transform: &TextDecoderStream,
2574) -> DomRoot<ReadableStream> {
2575 let mut realm = CurrentRealm::assert(cx);
2581 let promise = source.pipe_to(
2584 &mut realm,
2585 global,
2586 &transform.Writable(),
2587 false, false, false, None, );
2592
2593 promise.set_promise_is_handled(cx);
2595 transform.Readable()
2597}