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;
32
33use crate::dom::domexception::{DOMErrorName, DOMException};
34use crate::dom::encoding::textdecoderstream::TextDecoderStream;
35use script_bindings::codegen::GenericBindings::TextDecoderStreamBinding::TextDecoderStreamMethods;
36use script_bindings::conversions::{is_array_like, StringificationBehavior};
37use crate::dom::bindings::codegen::Bindings::QueuingStrategyBinding::QueuingStrategySize;
38use crate::dom::abortsignal::{AbortAlgorithm, AbortSignal};
39use crate::dom::bindings::codegen::Bindings::ReadableStreamDefaultReaderBinding::ReadableStreamDefaultReaderMethods;
40use crate::dom::bindings::codegen::Bindings::ReadableStreamDefaultControllerBinding::ReadableStreamDefaultController_Binding::ReadableStreamDefaultControllerMethods;
41use crate::dom::bindings::codegen::Bindings::UnderlyingSourceBinding::UnderlyingSource as JsUnderlyingSource;
42use crate::dom::bindings::conversions::{ConversionBehavior, ConversionResult, get_property, get_property_jsval};
43use crate::dom::bindings::error::{Error, ErrorToJsval, Fallible};
44use crate::dom::bindings::codegen::GenericBindings::WritableStreamDefaultWriterBinding::WritableStreamDefaultWriter_Binding::WritableStreamDefaultWriterMethods;
45use crate::dom::stream::writablestream::WritableStream;
46use crate::dom::bindings::codegen::UnionTypes::ReadableStreamDefaultReaderOrReadableStreamBYOBReader as ReadableStreamReader;
47use crate::dom::bindings::reflector::DomGlobal;
48use script_bindings::reflector::{Reflector, reflect_dom_object_with_proto};
49use crate::dom::bindings::root::{DomRoot, MutNullableDom, Dom};
50use crate::dom::bindings::trace::RootedTraceableBox;
51use crate::dom::stream::byteteeunderlyingsource::{ByteTeeCancelAlgorithm, ByteTeePullAlgorithm, ByteTeeUnderlyingSource};
52use crate::dom::stream::countqueuingstrategy::{extract_high_water_mark, extract_size_algorithm};
53use crate::dom::stream::readablestreamgenericreader::ReadableStreamGenericReader;
54use crate::dom::globalscope::GlobalScope;
55use crate::dom::promise::{wait_for_all_promise, Promise};
56use crate::dom::stream::readablebytestreamcontroller::ReadableByteStreamController;
57use crate::dom::stream::readablestreambyobreader::ReadableStreamBYOBReader;
58use crate::dom::stream::readablestreamdefaultcontroller::ReadableStreamDefaultController;
59use crate::dom::stream::readablestreamdefaultreader::{ReadRequest, ReadableStreamDefaultReader};
60use crate::dom::stream::defaultteeunderlyingsource::DefaultTeeCancelAlgorithm;
61use crate::dom::types::DefaultTeeUnderlyingSource;
62use crate::dom::stream::underlyingsourcecontainer::UnderlyingSourceType;
63use crate::dom::stream::writablestreamdefaultwriter::WritableStreamDefaultWriter;
64use script_bindings::codegen::GenericBindings::MessagePortBinding::MessagePortMethods;
65use crate::dom::messageport::MessagePort;
66use crate::realms::{enter_auto_realm};
67use crate::dom::promisenativehandler::{Callback, PromiseNativeHandler};
68use crate::dom::bindings::transferable::Transferable;
69use crate::dom::bindings::structuredclone::StructuredData;
70
71use super::readablestreambyobreader::ReadIntoRequest;
72use crate::dom::bindings::buffer_source::{HeapBufferSource, create_buffer_source};
73
74#[derive(Clone, Debug, Default, MallocSizeOf, PartialEq)]
76enum PipeToState {
77 #[default]
79 Starting,
80 PendingReady,
82 PendingRead,
84 ShuttingDownWithPendingWrites(Option<ShutdownAction>),
87 ShuttingDownPendingAction,
91 Finalized,
94}
95
96#[derive(Clone, Debug, MallocSizeOf, PartialEq)]
98enum ShutdownAction {
99 WritableStreamAbort,
101 ReadableStreamCancel,
103 WritableStreamDefaultWriterCloseWithErrorPropagation,
105 Abort,
107}
108
109impl js::gc::Rootable for PipeTo {}
110
111#[derive(Clone, JSTraceable, MallocSizeOf)]
120#[cfg_attr(crown, crown::unrooted_must_root_lint::must_root)]
121pub(crate) struct PipeTo {
122 reader: Dom<ReadableStreamDefaultReader>,
124
125 writer: Dom<WritableStreamDefaultWriter>,
127
128 #[ignore_malloc_size_of = "nested Rc"]
131 pending_writes: Rc<RefCell<VecDeque<Rc<Promise>>>>,
132
133 #[conditional_malloc_size_of]
135 #[no_trace]
136 state: Rc<RefCell<PipeToState>>,
137
138 prevent_abort: bool,
140
141 prevent_cancel: bool,
143
144 prevent_close: bool,
146
147 #[conditional_malloc_size_of]
150 shutting_down: Rc<Cell<bool>>,
151
152 #[ignore_malloc_size_of = "mozjs"]
155 abort_reason: Rc<Heap<JSVal>>,
156
157 #[ignore_malloc_size_of = "mozjs"]
160 shutdown_error: Rc<RefCell<Option<Heap<JSVal>>>>,
161
162 #[ignore_malloc_size_of = "nested Rc"]
165 shutdown_action_promise: Rc<RefCell<Option<Rc<Promise>>>>,
166
167 #[conditional_malloc_size_of]
170 result_promise: Rc<Promise>,
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_mut().front().cloned() {
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();
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();
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();
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.borrow_mut().push_back(write_promise);
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: Rc<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_mut().front() {
609 *self.state.borrow_mut() = PipeToState::ShuttingDownWithPendingWrites(action);
610 self.wait_on_pending_write(cx, global, write.clone());
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(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(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);
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)]
751struct SourceCancelPromiseFulfillmentHandler {
752 #[conditional_malloc_size_of]
753 result: Rc<Promise>,
754}
755
756impl Callback for SourceCancelPromiseFulfillmentHandler {
757 fn callback(&self, cx: &mut CurrentRealm, _v: SafeHandleValue) {
761 self.result.resolve_native(cx, &());
762 }
763}
764
765#[derive(Clone, JSTraceable, MallocSizeOf)]
768struct SourceCancelPromiseRejectionHandler {
769 #[conditional_malloc_size_of]
770 result: Rc<Promise>,
771}
772
773impl Callback for SourceCancelPromiseRejectionHandler {
774 fn callback(&self, cx: &mut CurrentRealm, v: SafeHandleValue) {
778 self.result.reject_native(cx, &v);
779 }
780}
781
782#[derive(Clone, Copy, Debug, Default, JSTraceable, MallocSizeOf, PartialEq)]
784pub(crate) enum ReadableStreamState {
785 #[default]
786 Readable,
787 Closed,
788 Errored,
789}
790
791#[derive(JSTraceable, MallocSizeOf)]
793#[cfg_attr(crown, crown::unrooted_must_root_lint::must_root)]
794pub(crate) enum ControllerType {
795 Byte(MutNullableDom<ReadableByteStreamController>),
797 Default(MutNullableDom<ReadableStreamDefaultController>),
799}
800
801#[derive(JSTraceable, MallocSizeOf)]
803#[cfg_attr(crown, crown::unrooted_must_root_lint::must_root)]
804pub(crate) enum ReaderType {
805 #[allow(clippy::upper_case_acronyms)]
807 BYOB(MutNullableDom<ReadableStreamBYOBReader>),
808 Default(MutNullableDom<ReadableStreamDefaultReader>),
810}
811
812impl js::gc::Rootable for ReaderType {}
813
814impl Eq for ReaderType {}
815impl PartialEq for ReaderType {
816 fn eq(&self, other: &Self) -> bool {
817 matches!(
818 (self, other),
819 (ReaderType::BYOB(_), ReaderType::BYOB(_)) |
820 (ReaderType::Default(_), ReaderType::Default(_))
821 )
822 }
823}
824
825pub(crate) fn create_readable_stream(
827 cx: &mut JSContext,
828 global: &GlobalScope,
829 underlying_source_type: UnderlyingSourceType,
830 queuing_strategy: Option<Rc<QueuingStrategySize>>,
831 high_water_mark: Option<f64>,
832) -> DomRoot<ReadableStream> {
833 let high_water_mark = high_water_mark.unwrap_or(1.0);
835
836 let size_algorithm =
838 queuing_strategy.unwrap_or(extract_size_algorithm(cx, &QueuingStrategy::empty()));
839
840 assert!(high_water_mark >= 0.0);
842
843 let stream = ReadableStream::new_with_proto(cx, global, None);
846
847 let controller = ReadableStreamDefaultController::new(
849 cx,
850 global,
851 underlying_source_type,
852 high_water_mark,
853 size_algorithm,
854 );
855
856 controller
859 .setup(cx, &stream)
860 .expect("Setup of default controller cannot fail");
861
862 stream
864}
865
866fn readable_byte_stream_tee(
868 cx: &mut JSContext,
869 global: &GlobalScope,
870 underlying_source_type: UnderlyingSourceType,
871) -> DomRoot<ReadableStream> {
872 let tee_stream = ReadableStream::new_with_proto(cx, global, None);
875
876 let controller = ReadableByteStreamController::new(cx, underlying_source_type, 0.0, global);
878
879 controller
881 .setup(cx, global, &tee_stream)
882 .expect("Setup of byte stream controller cannot fail");
883
884 tee_stream
886}
887
888#[dom_struct]
890pub(crate) struct ReadableStream {
891 reflector_: Reflector,
892
893 controller: RefCell<Option<ControllerType>>,
897
898 #[ignore_malloc_size_of = "mozjs"]
900 stored_error: Heap<JSVal>,
901
902 disturbed: Cell<bool>,
904
905 reader: RefCell<Option<ReaderType>>,
907
908 state: Cell<ReadableStreamState>,
910}
911
912impl ReadableStream {
913 fn new_inherited() -> ReadableStream {
915 ReadableStream {
916 reflector_: Reflector::new(),
917 controller: RefCell::new(None),
918 stored_error: Heap::default(),
919 disturbed: Default::default(),
920 reader: RefCell::new(None),
921 state: Cell::new(Default::default()),
922 }
923 }
924
925 pub(crate) fn new_with_proto(
926 cx: &mut JSContext,
927 global: &GlobalScope,
928 proto: Option<SafeHandleObject>,
929 ) -> DomRoot<ReadableStream> {
930 reflect_dom_object_with_proto(cx, Box::new(ReadableStream::new_inherited()), global, proto)
931 }
932
933 pub(crate) fn set_default_controller(&self, controller: &ReadableStreamDefaultController) {
936 *self.controller.borrow_mut() = Some(ControllerType::Default(MutNullableDom::new(Some(
937 controller,
938 ))));
939 }
940
941 pub(crate) fn set_byte_controller(&self, controller: &ReadableByteStreamController) {
944 *self.controller.borrow_mut() =
945 Some(ControllerType::Byte(MutNullableDom::new(Some(controller))));
946 }
947
948 pub(crate) fn assert_no_controller(&self) {
951 let has_no_controller = self.controller.borrow().is_none();
952 assert!(has_no_controller);
953 }
954
955 pub(crate) fn new_from_bytes(
957 cx: &mut JSContext,
958 global: &GlobalScope,
959 bytes: Vec<u8>,
960 ) -> Fallible<DomRoot<ReadableStream>> {
961 let stream = ReadableStream::new_with_external_underlying_source(
962 cx,
963 global,
964 UnderlyingSourceType::Memory(bytes.len()),
965 )?;
966 stream.enqueue_native(cx, bytes);
967 stream.controller_close_native(cx);
968 Ok(stream)
969 }
970
971 pub(crate) fn new_empty(
974 cx: &mut JSContext,
975 global: &GlobalScope,
976 ) -> Fallible<DomRoot<ReadableStream>> {
977 let empty_stream = ReadableStream::new_with_external_underlying_source(
980 cx,
981 global,
982 UnderlyingSourceType::Memory(0),
983 )?;
984 empty_stream.controller_close_native(cx);
986 Ok(empty_stream)
988 }
989
990 pub(crate) fn new_from_bytes_with_byte_reading_support(
992 cx: &mut JSContext,
993 global: &GlobalScope,
994 bytes: Vec<u8>,
995 ) -> Fallible<DomRoot<ReadableStream>> {
996 let stream = ReadableStream::new_with_external_underlying_byte_source(
997 cx,
998 global,
999 UnderlyingSourceType::Memory(bytes.len()),
1000 )?;
1001 stream.enqueue_native(cx, bytes);
1002 stream.controller_close_native(cx);
1003 Ok(stream)
1004 }
1005
1006 pub(crate) fn new_with_external_underlying_source(
1009 cx: &mut JSContext,
1010 global: &GlobalScope,
1011 source: UnderlyingSourceType,
1012 ) -> Fallible<DomRoot<ReadableStream>> {
1013 assert!(source.is_native());
1014 let stream = ReadableStream::new_with_proto(cx, global, None);
1015 let strategy_size = extract_size_algorithm(cx, &QueuingStrategy::empty());
1016 let controller =
1017 ReadableStreamDefaultController::new(cx, global, source, 1.0, strategy_size);
1018 controller.setup(cx, &stream)?;
1019 Ok(stream)
1020 }
1021
1022 pub(crate) fn new_with_external_underlying_byte_source(
1024 cx: &mut JSContext,
1025 global: &GlobalScope,
1026 source: UnderlyingSourceType,
1027 ) -> Fallible<DomRoot<ReadableStream>> {
1028 assert!(source.is_native());
1029 let stream = ReadableStream::new_with_proto(cx, global, None);
1030 let controller = ReadableByteStreamController::new(cx, source, 0.0, global);
1031 controller.setup(cx, global, &stream)?;
1032 Ok(stream)
1033 }
1034
1035 pub(crate) fn perform_release_steps(&self) -> Fallible<()> {
1037 match self.controller.borrow().as_ref() {
1038 Some(ControllerType::Default(controller)) => {
1039 let controller = controller
1040 .get()
1041 .ok_or_else(|| Error::Type(c"Stream should have controller.".to_owned()))?;
1042 controller.perform_release_steps()
1043 },
1044 Some(ControllerType::Byte(controller)) => {
1045 let controller = controller
1046 .get()
1047 .ok_or_else(|| Error::Type(c"Stream should have controller.".to_owned()))?;
1048 controller.perform_release_steps()
1049 },
1050 None => Err(Error::Type(c"Stream should have controller.".to_owned())),
1051 }
1052 }
1053
1054 pub(crate) fn perform_pull_steps(&self, cx: &mut JSContext, read_request: &ReadRequest) {
1058 match self.controller.borrow().as_ref() {
1059 Some(ControllerType::Default(controller)) => controller
1060 .get()
1061 .expect("Stream should have controller.")
1062 .perform_pull_steps(cx, read_request),
1063 Some(ControllerType::Byte(controller)) => controller
1064 .get()
1065 .expect("Stream should have controller.")
1066 .perform_pull_steps(cx, read_request),
1067 None => {
1068 unreachable!("Stream does not have a controller.");
1069 },
1070 }
1071 }
1072
1073 pub(crate) fn perform_pull_into(
1077 &self,
1078 cx: &mut JSContext,
1079 read_into_request: &ReadIntoRequest,
1080 view: &HeapBufferSource<ArrayBufferViewU8>,
1081 min: u64,
1082 ) {
1083 match self.controller.borrow().as_ref() {
1084 Some(ControllerType::Byte(controller)) => controller
1085 .get()
1086 .expect("Stream should have controller.")
1087 .perform_pull_into(cx, read_into_request, view, min),
1088 _ => {
1089 unreachable!(
1090 "Pulling a chunk from a stream with a default controller using a BYOB reader"
1091 )
1092 },
1093 }
1094 }
1095
1096 pub(crate) fn add_read_request(&self, read_request: &ReadRequest) {
1098 match self.reader.borrow().as_ref() {
1099 Some(ReaderType::Default(reader)) => {
1100 let Some(reader) = reader.get() else {
1101 panic!("Attempt to add a read request without having first acquired a reader.");
1102 };
1103
1104 assert!(self.is_readable());
1106
1107 reader.add_read_request(read_request);
1109 },
1110 _ => {
1111 unreachable!("Adding a read request can only be done on a default reader.")
1112 },
1113 }
1114 }
1115
1116 pub(crate) fn add_read_into_request(&self, read_request: &ReadIntoRequest) {
1118 match self.reader.borrow().as_ref() {
1119 Some(ReaderType::BYOB(reader)) => {
1121 let Some(reader) = reader.get() else {
1122 unreachable!(
1123 "Attempt to add a read into request without having first acquired a reader."
1124 );
1125 };
1126
1127 assert!(self.is_readable() || self.is_closed());
1129
1130 reader.add_read_into_request(read_request);
1132 },
1133 _ => {
1134 unreachable!("Adding a read into request can only be done on a BYOB reader.")
1135 },
1136 }
1137 }
1138
1139 pub(crate) fn enqueue_native(&self, cx: &mut JSContext, bytes: Vec<u8>) {
1141 match self.controller.borrow().as_ref() {
1142 Some(ControllerType::Default(controller)) => controller
1143 .get()
1144 .expect("Stream should have controller.")
1145 .enqueue_native(cx, bytes),
1146 Some(ControllerType::Byte(controller)) => {
1147 if bytes.is_empty() {
1148 return;
1149 }
1150
1151 let controller = controller.get().expect("Stream should have controller.");
1152 rooted!(&in(cx) let mut chunk_object = ptr::null_mut::<JSObject>());
1153 create_buffer_source::<Uint8>(cx, &bytes, chunk_object.handle_mut())
1154 .expect("failed to create buffer source for native byte chunk.");
1155
1156 let chunk = RootedTraceableBox::new(HeapBufferSource::<ArrayBufferViewU8>::new(
1157 chunk_object.handle(),
1158 ));
1159 controller
1160 .enqueue(cx, chunk)
1161 .expect("Enqueuing a native byte chunk should not fail.");
1162 },
1163 _ => {
1164 unreachable!("Enqueueing chunk to a stream from Rust without a controller");
1165 },
1166 }
1167 }
1168
1169 pub(crate) fn error(&self, cx: &mut JSContext, e: SafeHandleValue) {
1171 assert!(self.is_readable());
1173
1174 self.state.set(ReadableStreamState::Errored);
1176
1177 self.stored_error.set(e.get());
1179
1180 let default_reader = {
1183 let reader_ref = self.reader.borrow();
1184 match reader_ref.as_ref() {
1185 Some(ReaderType::Default(reader)) => reader.get(),
1186 _ => None,
1187 }
1188 };
1189
1190 if let Some(reader) = default_reader {
1191 reader.error(cx, e);
1193 return;
1194 }
1195
1196 let byob_reader = {
1197 let reader_ref = self.reader.borrow();
1198 match reader_ref.as_ref() {
1199 Some(ReaderType::BYOB(reader)) => reader.get(),
1200 _ => None,
1201 }
1202 };
1203
1204 if let Some(reader) = byob_reader {
1205 reader.error_read_into_requests(cx, e);
1207 }
1208
1209 }
1211
1212 pub(crate) fn get_stored_error(&self, mut handle_mut: SafeMutableHandleValue) {
1214 handle_mut.set(self.stored_error.get());
1215 }
1216
1217 pub(crate) fn error_native(&self, cx: &mut JSContext, error: Error) {
1220 rooted!(&in(cx) let mut error_val = UndefinedValue());
1221 error.to_jsval(cx, &self.global(), error_val.handle_mut());
1222 self.error(cx, error_val.handle());
1223 }
1224
1225 pub(crate) fn controller_close_native(&self, cx: &mut JSContext) {
1228 match self.controller.borrow().as_ref() {
1229 Some(ControllerType::Default(controller)) => {
1230 let _ = controller
1231 .get()
1232 .expect("Stream should have controller.")
1233 .Close(cx);
1234 },
1235 Some(ControllerType::Byte(controller)) => {
1236 let _ = controller
1237 .get()
1238 .expect("Stream should have controller.")
1239 .close(cx);
1240 },
1241 _ => {
1242 unreachable!("Native closing requires a stream controller.")
1243 },
1244 }
1245 }
1246
1247 pub(crate) fn in_memory(&self) -> bool {
1250 match self.controller.borrow().as_ref() {
1251 Some(ControllerType::Default(controller)) => controller
1252 .get()
1253 .expect("Stream should have controller.")
1254 .in_memory(),
1255 Some(ControllerType::Byte(controller)) => controller
1256 .get()
1257 .expect("Stream should have controller.")
1258 .in_memory(),
1259 _ => unreachable!("Checking if source is in memory for a stream without a controller"),
1260 }
1261 }
1262
1263 pub(crate) fn get_in_memory_bytes(&self, cx: &mut JSContext) -> Option<GenericSharedMemory> {
1266 match self.controller.borrow().as_ref() {
1267 Some(ControllerType::Default(controller)) => controller
1268 .get()
1269 .expect("Stream should have controller.")
1270 .get_in_memory_bytes()
1271 .map(GenericSharedMemory::from_vec),
1272 Some(ControllerType::Byte(controller)) => controller
1273 .get()
1274 .expect("Stream should have controller.")
1275 .get_in_memory_bytes(cx)
1276 .map(GenericSharedMemory::from_vec),
1277 _ => unreachable!("Getting in-memory bytes for a stream without a controller"),
1278 }
1279 }
1280
1281 pub(crate) fn acquire_default_reader(
1286 &self,
1287 cx: &mut JSContext,
1288 ) -> Fallible<DomRoot<ReadableStreamDefaultReader>> {
1289 let reader = ReadableStreamDefaultReader::new(cx, &self.global());
1291
1292 reader.set_up(cx, self, &self.global())?;
1294
1295 Ok(reader)
1297 }
1298
1299 pub(crate) fn acquire_byob_reader(
1301 &self,
1302 cx: &mut JSContext,
1303 ) -> Fallible<DomRoot<ReadableStreamBYOBReader>> {
1304 let reader = ReadableStreamBYOBReader::new(cx, &self.global());
1306 reader.set_up(cx, self, &self.global())?;
1308
1309 Ok(reader)
1311 }
1312
1313 pub(crate) fn get_default_controller(&self) -> DomRoot<ReadableStreamDefaultController> {
1314 match self.controller.borrow().as_ref() {
1315 Some(ControllerType::Default(controller)) => {
1316 controller.get().expect("Stream should have controller.")
1317 },
1318 _ => {
1319 unreachable!(
1320 "Getting default controller for a stream with a non-default controller"
1321 )
1322 },
1323 }
1324 }
1325
1326 pub(crate) fn get_byte_controller(&self) -> DomRoot<ReadableByteStreamController> {
1327 match self.controller.borrow().as_ref() {
1328 Some(ControllerType::Byte(controller)) => {
1329 controller.get().expect("Stream should have controller.")
1330 },
1331 _ => {
1332 unreachable!("Getting byte controller for a stream with a non-byte controller")
1333 },
1334 }
1335 }
1336
1337 pub(crate) fn get_default_reader(&self) -> DomRoot<ReadableStreamDefaultReader> {
1338 match self.reader.borrow().as_ref() {
1339 Some(ReaderType::Default(reader)) => reader.get().expect("Stream should have reader."),
1340 _ => {
1341 unreachable!("Getting default reader for a stream with a non-default reader")
1342 },
1343 }
1344 }
1345
1346 pub(crate) fn read_a_chunk(&self, cx: &mut JSContext) -> Rc<Promise> {
1352 match self.reader.borrow().as_ref() {
1353 Some(ReaderType::Default(reader)) => {
1354 let Some(reader) = reader.get() else {
1355 unreachable!(
1356 "Attempt to read stream chunk without having first acquired a reader."
1357 );
1358 };
1359 reader.Read(cx)
1360 },
1361 _ => {
1362 unreachable!("Native reading of a chunk can only be done with a default reader.")
1363 },
1364 }
1365 }
1366
1367 pub(crate) fn stop_reading(&self, cx: &mut JSContext) {
1372 let reader_ref = self.reader.borrow();
1373
1374 match reader_ref.as_ref() {
1375 Some(ReaderType::Default(reader)) => {
1376 let Some(reader) = reader.get() else {
1377 unreachable!("Attempt to stop reading without having first acquired a reader.");
1378 };
1379
1380 drop(reader_ref);
1381 reader.release(cx).expect("Reader release cannot fail.");
1382 },
1383 _ => {
1384 unreachable!("Native stop reading can only be done with a default reader.")
1385 },
1386 }
1387 }
1388
1389 pub(crate) fn is_locked(&self) -> bool {
1391 match self.reader.borrow().as_ref() {
1392 Some(ReaderType::Default(reader)) => reader.get().is_some(),
1393 Some(ReaderType::BYOB(reader)) => reader.get().is_some(),
1394 None => false,
1395 }
1396 }
1397
1398 pub(crate) fn is_disturbed(&self) -> bool {
1399 self.disturbed.get()
1400 }
1401
1402 pub(crate) fn set_is_disturbed(&self, disturbed: bool) {
1403 self.disturbed.set(disturbed);
1404 }
1405
1406 pub(crate) fn is_closed(&self) -> bool {
1407 self.state.get() == ReadableStreamState::Closed
1408 }
1409
1410 pub(crate) fn is_errored(&self) -> bool {
1411 self.state.get() == ReadableStreamState::Errored
1412 }
1413
1414 pub(crate) fn is_readable(&self) -> bool {
1415 self.state.get() == ReadableStreamState::Readable
1416 }
1417
1418 pub(crate) fn has_default_reader(&self) -> bool {
1419 match self.reader.borrow().as_ref() {
1420 Some(ReaderType::Default(reader)) => reader.get().is_some(),
1421 _ => false,
1422 }
1423 }
1424
1425 pub(crate) fn has_byob_reader(&self) -> bool {
1426 match self.reader.borrow().as_ref() {
1427 Some(ReaderType::BYOB(reader)) => reader.get().is_some(),
1428 _ => false,
1429 }
1430 }
1431
1432 pub(crate) fn has_byte_controller(&self) -> bool {
1433 match self.controller.borrow().as_ref() {
1434 Some(ControllerType::Byte(controller)) => controller.get().is_some(),
1435 _ => false,
1436 }
1437 }
1438
1439 pub(crate) fn get_num_read_requests(&self) -> usize {
1441 match self.reader.borrow().as_ref() {
1442 Some(ReaderType::Default(reader)) => {
1443 let reader = reader
1444 .get()
1445 .expect("Stream must have a reader when getting the number of read requests.");
1446 reader.get_num_read_requests()
1447 },
1448 _ => unreachable!(
1449 "Stream must have a default reader when get num read requests is called into."
1450 ),
1451 }
1452 }
1453
1454 pub(crate) fn get_num_read_into_requests(&self) -> usize {
1456 assert!(self.has_byob_reader());
1457
1458 match self.reader.borrow().as_ref() {
1459 Some(ReaderType::BYOB(reader)) => {
1460 let Some(reader) = reader.get() else {
1461 unreachable!(
1462 "Stream must have a reader when get num read into requests is called into."
1463 );
1464 };
1465 reader.get_num_read_into_requests()
1466 },
1467 _ => {
1468 unreachable!(
1469 "Stream must have a BYOB reader when get num read into requests is called into."
1470 );
1471 },
1472 }
1473 }
1474
1475 pub(crate) fn fulfill_read_request(
1477 &self,
1478 cx: &mut JSContext,
1479 chunk: SafeHandleValue,
1480 done: bool,
1481 ) {
1482 assert!(self.has_default_reader());
1484
1485 match self.reader.borrow().as_ref() {
1486 Some(ReaderType::Default(reader)) => {
1487 let reader = reader
1489 .get()
1490 .expect("Stream must have a reader when a read request is fulfilled.");
1491 assert_ne!(reader.get_num_read_requests(), 0);
1493 let request = reader.remove_read_request();
1496
1497 if done {
1498 request.close_steps(cx);
1500 } else {
1501 let result = RootedTraceableBox::new(Heap::default());
1503 result.set(*chunk);
1504 request.chunk_steps(cx, result, &self.global());
1505 }
1506 },
1507 _ => {
1508 unreachable!(
1509 "Stream must have a default reader when fulfill read requests is called into."
1510 );
1511 },
1512 }
1513 }
1514
1515 pub(crate) fn fulfill_read_into_request(
1517 &self,
1518 cx: &mut JSContext,
1519 chunk: SafeHandleValue,
1520 done: bool,
1521 ) {
1522 assert!(self.has_byob_reader());
1524
1525 match self.reader.borrow().as_ref() {
1527 Some(ReaderType::BYOB(reader)) => {
1528 let Some(reader) = reader.get() else {
1529 unreachable!(
1530 "Stream must have a reader when a read into request is fulfilled."
1531 );
1532 };
1533
1534 assert!(reader.get_num_read_into_requests() > 0);
1536
1537 let read_into_request = reader.remove_read_into_request();
1540
1541 let result = RootedTraceableBox::new(Heap::default());
1543 if done {
1544 result.set(*chunk);
1545 read_into_request.close_steps(cx, Some(result));
1546 } else {
1547 result.set(*chunk);
1549 read_into_request.chunk_steps(cx, result);
1550 }
1551 },
1552 _ => {
1553 unreachable!(
1554 "Stream must have a BYOB reader when fulfill read into requests is called into."
1555 );
1556 },
1557 };
1558 }
1559
1560 pub(crate) fn close(&self, cx: &mut JSContext) {
1562 assert!(self.is_readable());
1564 self.state.set(ReadableStreamState::Closed);
1566 let default_reader = {
1572 let reader_ref = self.reader.borrow();
1573 match reader_ref.as_ref() {
1574 Some(ReaderType::Default(reader)) => reader.get(),
1575 _ => None,
1576 }
1577 };
1578
1579 if let Some(reader) = default_reader {
1580 reader.close(cx);
1582 return;
1583 }
1584
1585 let byob_reader = {
1587 let reader_ref = self.reader.borrow();
1588 match reader_ref.as_ref() {
1589 Some(ReaderType::BYOB(reader)) => reader.get(),
1590 _ => None,
1591 }
1592 };
1593
1594 if let Some(reader) = byob_reader {
1595 reader.close(cx);
1597 }
1598
1599 }
1601
1602 pub(crate) fn cancel(
1604 &self,
1605 cx: &mut JSContext,
1606 global: &GlobalScope,
1607 reason: SafeHandleValue,
1608 ) -> Rc<Promise> {
1609 self.disturbed.set(true);
1611
1612 if self.is_closed() {
1614 return Promise::new_resolved(cx, global, ());
1615 }
1616 if self.is_errored() {
1618 let promise = Promise::new(cx, global);
1619 rooted!(&in(cx) let mut rval = UndefinedValue());
1620 self.stored_error.safe_to_jsval(cx, rval.handle_mut());
1621 promise.reject_native(cx, &rval.handle());
1622 return promise;
1623 }
1624 self.close(cx);
1626
1627 let byob_reader = {
1629 let reader_ref = self.reader.borrow();
1630 match reader_ref.as_ref() {
1631 Some(ReaderType::BYOB(reader)) => reader.get(),
1632 _ => None,
1633 }
1634 };
1635
1636 if let Some(reader) = byob_reader {
1637 reader.cancel(cx);
1639 }
1640
1641 let source_cancel_promise = match self.controller.borrow().as_ref() {
1644 Some(ControllerType::Default(controller)) => controller
1645 .get()
1646 .expect("Stream should have controller.")
1647 .perform_cancel_steps(cx, global, reason),
1648 Some(ControllerType::Byte(controller)) => controller
1649 .get()
1650 .expect("Stream should have controller.")
1651 .perform_cancel_steps(cx, global, reason),
1652 None => {
1653 panic!("Stream does not have a controller.");
1654 },
1655 };
1656
1657 let global = self.global();
1660 let result_promise = Promise::new(cx, &global);
1661 let fulfillment_handler = Box::new(SourceCancelPromiseFulfillmentHandler {
1662 result: result_promise.clone(),
1663 });
1664 let rejection_handler = Box::new(SourceCancelPromiseRejectionHandler {
1665 result: result_promise.clone(),
1666 });
1667 let handler = PromiseNativeHandler::new(
1668 cx,
1669 &global,
1670 Some(fulfillment_handler),
1671 Some(rejection_handler),
1672 );
1673 let mut realm = enter_auto_realm(cx, &*global);
1674 let cx = &mut realm.current_realm();
1675 source_cancel_promise.append_native_handler(cx, &handler);
1676
1677 result_promise
1680 }
1681
1682 #[cfg_attr(crown, expect(crown::unrooted_must_root))]
1683 pub(crate) fn set_reader(&self, new_reader: Option<ReaderType>) {
1684 *self.reader.borrow_mut() = new_reader;
1685 }
1686
1687 #[cfg_attr(crown, expect(crown::unrooted_must_root))]
1688 fn byte_tee(&self, cx: &mut JSContext) -> Fallible<Vec<DomRoot<ReadableStream>>> {
1690 let reader = self.acquire_default_reader(cx)?;
1695 let reader = Rc::new(RefCell::new(ReaderType::Default(MutNullableDom::new(
1696 Some(&reader),
1697 ))));
1698
1699 let reading = Rc::new(Cell::new(false));
1701
1702 let read_again_for_branch_1 = Rc::new(Cell::new(false));
1704
1705 let read_again_for_branch_2 = Rc::new(Cell::new(false));
1707
1708 let canceled_1 = Rc::new(Cell::new(false));
1710
1711 let canceled_2 = Rc::new(Cell::new(false));
1713
1714 let reason_1 = Rc::new(Heap::default());
1716
1717 let reason_2 = Rc::new(Heap::default());
1719
1720 let cancel_promise = Promise::new(cx, &self.global());
1722 let reader_version = Rc::new(Cell::new(0));
1723
1724 let byte_tee_source_1 = ByteTeeUnderlyingSource::new(
1725 cx,
1726 reader.clone(),
1727 self,
1728 reading.clone(),
1729 read_again_for_branch_1.clone(),
1730 read_again_for_branch_2.clone(),
1731 canceled_1.clone(),
1732 canceled_2.clone(),
1733 reason_1.clone(),
1734 reason_2.clone(),
1735 cancel_promise.clone(),
1736 reader_version.clone(),
1737 ByteTeeCancelAlgorithm::Cancel1Algorithm,
1738 ByteTeePullAlgorithm::Pull1Algorithm,
1739 );
1740
1741 let byte_tee_source_2 = ByteTeeUnderlyingSource::new(
1742 cx,
1743 reader.clone(),
1744 self,
1745 reading,
1746 read_again_for_branch_1,
1747 read_again_for_branch_2,
1748 canceled_1,
1749 canceled_2,
1750 reason_1,
1751 reason_2,
1752 cancel_promise,
1753 reader_version,
1754 ByteTeeCancelAlgorithm::Cancel2Algorithm,
1755 ByteTeePullAlgorithm::Pull2Algorithm,
1756 );
1757
1758 let branch_1 = readable_byte_stream_tee(
1760 cx,
1761 &self.global(),
1762 UnderlyingSourceType::TeeByte(&byte_tee_source_1),
1763 );
1764 byte_tee_source_1.set_branch_1(&branch_1);
1765 byte_tee_source_2.set_branch_1(&branch_1);
1766
1767 let branch_2 = readable_byte_stream_tee(
1769 cx,
1770 &self.global(),
1771 UnderlyingSourceType::TeeByte(&byte_tee_source_2),
1772 );
1773 byte_tee_source_1.set_branch_2(&branch_2);
1774 byte_tee_source_2.set_branch_2(&branch_2);
1775
1776 byte_tee_source_1.forward_reader_error(cx, reader.clone());
1778 byte_tee_source_2.forward_reader_error(cx, reader);
1779
1780 Ok(vec![branch_1, branch_2])
1782 }
1783
1784 #[cfg_attr(crown, expect(crown::unrooted_must_root))]
1786 fn default_tee(
1787 &self,
1788 cx: &mut JSContext,
1789 clone_for_branch_2: bool,
1790 ) -> Fallible<Vec<DomRoot<ReadableStream>>> {
1791 let clone_for_branch_2 = Rc::new(Cell::new(clone_for_branch_2));
1795
1796 let reader = self.acquire_default_reader(cx)?;
1798
1799 let reading = Rc::new(Cell::new(false));
1801 let read_again = Rc::new(Cell::new(false));
1803 let canceled_1 = Rc::new(Cell::new(false));
1805 let canceled_2 = Rc::new(Cell::new(false));
1807
1808 let reason_1 = Rc::new(Heap::default());
1810 let reason_2 = Rc::new(Heap::default());
1812 let cancel_promise = Promise::new(cx, &self.global());
1814
1815 let tee_source_1 = DefaultTeeUnderlyingSource::new(
1816 cx,
1817 &reader,
1818 self,
1819 reading.clone(),
1820 read_again.clone(),
1821 canceled_1.clone(),
1822 canceled_2.clone(),
1823 clone_for_branch_2.clone(),
1824 reason_1.clone(),
1825 reason_2.clone(),
1826 cancel_promise.clone(),
1827 DefaultTeeCancelAlgorithm::Cancel1Algorithm,
1828 );
1829
1830 let underlying_source_type_branch_1 = UnderlyingSourceType::Tee(&tee_source_1);
1831
1832 let tee_source_2 = DefaultTeeUnderlyingSource::new(
1833 cx,
1834 &reader,
1835 self,
1836 reading,
1837 read_again,
1838 canceled_1.clone(),
1839 canceled_2.clone(),
1840 clone_for_branch_2,
1841 reason_1,
1842 reason_2,
1843 cancel_promise.clone(),
1844 DefaultTeeCancelAlgorithm::Cancel2Algorithm,
1845 );
1846
1847 let underlying_source_type_branch_2 = UnderlyingSourceType::Tee(&tee_source_2);
1848
1849 let branch_1 = create_readable_stream(
1851 cx,
1852 &self.global(),
1853 underlying_source_type_branch_1,
1854 None,
1855 None,
1856 );
1857 tee_source_1.set_branch_1(&branch_1);
1858 tee_source_2.set_branch_1(&branch_1);
1859
1860 let branch_2 = create_readable_stream(
1862 cx,
1863 &self.global(),
1864 underlying_source_type_branch_2,
1865 None,
1866 None,
1867 );
1868 tee_source_1.set_branch_2(&branch_2);
1869 tee_source_2.set_branch_2(&branch_2);
1870
1871 reader.default_tee_append_native_handler_to_closed_promise(
1873 cx,
1874 &branch_1,
1875 &branch_2,
1876 canceled_1,
1877 canceled_2,
1878 cancel_promise,
1879 );
1880
1881 Ok(vec![branch_1, branch_2])
1883 }
1884
1885 #[allow(clippy::too_many_arguments)]
1887 pub(crate) fn pipe_to(
1888 &self,
1889 cx: &mut CurrentRealm,
1890 global: &GlobalScope,
1891 dest: &WritableStream,
1892 prevent_close: bool,
1893 prevent_abort: bool,
1894 prevent_cancel: bool,
1895 signal: Option<&AbortSignal>,
1896 ) -> Rc<Promise> {
1897 assert!(!self.is_locked());
1908
1909 assert!(!dest.is_locked());
1911
1912 let reader = self
1920 .acquire_default_reader(cx)
1921 .expect("Acquiring a default reader for pipe_to cannot fail");
1922
1923 let writer = dest
1925 .aquire_default_writer(cx, global)
1926 .expect("Acquiring a default writer for pipe_to cannot fail");
1927
1928 self.disturbed.set(true);
1930
1931 let promise = Promise::new(cx, global);
1936
1937 rooted!(&in(cx) let pipe_to = PipeTo {
1939 reader: Dom::from_ref(&reader),
1940 writer: Dom::from_ref(&writer),
1941 pending_writes: Default::default(),
1942 state: Default::default(),
1943 prevent_abort,
1944 prevent_cancel,
1945 prevent_close,
1946 shutting_down: Default::default(),
1947 abort_reason: Default::default(),
1948 shutdown_error: Default::default(),
1949 shutdown_action_promise: Default::default(),
1950 result_promise: promise.clone(),
1951 });
1952
1953 if let Some(signal) = signal {
1956 rooted!(&in(cx) let abort_algorithm = AbortAlgorithm::StreamPiping(pipe_to.clone()));
1959
1960 if signal.aborted() {
1962 signal.run_abort_algorithm(cx, global, &abort_algorithm);
1963 return promise;
1964 }
1965
1966 signal.add(&abort_algorithm);
1968 }
1969
1970 pipe_to.check_and_propagate_errors_forward(cx, global);
1972 pipe_to.check_and_propagate_errors_backward(cx, global);
1973 pipe_to.check_and_propagate_closing_forward(cx, global);
1974 pipe_to.check_and_propagate_closing_backward(cx, global);
1975
1976 if *pipe_to.state.borrow() == PipeToState::Starting {
1978 pipe_to.wait_for_writer_ready(cx, global);
1980 }
1981
1982 promise
1984 }
1985
1986 pub(crate) fn tee(
1988 &self,
1989 cx: &mut JSContext,
1990 clone_for_branch_2: bool,
1991 ) -> Fallible<Vec<DomRoot<ReadableStream>>> {
1992 match self.controller.borrow().as_ref() {
1996 Some(ControllerType::Default(_)) => {
1997 self.default_tee(cx, clone_for_branch_2)
1999 },
2000 Some(ControllerType::Byte(_)) => {
2001 self.byte_tee(cx)
2004 },
2005 None => {
2006 unreachable!("Stream should have a controller.");
2007 },
2008 }
2009 }
2010
2011 fn set_up_byte_controller(
2013 &self,
2014 cx: &mut JSContext,
2015 global: &GlobalScope,
2016 underlying_source_dict: JsUnderlyingSource,
2017 underlying_source_handle: SafeHandleObject,
2018 stream: &ReadableStream,
2019 strategy_hwm: f64,
2020 ) -> Fallible<()> {
2021 if let Some(0) = underlying_source_dict.autoAllocateChunkSize {
2037 return Err(Error::Type(c"autoAllocateChunkSize cannot be 0".to_owned()));
2038 }
2039
2040 let controller = ReadableByteStreamController::new(
2041 cx,
2042 UnderlyingSourceType::Js(underlying_source_dict),
2043 strategy_hwm,
2044 global,
2045 );
2046
2047 controller.set_underlying_source_this_object(underlying_source_handle);
2050
2051 controller.setup(cx, global, stream)
2054 }
2055
2056 pub(crate) fn setup_cross_realm_transform_readable(
2058 &self,
2059 cx: &mut JSContext,
2060 port: &MessagePort,
2061 ) {
2062 let port_id = port.message_port_id();
2063 let global = self.global();
2064
2065 let size_algorithm = extract_size_algorithm(cx, &QueuingStrategy::default());
2070
2071 let controller = ReadableStreamDefaultController::new(
2075 cx,
2076 &self.global(),
2077 UnderlyingSourceType::Transfer(port),
2078 0.,
2079 size_algorithm,
2080 );
2081
2082 rooted!(&in(cx) let cross_realm_transform_readable = CrossRealmTransformReadable {
2085 controller: Dom::from_ref(&controller),
2086 });
2087 global.note_cross_realm_transform_readable(&cross_realm_transform_readable, port_id);
2088
2089 port.Start(cx);
2091
2092 controller
2094 .setup(cx, self)
2095 .expect("Setting up controller for transfer cannot fail.");
2096 }
2097}
2098
2099impl ReadableStreamMethods<crate::DomTypeHolder> for ReadableStream {
2100 fn Constructor(
2102 cx: &mut JSContext,
2103 global: &GlobalScope,
2104 proto: Option<SafeHandleObject>,
2105 underlying_source: Option<*mut JSObject>,
2106 strategy: &QueuingStrategy,
2107 ) -> Fallible<DomRoot<Self>> {
2108 rooted!(&in(cx) let underlying_source_obj = underlying_source.unwrap_or(ptr::null_mut()));
2110 let underlying_source_dict = if !underlying_source_obj.is_null() {
2113 rooted!(&in(cx) let obj_val = ObjectValue(underlying_source_obj.get()));
2114 match JsUnderlyingSource::new(cx, obj_val.handle()) {
2115 Ok(ConversionResult::Success(val)) => val,
2116 Ok(ConversionResult::Failure(error)) => {
2117 return Err(Error::Type(error.into_owned()));
2118 },
2119 _ => {
2120 return Err(Error::JSFailed);
2121 },
2122 }
2123 } else {
2124 JsUnderlyingSource::empty()
2125 };
2126
2127 let stream = ReadableStream::new_with_proto(cx, global, proto);
2129
2130 if underlying_source_dict.type_.is_some() {
2131 if strategy.size.is_some() {
2133 return Err(Error::Range(
2134 c"size is not supported for byte streams".to_owned(),
2135 ));
2136 }
2137
2138 let strategy_hwm = extract_high_water_mark(strategy, 0.0)?;
2140
2141 stream.set_up_byte_controller(
2144 cx,
2145 global,
2146 underlying_source_dict,
2147 underlying_source_obj.handle(),
2148 &stream,
2149 strategy_hwm,
2150 )?;
2151 } else {
2152 let high_water_mark = extract_high_water_mark(strategy, 1.0)?;
2154
2155 let size_algorithm = extract_size_algorithm(cx, strategy);
2157
2158 let controller = ReadableStreamDefaultController::new(
2159 cx,
2160 global,
2161 UnderlyingSourceType::Js(underlying_source_dict),
2162 high_water_mark,
2163 size_algorithm,
2164 );
2165
2166 controller.set_underlying_source_this_object(underlying_source_obj.handle());
2169
2170 controller.setup(cx, &stream)?;
2172 };
2173
2174 Ok(stream)
2175 }
2176
2177 fn Locked(&self) -> bool {
2179 self.is_locked()
2180 }
2181
2182 fn Cancel(&self, cx: &mut JSContext, reason: SafeHandleValue) -> Rc<Promise> {
2184 let global = self.global();
2185 if self.is_locked() {
2186 let promise = Promise::new(cx, &global);
2189 promise.reject_error(cx, Error::Type(c"stream is locked".to_owned()));
2190 promise
2191 } else {
2192 self.cancel(cx, &global, reason)
2194 }
2195 }
2196
2197 fn GetReader(
2199 &self,
2200 cx: &mut JSContext,
2201 options: &ReadableStreamGetReaderOptions,
2202 ) -> Fallible<ReadableStreamReader> {
2203 if options.mode.is_none() {
2205 return Ok(ReadableStreamReader::ReadableStreamDefaultReader(
2206 self.acquire_default_reader(cx)?,
2207 ));
2208 }
2209 assert!(options.mode.unwrap() == ReadableStreamReaderMode::Byob);
2211
2212 Ok(ReadableStreamReader::ReadableStreamBYOBReader(
2214 self.acquire_byob_reader(cx)?,
2215 ))
2216 }
2217
2218 fn Tee(&self, cx: &mut JSContext) -> Fallible<Vec<DomRoot<ReadableStream>>> {
2220 self.tee(cx, false)
2222 }
2223
2224 fn PipeTo(
2226 &self,
2227 cx: &mut CurrentRealm,
2228 destination: &WritableStream,
2229 options: &StreamPipeOptions,
2230 ) -> Rc<Promise> {
2231 let global = self.global();
2232
2233 if self.is_locked() {
2235 let promise = Promise::new(cx, &global);
2237 promise.reject_error(cx, Error::Type(c"Source stream is locked".to_owned()));
2238 return promise;
2239 }
2240
2241 if destination.is_locked() {
2243 let promise = Promise::new(cx, &global);
2245 promise.reject_error(cx, Error::Type(c"Destination stream is locked".to_owned()));
2246 return promise;
2247 }
2248
2249 let signal = options.signal.as_deref();
2251
2252 self.pipe_to(
2254 cx,
2255 &global,
2256 destination,
2257 options.preventClose,
2258 options.preventAbort,
2259 options.preventCancel,
2260 signal,
2261 )
2262 }
2263
2264 fn PipeThrough(
2266 &self,
2267 cx: &mut CurrentRealm,
2268 transform: &ReadableWritablePair,
2269 options: &StreamPipeOptions,
2270 ) -> Fallible<DomRoot<ReadableStream>> {
2271 let global = self.global();
2272
2273 if self.is_locked() {
2275 return Err(Error::Type(c"Source stream is locked".to_owned()));
2276 }
2277
2278 if transform.writable.is_locked() {
2280 return Err(Error::Type(c"Destination stream is locked".to_owned()));
2281 }
2282
2283 let signal = options.signal.as_deref();
2285
2286 let promise = self.pipe_to(
2289 cx,
2290 &global,
2291 &transform.writable,
2292 options.preventClose,
2293 options.preventAbort,
2294 options.preventCancel,
2295 signal,
2296 );
2297
2298 promise.set_promise_is_handled(cx);
2300
2301 Ok(transform.readable.clone())
2303 }
2304}
2305
2306pub(crate) fn get_type_and_value_from_message(
2310 cx: &mut JSContext,
2311 data: SafeHandleValue,
2312 value: SafeMutableHandleValue,
2313) -> DOMString {
2314 assert!(data.is_object());
2320 rooted!(&in(cx) let data_object = data.to_object());
2321
2322 let type_ = get_property::<DOMString>(
2324 cx,
2325 data_object.handle(),
2326 c"type",
2327 StringificationBehavior::Empty,
2328 );
2329
2330 get_property_jsval(cx, data_object.handle(), c"value", value)
2332 .expect("Getting the value should not fail.");
2333
2334 type_
2336 .expect("The type of the message should be a string")
2337 .expect("Property should be present")
2338}
2339
2340impl js::gc::Rootable for CrossRealmTransformReadable {}
2341
2342#[derive(Clone, JSTraceable, MallocSizeOf)]
2346#[cfg_attr(crown, crown::unrooted_must_root_lint::must_root)]
2347pub(crate) struct CrossRealmTransformReadable {
2348 controller: Dom<ReadableStreamDefaultController>,
2350}
2351
2352impl CrossRealmTransformReadable {
2353 pub(crate) fn handle_message(
2356 &self,
2357 cx: &mut CurrentRealm,
2358 global: &GlobalScope,
2359 port: &MessagePort,
2360 message: SafeHandleValue,
2361 ) {
2362 rooted!(&in(cx) let mut value = UndefinedValue());
2363 let type_string = get_type_and_value_from_message(cx, message, value.handle_mut());
2364
2365 if type_string == "chunk" {
2367 self.controller
2369 .enqueue(cx, value.handle())
2370 .expect("Enqueing a chunk should not fail.");
2371 }
2372
2373 if type_string == "close" {
2375 self.controller.close(cx);
2377
2378 global.disentangle_port(cx, port);
2380 }
2381
2382 if type_string == "error" {
2384 self.controller.error(cx, value.handle());
2386
2387 global.disentangle_port(cx, port);
2389 }
2390 }
2391
2392 pub(crate) fn handle_error(
2395 &self,
2396 cx: &mut CurrentRealm,
2397 global: &GlobalScope,
2398 port: &MessagePort,
2399 ) {
2400 let error = DOMException::new(cx, global, DOMErrorName::DataCloneError);
2402 rooted!(&in(cx) let mut rooted_error = UndefinedValue());
2403 error.safe_to_jsval(cx, rooted_error.handle_mut());
2404
2405 port.cross_realm_transform_send_error(cx, rooted_error.handle());
2407
2408 self.controller.error(cx, rooted_error.handle());
2410
2411 global.disentangle_port(cx, port);
2413 }
2414}
2415
2416pub(crate) fn get_read_promise_done(
2418 cx: &mut JSContext,
2419 v: &SafeHandleValue,
2420) -> Result<bool, Error> {
2421 if !v.is_object() {
2422 return Err(Error::Type(c"Unknown format for done property.".to_owned()));
2423 }
2424
2425 rooted!(&in(cx) let object = v.to_object());
2426 get_property::<bool>(cx, object.handle(), c"done", ())?
2427 .ok_or(Error::Type(c"Promise has no done property.".to_owned()))
2428}
2429
2430pub(crate) fn get_read_promise_bytes(
2432 cx: &mut JSContext,
2433 v: &SafeHandleValue,
2434) -> Result<Vec<u8>, Error> {
2435 if !v.is_object() {
2436 return Err(Error::Type(
2437 c"Unknown format for for bytes read.".to_owned(),
2438 ));
2439 }
2440
2441 rooted!(&in(cx) let object = v.to_object());
2442 get_property::<Vec<u8>>(
2443 cx,
2444 object.handle(),
2445 c"value",
2446 ConversionBehavior::EnforceRange,
2447 )?
2448 .ok_or(Error::Type(c"Promise has no value property.".to_owned()))
2449}
2450
2451pub(crate) fn bytes_from_chunk_jsval(
2455 cx: &mut JSContext,
2456 chunk: &RootedTraceableBox<Heap<JSVal>>,
2457) -> Result<Vec<u8>, Error> {
2458 match Vec::<u8>::safe_from_jsval(cx, chunk.handle(), ConversionBehavior::EnforceRange) {
2459 Ok(ConversionResult::Success(vec)) => Ok(vec),
2460 Ok(ConversionResult::Failure(error)) => Err(Error::Type(error.into_owned())),
2461 _ => Err(Error::Type(c"Unknown format for bytes read.".to_owned())),
2462 }
2463}
2464
2465impl Transferable for ReadableStream {
2467 type Index = MessagePortIndex;
2468 type Data = MessagePortImpl;
2469
2470 fn transfer(&self, cx: &mut JSContext) -> Fallible<(MessagePortId, MessagePortImpl)> {
2472 if self.is_locked() {
2475 return Err(Error::DataClone(None));
2476 }
2477
2478 let global = self.global();
2479 let mut realm = enter_auto_realm(cx, &*global);
2480 let mut realm = realm.current_realm();
2481 let cx = &mut realm;
2482
2483 let port_1 = MessagePort::new(cx, &global);
2485 global.track_message_port(&port_1, None);
2486
2487 let port_2 = MessagePort::new(cx, &global);
2489 global.track_message_port(&port_2, None);
2490
2491 global.entangle_ports(*port_1.message_port_id(), *port_2.message_port_id());
2493
2494 let writable = WritableStream::new_with_proto(cx, &global, None);
2496
2497 writable.setup_cross_realm_transform_writable(cx, &port_1);
2499
2500 let promise = self.pipe_to(cx, &global, &writable, false, false, false, None);
2502
2503 promise.set_promise_is_handled(cx);
2505
2506 port_2.transfer(cx)
2508 }
2509
2510 fn transfer_receive(
2512 cx: &mut JSContext,
2513 owner: &GlobalScope,
2514 id: MessagePortId,
2515 port_impl: MessagePortImpl,
2516 ) -> Result<DomRoot<Self>, ()> {
2517 let value = ReadableStream::new_with_proto(cx, owner, None);
2520
2521 let transferred_port = MessagePort::transfer_receive(cx, owner, id, port_impl)?;
2528
2529 value.setup_cross_realm_transform_readable(cx, &transferred_port);
2531 Ok(value)
2532 }
2533
2534 fn serialized_storage<'a>(
2536 data: StructuredData<'a, '_>,
2537 ) -> &'a mut Option<FxHashMap<MessagePortId, Self::Data>> {
2538 match data {
2539 StructuredData::Reader(r) => &mut r.port_impls,
2540 StructuredData::Writer(w) => &mut w.ports,
2541 }
2542 }
2543}
2544
2545pub(crate) fn pipe_through(
2552 source: &ReadableStream,
2553 cx: &mut JSContext,
2554 global: &GlobalScope,
2555 transform: &TextDecoderStream,
2556) -> DomRoot<ReadableStream> {
2557 let mut realm = CurrentRealm::assert(cx);
2563 let promise = source.pipe_to(
2566 &mut realm,
2567 global,
2568 &transform.Writable(),
2569 false, false, false, None, );
2574
2575 promise.set_promise_is_handled(cx);
2577 transform.Readable()
2579}