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

Code before:
            ReadRequest::Read(promise) => {
                // close steps
                // Resolve promise with «[ "value" → undefined, "done" → true ]».
                let result = RootedTraceableBox::new(Heap::default());
                result.set(UndefinedValue());
                promise.resolve_native(
                    &ReadableStreamReadResult {
                        done: Some(true),
                        value: result,
                    },
                    can_gc,
                );
            },
            ReadRequest::DefaultTee { tee_read_request } => {
                tee_read_request.close_steps(can_gc);
            },
            ReadRequest::ReadLoop {
                success_steps,
                reader: _,
                bytes,
                ..
            } => {
                // Step 1. Call successSteps with bytes.
                (success_steps)(&bytes.borrow());
            },
        }
    }

    /// <https://streams.spec.whatwg.org/#read-request-error-steps>
    pub(crate) fn error_steps(&self, e: SafeHandleValue, can_gc: CanGc) {
        match self {
            ReadRequest::Read(promise) => {
                // error steps, given e
                // Reject promise with e.
                promise.reject_native(&e, can_gc)
            },
            ReadRequest::DefaultTee { tee_read_request } => {
                tee_read_request.error_steps();
            },
            ReadRequest::ReadLoop { failure_steps, .. } => {
                // Step 1. Call failureSteps with e.
                let cx = GlobalScope::get_cx();
                (failure_steps)(cx, e);
            },
        }
    }
}

/// The rejection handler for
/// <https://streams.spec.whatwg.org/#readable-stream-tee>
#[derive(Clone, JSTraceable, MallocSizeOf)]

Review comment (bug):
In the test, the [`getReader()`](https://github.com/servo/servo/blob/75e32ba5a49fb35474d7ce1b2a591c9f34773500/tests/wpt/tests/fetch/api/abort/general.any.js#L494) call fails with "stream is locked". 

The spec doesn't say so, but to fix the test, you have to explicitly release the reader in the close and error steps.

See the calls to `self.reader.release` in the previous implementation(like [this one](https://github.com/servo/servo/pull/39510/files#diff-8fa92390cccc8be95f32344c311dbb4355203d03ac5ad8221bf52b3cdea90b71L81)).

Code after:
    pub(crate) fn close_steps(&self, can_gc: CanGc) {
        match self {
            ReadRequest::Read(promise) => {
                // close steps
                // Resolve promise with «[ "value" → undefined, "done" → true ]».
                let result = RootedTraceableBox::new(Heap::default());
                result.set(UndefinedValue());
                promise.resolve_native(
                    &ReadableStreamReadResult {
                        done: Some(true),
                        value: result,
                    },
                    can_gc,
                );
            },
            ReadRequest::DefaultTee { tee_read_request } => {
                tee_read_request.close_steps(can_gc);
            },
            ReadRequest::ReadLoop {
                success_steps,
                reader,
                bytes,
                ..
            } => {
                // Step 1. Call successSteps with bytes.
                (success_steps)(&bytes.borrow());

                reader
                    .release(can_gc)
                    .expect("Releasing the read-all-bytes reader should succeed");
            },
        }
    }

    /// <https://streams.spec.whatwg.org/#read-request-error-steps>
    pub(crate) fn error_steps(&self, e: SafeHandleValue, can_gc: CanGc) {
        match self {
            ReadRequest::Read(promise) => {
                // error steps, given e
                // Reject promise with e.
                promise.reject_native(&e, can_gc)
            },
            ReadRequest::DefaultTee { tee_read_request } => {
                tee_read_request.error_steps();
            },
            ReadRequest::ReadLoop {
                failure_steps,
                reader,
                ..
            } => {
                // Step 1. Call failureSteps with e.