function ReadableStreamTee(stream) {
    const reader = AcquireReadableStreamDefaultReader(stream);

    let closedOrErrored = false;
    let canceled1 = false;
    let canceled2 = false;
    let reason1;
    let reason2;
    const cancelPromise = v8.createPromise();

    function pullAlgorithm() {
      return thenPromise(
          ReadableStreamDefaultReaderRead(reader), ({value, done}) => {
            if (done && !closedOrErrored) {
              if (!canceled1) {
                ReadableStreamDefaultControllerClose(branch1controller);
              }
              if (!canceled2) {
                ReadableStreamDefaultControllerClose(branch2controller);
              }
              closedOrErrored = true;
            }

            if (closedOrErrored) {
              return;
            }

            // TODO(ricea): Implement these steps for cloning.
            //
            // vii. Let _value1_ and _value2_ be _value_.
            // viii. If _canceled2_ is false and _cloneForBranch2_ is true, set
            // value2 to ? StructuredDeserialize(? StructuredSerialize(value2),
            // the current Realm Record).

            if (!canceled1) {
              ReadableStreamDefaultControllerEnqueue(branch1controller, value);
            }

            if (!canceled2) {
              ReadableStreamDefaultControllerEnqueue(branch2controller, value);
            }
          });
    }

    function cancel1Algorithm(reason) {
      canceled1 = true;
      reason1 = reason;
      if (canceled2) {
        const cancelResult = ReadableStreamCancel(stream, [reason1, reason2]);
        resolvePromise(cancelPromise, cancelResult);
      }
      return cancelPromise;
    }

    function cancel2Algorithm(reason) {
      canceled2 = true;
      reason2 = reason;
      if (canceled1) {
        const cancelResult = ReadableStreamCancel(stream, [reason1, reason2]);
        resolvePromise(cancelPromise, cancelResult);
      }
      return cancelPromise;
    }

    const startAlgorithm = () => undefined;

    const branch1Stream = CreateReadableStream(
        startAlgorithm, pullAlgorithm, cancel1Algorithm, undefined, undefined,
        false);
    const branch2Stream = CreateReadableStream(
        startAlgorithm, pullAlgorithm, cancel2Algorithm, undefined, undefined,
        false);
    const branch1controller = branch1Stream[_controller];
    const branch2controller = branch2Stream[_controller];

    thenPromise(reader[_closedPromise], undefined, r => {
      if (closedOrErrored === true) {
        return;
      }

      ReadableStreamDefaultControllerError(branch1controller, r);
      ReadableStreamDefaultControllerError(branch2controller, r);
      closedOrErrored = true;
    });

    return [branch1Stream, branch2Stream];
  }
// TODO(domenic): cloneForBranch2 argument from spec not supported yet
cloneForBranch2 argument from spec not supported yet
cloneForBranch2 argument from spec not supported yet
function ReadableStreamTee(stream) {
    const reader = AcquireReadableStreamDefaultReader(stream);
    let closedOrErrored = false;
    let canceled1 = false;
    let canceled2 = false;
    let reason1;
    let reason2;
    const cancelPromise = v8.createPromise();
    function pullAlgorithm() {
      return thenPromise(
          ReadableStreamDefaultReaderRead(reader), ({value, done}) => {
            if (done && !closedOrErrored) {
              if (!canceled1) {
                ReadableStreamDefaultControllerClose(branch1controller);
              }
              if (!canceled2) {
                ReadableStreamDefaultControllerClose(branch2controller);
              }
              closedOrErrored = true;
            }
            if (closedOrErrored) {
              return;
            }
             vii. Let _value1_ and _value2_ be _value_.
             viii. If _canceled2_ is false and _cloneForBranch2_ is true, set
             value2 to ? StructuredDeserialize(? StructuredSerialize(value2),
             the current Realm Record).
            if (!canceled1) {
              ReadableStreamDefaultControllerEnqueue(branch1controller, value);
            }
            if (!canceled2) {
              ReadableStreamDefaultControllerEnqueue(branch2controller, value);
            }
          });
    }
    function cancel1Algorithm(reason) {
      canceled1 = true;
      reason1 = reason;
      if (canceled2) {
        const cancelResult = ReadableStreamCancel(stream, [reason1, reason2]);
        resolvePromise(cancelPromise, cancelResult);
      }
      return cancelPromise;
    }
    function cancel2Algorithm(reason) {
      canceled2 = true;
      reason2 = reason;
      if (canceled1) {
        const cancelResult = ReadableStreamCancel(stream, [reason1, reason2]);
        resolvePromise(cancelPromise, cancelResult);
      }
      return cancelPromise;
    }
    const startAlgorithm = () => undefined;
    const branch1Stream = CreateReadableStream(
        startAlgorithm, pullAlgorithm, cancel1Algorithm, undefined, undefined,
        false);
    const branch2Stream = CreateReadableStream(
        startAlgorithm, pullAlgorithm, cancel2Algorithm, undefined, undefined,
        false);
    const branch1controller = branch1Stream[_controller];
    const branch2controller = branch2Stream[_controller];
    thenPromise(reader[_closedPromise], undefined, r => {
      if (closedOrErrored === true) {
        return;
      }
      ReadableStreamDefaultControllerError(branch1controller, r);
      ReadableStreamDefaultControllerError(branch2controller, r);
      closedOrErrored = true;
    });
    return [branch1Stream, branch2Stream];
  }
function ReadableStreamTee ( stream ) { const reader = AcquireReadableStreamDefaultReader ( stream ) ; let closedOrErrored = false ; let canceled1 = false ; let canceled2 = false ; let reason1 ; let reason2 ; const cancelPromise = v8 . createPromise ( ) ; function pullAlgorithm ( ) { return thenPromise ( ReadableStreamDefaultReaderRead ( reader ) , ( { value , done } ) => { if ( done && ! closedOrErrored ) { if ( ! canceled1 ) { ReadableStreamDefaultControllerClose ( branch1controller ) ; } if ( ! canceled2 ) { ReadableStreamDefaultControllerClose ( branch2controller ) ; } closedOrErrored = true ; } if ( closedOrErrored ) { return ; } if ( ! canceled1 ) { ReadableStreamDefaultControllerEnqueue ( branch1controller , value ) ; } if ( ! canceled2 ) { ReadableStreamDefaultControllerEnqueue ( branch2controller , value ) ; } } ) ; } function cancel1Algorithm ( reason ) { canceled1 = true ; reason1 = reason ; if ( canceled2 ) { const cancelResult = ReadableStreamCancel ( stream , [ reason1 , reason2 ] ) ; resolvePromise ( cancelPromise , cancelResult ) ; } return cancelPromise ; } function cancel2Algorithm ( reason ) { canceled2 = true ; reason2 = reason ; if ( canceled1 ) { const cancelResult = ReadableStreamCancel ( stream , [ reason1 , reason2 ] ) ; resolvePromise ( cancelPromise , cancelResult ) ; } return cancelPromise ; } const startAlgorithm = ( ) => undefined ; const branch1Stream = CreateReadableStream ( startAlgorithm , pullAlgorithm , cancel1Algorithm , undefined , undefined , false ) ; const branch2Stream = CreateReadableStream ( startAlgorithm , pullAlgorithm , cancel2Algorithm , undefined , undefined , false ) ; const branch1controller = branch1Stream [ _controller ] ; const branch2controller = branch2Stream [ _controller ] ; thenPromise ( reader [ _closedPromise ] , undefined , r => { if ( closedOrErrored === true ) { return ; } ReadableStreamDefaultControllerError ( branch1controller , r ) ; ReadableStreamDefaultControllerError ( branch2controller , r ) ; closedOrErrored = true ; } ) ; return [ branch1Stream , branch2Stream ] ; }
TODO(domenic): cloneForBranch2 argument from spec not supported yet
TODO ( domenic ) : cloneForBranch2 argument from spec not supported yet
// TODO(ricea): Implement these steps for cloning. // // vii. Let _value1_ and _value2_ be _value_. // viii. If _canceled2_ is false and _cloneForBranch2_ is true, set // value2 to ? StructuredDeserialize(? StructuredSerialize(value2), // the current Realm Record).