Repository: servo/servo
File: components/script/dom/readablestreamdefaultreader.rs (Rust)

Code before:
struct ContinueReadMicrotask {
    reader: Dom<ReadableStreamDefaultReader>,
    request: ReadRequest,
}

impl Callback for ContinueReadMicrotask {
    fn callback(&self, cx: SafeJSContext, _v: SafeHandleValue, _realm: InRealm, can_gc: CanGc) {
        // Spec: Perform ! ReadableStreamDefaultReaderRead(reader, readRequest).
        self.reader.read(cx, &self.request, can_gc);
    }
}

/// <https://streams.spec.whatwg.org/#read-loop>
fn read_loop(
    reader: &ReadableStreamDefaultReader,
    cx: SafeJSContext,
    success_steps: Rc<ReadAllBytesSuccessSteps>,
    failure_steps: Rc<ReadAllBytesFailureSteps>,
    can_gc: CanGc,
) {
    // For the purposes of the above algorithm, to read-loop given reader,
    // bytes, successSteps, and failureSteps:

    // Step 1 .Let readRequest be a new read request with the following items:
    let req = ReadRequest::ReadLoop {
        success_steps,
        failure_steps,
        reader: Dom::from_ref(reader),
        bytes: Rc::new(DomRefCell::new(Vec::new())),
    };
    // Step 2 .Perform ! ReadableStreamDefaultReaderRead(reader, readRequest).
    reader.read(cx, &req, can_gc);
}

/// <https://streams.spec.whatwg.org/#read-request>
#[derive(Clone, JSTraceable, MallocSizeOf)]
pub(crate) enum ReadRequest {
    /// <https://streams.spec.whatwg.org/#default-reader-read>
    Read(#[ignore_malloc_size_of = "Rc is hard"] Rc<Promise>),
    /// <https://streams.spec.whatwg.org/#ref-for-read-request%E2%91%A2>
    DefaultTee {
        tee_read_request: Dom<DefaultTeeReadRequest>,
    },
    /// Spec read loop variant, driven by read-request steps (no Promise).
    /// <https://streams.spec.whatwg.org/#read-loop>
    ReadLoop {
        #[ignore_malloc_size_of = "Rc is hard"]
        #[no_trace]
        success_steps: Rc<ReadAllBytesSuccessSteps>,
        #[ignore_malloc_size_of = "Rc is hard"]
        #[no_trace]

Review comment (bug):
I think we should mark `ReadRequest` as `crown::unrooted_must_root_lint::must_root`, and that then you will get an error here, and to fix that you should just pass the request directly to the `read` call. 

Code after:
struct ContinueReadMicrotask {
    reader: Dom<ReadableStreamDefaultReader>,
    request: ReadRequest,
}

impl Callback for ContinueReadMicrotask {
    fn callback(&self, cx: SafeJSContext, _v: SafeHandleValue, _realm: InRealm, can_gc: CanGc) {
        // https://streams.spec.whatwg.org/#ref-for-read-loop%E2%91%A0
        // Note: continuing the read-loop from inside a micro-task to break recursion.
        self.reader.read(cx, &self.request, can_gc);
    }
}

/// <https://streams.spec.whatwg.org/#read-loop>
fn read_loop(
    reader: &ReadableStreamDefaultReader,
    cx: SafeJSContext,
    success_steps: Rc<ReadAllBytesSuccessSteps>,
    failure_steps: Rc<ReadAllBytesFailureSteps>,
    can_gc: CanGc,
) {
    // For the purposes of the above algorithm, to read-loop given reader,
    // bytes, successSteps, and failureSteps:

    // Step 1 .Let readRequest be a new read request with the following items:
    let req = ReadRequest::ReadLoop {
        success_steps,
        failure_steps,
        reader: Dom::from_ref(reader),
        bytes: Rc::new(DomRefCell::new(Vec::new())),
    };
    // Step 2 .Perform ! ReadableStreamDefaultReaderRead(reader, readRequest).
    reader.read(cx, &req, can_gc);
}

/// <https://streams.spec.whatwg.org/#read-request>
#[derive(Clone, JSTraceable, MallocSizeOf)]
pub(crate) enum ReadRequest {
    /// <https://streams.spec.whatwg.org/#default-reader-read>
    Read(#[conditional_malloc_size_of] Rc<Promise>),
    /// <https://streams.spec.whatwg.org/#ref-for-read-request%E2%91%A2>
    DefaultTee {
        tee_read_request: Dom<DefaultTeeReadRequest>,
    },
    /// Spec read loop variant, driven by read-request steps (no Promise).
    /// <https://streams.spec.whatwg.org/#read-loop>
    ReadLoop {
        #[ignore_malloc_size_of = "Rc is hard"]
        #[no_trace]
        success_steps: Rc<ReadAllBytesSuccessSteps>,
        #[ignore_malloc_size_of = "Rc is hard"]