Bug 1504464 - Part 4: Comment-only changes. r=jwalden
authorJason Orendorff <jorendorff@mozilla.com>
Mon, 14 Jan 2019 20:32:31 +0000
changeset 510918 d35260c2032c61c08e1e9af2f5f9fda142097de8
parent 510917 0030c59cdea424b2f7a4dd77a83b9ba5d4b71dd4
child 510919 de74494a1aa7ddfbc6a6475b8e2c3a91eba4dad9
push id10547
push userffxbld-merge
push dateMon, 21 Jan 2019 13:03:58 +0000
treeherdermozilla-beta@24ec1916bffe [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjwalden
bugs1504464
milestone66.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1504464 - Part 4: Comment-only changes. r=jwalden Differential Revision: https://phabricator.services.mozilla.com/D14499
js/src/builtin/Stream.cpp
--- a/js/src/builtin/Stream.cpp
+++ b/js/src/builtin/Stream.cpp
@@ -833,33 +833,33 @@ MOZ_MUST_USE ReadableStream* CreateReada
     HandleValue cancelMethod = UndefinedHandleValue, double highWaterMark = 1,
     HandleValue sizeAlgorithm = UndefinedHandleValue,
     HandleObject proto = nullptr) {
   cx->check(underlyingSource, sizeAlgorithm, proto);
   MOZ_ASSERT(sizeAlgorithm.isUndefined() || IsCallable(sizeAlgorithm));
 
   // Step 1: If highWaterMark was not passed, set it to 1 (implicit).
   // Step 2: If sizeAlgorithm was not passed, set it to an algorithm that
-  // returns 1 (implicit). Step 3: Assert: ! IsNonNegativeNumber(highWaterMark)
-  // is true.
+  //         returns 1 (implicit).
+  // Step 3: Assert: ! IsNonNegativeNumber(highWaterMark) is true.
   MOZ_ASSERT(highWaterMark >= 0);
 
   // Step 4: Let stream be ObjectCreate(the original value of ReadableStream's
-  // prototype property). Step 5: Perform ! InitializeReadableStream(stream).
+  //         prototype property).
+  // Step 5: Perform ! InitializeReadableStream(stream).
   Rooted<ReadableStream*> stream(cx, ReadableStream::create(cx, proto));
   if (!stream) {
     return nullptr;
   }
 
   // Step 6: Let controller be ObjectCreate(the original value of
   //         ReadableStreamDefaultController's prototype property).
   // Step 7: Perform ? SetUpReadableStreamDefaultController(stream,
   //         controller, startAlgorithm, pullAlgorithm, cancelAlgorithm,
   //         highWaterMark, sizeAlgorithm).
-
   if (!SetUpReadableStreamDefaultController(
           cx, stream, sourceAlgorithms, underlyingSource, pullMethod,
           cancelMethod, highWaterMark, sizeAlgorithm)) {
     return nullptr;
   }
 
   // Step 8: Return stream.
   return stream;
@@ -894,17 +894,17 @@ MOZ_MUST_USE /* static */ ReadableStream
 
   // Step 3: Set stream.[[disturbed]] to false (done in step 1).
   MOZ_ASSERT(!stream->disturbed());
 
   return stream;
 }
 
 // Streams spec, 3.3.6. IsReadableStream ( x )
-// Using is<T> instead.
+// Using UnwrapAndTypeCheck templates instead.
 
 // Streams spec, 3.3.7. IsReadableStreamDisturbed ( stream )
 // Using stream->disturbed() instead.
 
 /**
  * Streams spec, 3.3.8. IsReadableStreamLocked ( stream )
  */
 bool ReadableStream::locked() const {
@@ -1312,27 +1312,30 @@ static MOZ_MUST_USE bool ReadableStreamT
 
 /*** 3.4. The interface between readable streams and controllers ************/
 
 inline static MOZ_MUST_USE bool AppendToListAtSlot(
     JSContext* cx, HandleNativeObject unwrappedContainer, uint32_t slot,
     HandleObject obj);
 
 /**
- * Streams spec, 3.4.1. ReadableStreamAddReadIntoRequest ( stream, forAuthorCode
- * ) Streams spec, 3.4.2. ReadableStreamAddReadRequest ( stream, forAuthorCode )
+ * Streams spec, 3.4.1.
+ *      ReadableStreamAddReadIntoRequest ( stream, forAuthorCode )
+ * Streams spec, 3.4.2.
+ *      ReadableStreamAddReadRequest ( stream, forAuthorCode )
  *
  * Our implementation does not pass around forAuthorCode parameters in the same
  * places as the standard, but the effect is the same. See the comment on
  * `ReadableStreamReader::forAuthorCode()`.
  */
 static MOZ_MUST_USE JSObject* ReadableStreamAddReadOrReadIntoRequest(
     JSContext* cx, Handle<ReadableStream*> unwrappedStream) {
-  // Step 1: Assert: ! IsReadableStreamBYOBReader(stream.[[reader]]) is true.
-  // Skipped: handles both kinds of readers.
+  // Step 1: Assert: ! IsReadableStream{BYOB,Default}Reader(stream.[[reader]])
+  //         is true.
+  // (Only default readers exist so far.)
   Rooted<ReadableStreamReader*> unwrappedReader(
       cx, UnwrapReaderFromStream(cx, unwrappedStream));
   if (!unwrappedReader) {
     return nullptr;
   }
 
   // Step 2 of 3.4.2: Assert: stream.[[state]] is "readable".
   MOZ_ASSERT_IF(unwrappedReader->is<ReadableStreamDefaultReader>(),
@@ -1413,17 +1416,17 @@ static MOZ_MUST_USE JSObject* ReadableSt
   Rooted<ReadableStreamController*> unwrappedController(
       cx, unwrappedStream->controller());
   RootedObject sourceCancelPromise(
       cx, ReadableStreamControllerCancelSteps(cx, unwrappedController, reason));
   if (!sourceCancelPromise) {
     return nullptr;
   }
 
-  // Step 6: Return the result of transforming sourceCancelPromise by a
+  // Step 6: Return the result of transforming sourceCancelPromise with a
   //         fulfillment handler that returns undefined.
   RootedAtom funName(cx, cx->names().empty);
   RootedFunction returnUndefined(
       cx, NewNativeFunction(cx, ReturnUndefined, 0, funName));
   if (!returnUndefined) {
     return nullptr;
   }
   return JS::CallOriginalPromiseThen(cx, sourceCancelPromise, returnUndefined,
@@ -1488,17 +1491,16 @@ MOZ_MUST_USE bool ReadableStreamCloseInt
       }
     }
 
     // Step b: Set reader.[[readRequests]] to an empty List.
     unwrappedReader->clearRequests();
   }
 
   // Step 6: Resolve reader.[[closedPromise]] with undefined.
-  // Step 7: Return (implicit).
   RootedObject closedPromise(cx, unwrappedReader->closedPromise());
   if (!cx->compartment()->wrap(cx, &closedPromise)) {
     return false;
   }
   if (!ResolvePromise(cx, closedPromise, UndefinedHandleValue)) {
     return false;
   }
 
@@ -1578,51 +1580,50 @@ MOZ_MUST_USE bool ReadableStreamErrorInt
 
   // Step 5: Let reader be stream.[[reader]].
   Rooted<ReadableStreamReader*> unwrappedReader(
       cx, UnwrapReaderFromStream(cx, unwrappedStream));
   if (!unwrappedReader) {
     return false;
   }
 
-  // Steps 7,8: (Identical in our implementation.)
-  // Step a: Repeat for each readRequest that is an element of
-  //         reader.[[readRequests]],
+  // Steps 7-8: (Identical in our implementation.)
+  // Step 7.a/8.b: Repeat for each read{Into}Request that is an element of
+  //               reader.[[read{Into}Requests]],
   Rooted<ListObject*> unwrappedReadRequests(cx, unwrappedReader->requests());
   RootedObject readRequest(cx);
   RootedValue val(cx);
   uint32_t len = unwrappedReadRequests->length();
   for (uint32_t i = 0; i < len; i++) {
-    // Step i: Reject readRequest.[[promise]] with e.
+    // Step i: Reject read{Into}Request.[[promise]] with e.
     val = unwrappedReadRequests->get(i);
     readRequest = &val.toObject();
 
     // Responses have to be created in the compartment from which the
     // error was triggered, which might not be the same as the one the
     // request was created in, so we have to wrap requests here.
     if (!cx->compartment()->wrap(cx, &readRequest)) {
       return false;
     }
 
     if (!RejectPromise(cx, readRequest, e)) {
       return false;
     }
   }
 
-  // Step b: Set reader.[[readRequests]] to a new empty List.
+  // Step 7.b/8.c: Set reader.[[read{Into}Requests]] to a new empty List.
   if (!SetNewList(cx, unwrappedReader, ReadableStreamReader::Slot_Requests)) {
     return false;
   }
 
   // Step 9: Reject reader.[[closedPromise]] with e.
   //
   // The closedPromise might have been created in another compartment.
-  // RejectPromise can deal with wrapped Promise objects, but has to be
-  // with all arguments in the current compartment, so we do need to wrap
-  // the Promise.
+  // RejectPromise can deal with wrapped Promise objects, but all its arguments
+  // must be same-compartment with cx, so we do need to wrap the Promise.
   RootedObject closedPromise(cx, unwrappedReader->closedPromise());
   if (!cx->compartment()->wrap(cx, &closedPromise)) {
     return false;
   }
   if (!RejectPromise(cx, closedPromise, e)) {
     return false;
   }
 
@@ -1658,21 +1659,21 @@ static MOZ_MUST_USE bool ReadableStreamF
 
   // Step 1: Let reader be stream.[[reader]].
   Rooted<ReadableStreamReader*> unwrappedReader(
       cx, UnwrapReaderFromStream(cx, unwrappedStream));
   if (!unwrappedReader) {
     return false;
   }
 
-  // Step 2: Let readIntoRequest be the first element of
-  //         reader.[[readIntoRequests]].
-  // Step 3: Remove readIntoRequest from reader.[[readIntoRequests]], shifting
-  //         all other elements downward (so that the second becomes the first,
-  //         and so on).
+  // Step 2: Let read{Into}Request be the first element of
+  //         reader.[[read{Into}Requests]].
+  // Step 3: Remove read{Into}Request from reader.[[read{Into}Requests]],
+  //         shifting all other elements downward (so that the second becomes
+  //         the first, and so on).
   Rooted<ListObject*> unwrappedReadIntoRequests(cx,
                                                 unwrappedReader->requests());
   RootedObject readIntoRequest(
       cx, &unwrappedReadIntoRequests->popFirstAs<JSObject>(cx));
   MOZ_ASSERT(readIntoRequest);
   if (!cx->compartment()->wrap(cx, &readIntoRequest)) {
     return false;
   }
@@ -1692,17 +1693,17 @@ static MOZ_MUST_USE bool ReadableStreamF
 
 /**
  * Streams spec, 3.4.9. ReadableStreamGetNumReadIntoRequests ( stream )
  * Streams spec, 3.4.10. ReadableStreamGetNumReadRequests ( stream )
  * (Identical implementation.)
  */
 static uint32_t ReadableStreamGetNumReadRequests(ReadableStream* stream) {
   // Step 1: Return the number of elements in
-  //         stream.[[reader]].[[readRequests]].
+  //         stream.[[reader]].[[read{Into}Requests]].
   if (!stream->hasReader()) {
     return 0;
   }
 
   JS::AutoSuppressGCAnalysis nogc;
   ReadableStreamReader* reader = UnwrapReaderFromStreamNoThrow(stream);
 
   // Reader is a dead wrapper, treat it as non-existent.
@@ -1719,25 +1720,24 @@ static uint32_t ReadableStreamGetNumRead
 static MOZ_MUST_USE bool ReadableStreamHasDefaultReader(
     JSContext* cx, Handle<ReadableStream*> unwrappedStream, bool* result) {
   // Step 1: Let reader be stream.[[reader]].
   // Step 2: If reader is undefined, return false.
   if (!unwrappedStream->hasReader()) {
     *result = false;
     return true;
   }
-
-  // Step 3: If ! ReadableStreamDefaultReader(reader) is false, return false.
-  // Step 4: Return true.
   Rooted<ReadableStreamReader*> unwrappedReader(
       cx, UnwrapReaderFromStream(cx, unwrappedStream));
   if (!unwrappedReader) {
     return false;
   }
 
+  // Step 3: If ! ReadableStreamDefaultReader(reader) is false, return false.
+  // Step 4: Return true.
   *result = unwrappedReader->is<ReadableStreamDefaultReader>();
   return true;
 }
 
 /*** 3.5. Class ReadableStreamDefaultReader *********************************/
 
 static MOZ_MUST_USE bool ReadableStreamReaderGenericInitialize(
     JSContext* cx, Handle<ReadableStreamReader*> reader,
@@ -1789,17 +1789,17 @@ bool ReadableStreamDefaultReader::constr
 
   // Implicit in the spec: Find the prototype object to use.
   RootedObject proto(cx);
   if (!GetPrototypeFromBuiltinConstructor(cx, args, JSProto_Null, &proto)) {
     return false;
   }
 
   // Step 1: If ! IsReadableStream(stream) is false, throw a TypeError
-  // exception.
+  //         exception.
   Rooted<ReadableStream*> unwrappedStream(
       cx, UnwrapAndTypeCheckArgument<ReadableStream>(
               cx, args, "ReadableStreamDefaultReader constructor", 0));
   if (!unwrappedStream) {
     return false;
   }
 
   RootedObject reader(
@@ -2159,48 +2159,48 @@ static MOZ_MUST_USE bool ReadableStreamR
 
   return true;
 }
 
 static MOZ_MUST_USE JSObject* ReadableStreamControllerPullSteps(
     JSContext* cx, Handle<ReadableStreamController*> unwrappedController);
 
 /**
- * Streams spec, 3.7.7. ReadableStreamDefaultReaderRead ( reader [,
- * forAuthorCode ] )
+ * Streams spec, 3.7.7.
+ *      ReadableStreamDefaultReaderRead ( reader [, forAuthorCode ] )
  */
 static MOZ_MUST_USE JSObject* ReadableStreamDefaultReaderRead(
     JSContext* cx, Handle<ReadableStreamDefaultReader*> unwrappedReader) {
   // Step 1: If forAuthorCode was not passed, set it to false (implicit).
 
   // Step 2: Let stream be reader.[[ownerReadableStream]].
   // Step 3: Assert: stream is not undefined.
   Rooted<ReadableStream*> unwrappedStream(
       cx, UnwrapStreamFromReader(cx, unwrappedReader));
   if (!unwrappedStream) {
     return nullptr;
   }
 
   // Step 4: Set stream.[[disturbed]] to true.
   unwrappedStream->setDisturbed();
 
-  // Step 5: If stream.[[state]] is "closed", return a new promise resolved with
+  // Step 5: If stream.[[state]] is "closed", return a promise resolved with
   //         ! ReadableStreamCreateReadResult(undefined, true, forAuthorCode).
   if (unwrappedStream->closed()) {
     RootedObject iterResult(
         cx, ReadableStreamCreateReadResult(cx, UndefinedHandleValue, true,
                                            unwrappedReader->forAuthorCode()));
     if (!iterResult) {
       return nullptr;
     }
     RootedValue iterResultVal(cx, ObjectValue(*iterResult));
     return PromiseObject::unforgeableResolve(cx, iterResultVal);
   }
 
-  // Step 6: If stream.[[state]] is "errored", return a new promise rejected
+  // Step 6: If stream.[[state]] is "errored", return a promise rejected
   //         with stream.[[storedError]].
   if (unwrappedStream->errored()) {
     RootedValue storedError(cx, unwrappedStream->storedError());
     if (!cx->compartment()->wrap(cx, &storedError)) {
       return nullptr;
     }
     return PromiseObject::unforgeableReject(cx, storedError);
   }
@@ -2215,61 +2215,60 @@ static MOZ_MUST_USE JSObject* ReadableSt
 }
 
 /*** 3.8. Class ReadableStreamDefaultController *****************************/
 
 inline static MOZ_MUST_USE bool ReadableStreamControllerCallPullIfNeeded(
     JSContext* cx, Handle<ReadableStreamController*> unwrappedController);
 
 /**
- * Streams spec, 3.8.3, step 11.a.
+ * Streams spec, 3.9.11. SetUpReadableStreamDefaultController, step 11
  * and
- * Streams spec, 3.10.3, step 16.a.
+ * Streams spec, 3.12.26. SetUpReadableByteStreamController, step 16:
+ *      Upon fulfillment of startPromise, [...]
  */
 static bool ControllerStartHandler(JSContext* cx, unsigned argc, Value* vp) {
   CallArgs args = CallArgsFromVp(argc, vp);
   Rooted<ReadableStreamController*> controller(
       cx, TargetFromHandler<ReadableStreamController>(args));
 
-  // Step i: Set controller.[[started]] to true.
+  // Step a: Set controller.[[started]] to true.
   controller->setStarted();
 
-  // Step ii: Assert: controller.[[pulling]] is false.
+  // Step b: Assert: controller.[[pulling]] is false.
   MOZ_ASSERT(!controller->pulling());
 
-  // Step iii: Assert: controller.[[pullAgain]] is false.
+  // Step c: Assert: controller.[[pullAgain]] is false.
   MOZ_ASSERT(!controller->pullAgain());
 
-  // Step iv: Perform
-  //          ! ReadableStreamDefaultControllerCallPullIfNeeded(controller).
-  // or
-  // Step iv: Perform
-  //          ! ReadableByteStreamControllerCallPullIfNeeded((controller).
+  // Step d: Perform
+  //      ! ReadableStreamDefaultControllerCallPullIfNeeded(controller)
+  //      (or ReadableByteStreamControllerCallPullIfNeeded(controller)).
   if (!ReadableStreamControllerCallPullIfNeeded(cx, controller)) {
     return false;
   }
   args.rval().setUndefined();
   return true;
 }
 
 /**
- * Streams spec, 3.9.11, step 12.a.
+ * Streams spec, 3.9.11. SetUpReadableStreamDefaultController, step 12
  * and
- * Streams spec, 3.12.26, step 17.a.
+ * Streams spec, 3.12.26. SetUpReadableByteStreamController, step 17:
+ *      Upon rejection of startPromise with reason r, [...]
  */
 static bool ControllerStartFailedHandler(JSContext* cx, unsigned argc,
                                          Value* vp) {
   CallArgs args = CallArgsFromVp(argc, vp);
   Rooted<ReadableStreamController*> controller(
       cx, TargetFromHandler<ReadableStreamController>(args));
 
-  // 3.9.11, Step 12.a: Perform
-  //      ! ReadableStreamDefaultControllerError(controller, r).
-  // 3.12.26, Step 17.a: Perform
-  //      ! ReadableByteStreamControllerError(controller, r).
+  // Step a: Perform
+  //      ! ReadableStreamDefaultControllerError(controller, r)
+  //      (or ReadableByteStreamControllerError(controller, r)).
   if (!ReadableStreamControllerError(cx, controller, args.get(0))) {
     return false;
   }
 
   args.rval().setUndefined();
   return true;
 }
 
@@ -2287,33 +2286,31 @@ bool ReadableStreamDefaultController::co
   return false;
 }
 
 static MOZ_MUST_USE double ReadableStreamControllerGetDesiredSizeUnchecked(
     ReadableStreamController* controller);
 
 /**
  * Streams spec, 3.8.4.1. get desiredSize
- * and
- * Streams spec, 3.10.4.2. get desiredSize
  */
 static bool ReadableStreamDefaultController_desiredSize(JSContext* cx,
                                                         unsigned argc,
                                                         Value* vp) {
   // Step 1: If ! IsReadableStreamDefaultController(this) is false, throw a
   //         TypeError exception.
   CallArgs args = CallArgsFromVp(argc, vp);
   Rooted<ReadableStreamController*> unwrappedController(
       cx, UnwrapAndTypeCheckThis<ReadableStreamDefaultController>(
               cx, args, "get desiredSize"));
   if (!unwrappedController) {
     return false;
   }
 
-  // Streams spec, 3.9.8. steps 1-4.
+  // 3.9.8. ReadableStreamDefaultControllerGetDesiredSize, steps 1-4.
   // 3.9.8. Step 1: Let stream be controller.[[controlledReadableStream]].
   ReadableStream* unwrappedStream = unwrappedController->stream();
 
   // 3.9.8. Step 2: Let state be stream.[[state]].
   // 3.9.8. Step 3: If state is "errored", return null.
   if (unwrappedStream->errored()) {
     args.rval().setNull();
     return true;
@@ -2331,17 +2328,18 @@ static bool ReadableStreamDefaultControl
   return true;
 }
 
 static MOZ_MUST_USE bool ReadableStreamDefaultControllerClose(
     JSContext* cx,
     Handle<ReadableStreamDefaultController*> unwrappedController);
 
 /**
- * Unified implementation of step 2 of 3.8.4.2 and steps 2-3 of 3.10.4.3.
+ * Unified implementation of step 2 of 3.8.4.2 and 3.8.4.3,
+ * and steps 2-3 of 3.10.4.3.
  */
 static MOZ_MUST_USE bool VerifyControllerStateForClosing(
     JSContext* cx, Handle<ReadableStreamController*> unwrappedController) {
   // Step 2: If this.[[closeRequested]] is true, throw a TypeError exception.
   if (unwrappedController->closeRequested()) {
     JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr,
                               JSMSG_READABLESTREAMCONTROLLER_CLOSED, "close");
     return false;
@@ -2375,20 +2373,21 @@ static bool ReadableStreamDefaultControl
     return false;
   }
 
   // Steps 2-3.
   if (!VerifyControllerStateForClosing(cx, unwrappedController)) {
     return false;
   }
 
-  // Step 4: Perform ! ReadableStreamDefaultControllerClose(this).
+  // Step 3: Perform ! ReadableStreamDefaultControllerClose(this).
   if (!ReadableStreamDefaultControllerClose(cx, unwrappedController)) {
     return false;
   }
+
   args.rval().setUndefined();
   return true;
 }
 
 /**
  * Streams spec, 3.8.4.3. enqueue ( chunk )
  */
 static bool ReadableStreamDefaultController_enqueue(JSContext* cx,
@@ -2578,48 +2577,49 @@ static MOZ_MUST_USE JSObject* ReadableSt
                              wrappedReason);
       }
       if (!cx->compartment()->wrap(cx, &result)) {
         result = nullptr;
       }
     }
   }
 
-  // Step 3 of 3.8.5.1, step 4 of 3.10.5.1: Perform
-  //      ! ReadableByteStreamControllerClearAlgorithms(this).
+  // Step 3 (or 4): Perform
+  //      ! ReadableStreamDefaultControllerClearAlgorithms(this)
+  //      (or ReadableByteStreamControllerClearAlgorithms(this)).
   ReadableStreamControllerClearAlgorithms(unwrappedController);
 
-  // Step 4 of 3.8.5.1, step 5 of 3.10.5.1: Return result.
+  // Step 4 (or 5): Return result.
   return result;
 }
 
 inline static MOZ_MUST_USE bool DequeueValue(
     JSContext* cx, Handle<ReadableStreamController*> unwrappedContainer,
     MutableHandleValue chunk);
 
 /**
- * Streams spec, 3.8.5.2. ReadableStreamDefaultController [[PullSteps]](
- * forAuthorCode )
+ * Streams spec, 3.8.5.2.
+ *     ReadableStreamDefaultController [[PullSteps]]( forAuthorCode )
  */
 static JSObject* ReadableStreamDefaultControllerPullSteps(
     JSContext* cx,
     Handle<ReadableStreamDefaultController*> unwrappedController) {
   // Step 1: Let stream be this.[[controlledReadableStream]].
   Rooted<ReadableStream*> unwrappedStream(cx, unwrappedController->stream());
 
   // Step 2: If this.[[queue]] is not empty,
   Rooted<ListObject*> unwrappedQueue(cx);
   RootedValue val(
       cx, unwrappedController->getFixedSlot(StreamController::Slot_Queue));
   if (val.isObject()) {
     unwrappedQueue = &val.toObject().as<ListObject>();
   }
 
   if (unwrappedQueue && unwrappedQueue->length() != 0) {
-    // Step a: Let chunk be ! DequeueValue(this.[[queue]]).
+    // Step a: Let chunk be ! DequeueValue(this).
     RootedValue chunk(cx);
     if (!DequeueValue(cx, unwrappedController, &chunk)) {
       return nullptr;
     }
 
     // Step b: If this.[[closeRequested]] is true and this.[[queue]] is empty,
     //         perform ! ReadableStreamClose(stream).
     if (unwrappedController->closeRequested() &&
@@ -2674,17 +2674,17 @@ static JSObject* ReadableStreamDefaultCo
 
 /*** 3.9. Readable stream default controller abstract operations ************/
 
 // Streams spec, 3.9.1. IsReadableStreamDefaultController ( x )
 // Implemented via is<ReadableStreamDefaultController>()
 
 /**
  * Streams spec, 3.9.2 and 3.12.3. step 7:
- * Upon fulfillment of pullPromise,
+ *      Upon fulfillment of pullPromise, [...]
  */
 static bool ControllerPullHandler(JSContext* cx, unsigned argc, Value* vp) {
   CallArgs args = CallArgsFromVp(argc, vp);
 
   Rooted<ReadableStreamController*> controller(
       cx, UnwrapCalleeSlot<ReadableStreamController>(cx, args, 0));
   if (!controller) {
     return false;
@@ -2837,79 +2837,91 @@ inline static MOZ_MUST_USE bool Readable
         return false;
       }
     }
   }
   if (!pullPromise) {
     return false;
   }
 
+  // Step 7: Upon fulfillment of pullPromise, [...]
+  // Step 8. Upon rejection of pullPromise with reason e, [...]
   RootedObject onPullFulfilled(
       cx, NewHandler(cx, ControllerPullHandler, wrappedController));
   if (!onPullFulfilled) {
     return false;
   }
-
   RootedObject onPullRejected(
       cx, NewHandler(cx, ControllerPullFailedHandler, wrappedController));
   if (!onPullRejected) {
     return false;
   }
-
   return JS::AddPromiseReactions(cx, pullPromise, onPullFulfilled,
                                  onPullRejected);
-
-  // Steps 7-8 implemented in functions above.
 }
 
 /**
  * Streams spec, 3.9.3.
  *      ReadableStreamDefaultControllerShouldCallPull ( controller )
  * Streams spec, 3.12.25.
  *      ReadableByteStreamControllerShouldCallPull ( controller )
  */
 static bool ReadableStreamControllerShouldCallPull(
     ReadableStreamController* unwrappedController) {
-  // Step 1: Let stream be controller.[[controlledReadableStream]].
+  // Step 1: Let stream be controller.[[controlledReadableStream]]
+  //         (or [[controlledReadableByteStream]]).
   ReadableStream* unwrappedStream = unwrappedController->stream();
 
-  // Step 2: If stream.[[state]] is "closed" or stream.[[state]] is "errored",
-  //         return false.
-  // or, equivalently
-  // Step 2: If stream.[[state]] is not "readable", return false.
+  // 3.9.3. Step 2:
+  //      If ! ReadableStreamDefaultControllerCanCloseOrEnqueue(controller)
+  //      is false, return false.
+  // This turns out to be the same as 3.12.25 steps 2-3.
+
+  // 3.12.25 Step 2: If stream.[[state]] is not "readable", return false.
   if (!unwrappedStream->readable()) {
     return false;
   }
 
-  // Step 3: If controller.[[closeRequested]] is true, return false.
+  // 3.12.25 Step 3: If controller.[[closeRequested]] is true, return false.
   if (unwrappedController->closeRequested()) {
     return false;
   }
 
-  // Step 4: If controller.[[started]] is false, return false.
+  // Step 3 (or 4):
+  //      If controller.[[started]] is false, return false.
   if (!unwrappedController->started()) {
     return false;
   }
 
-  // Step 5: If ! IsReadableStreamLocked(stream) is true and
+  // 3.9.3.
+  // Step 4: If ! IsReadableStreamLocked(stream) is true and
+  //      ! ReadableStreamGetNumReadRequests(stream) > 0, return true.
+  //
+  // 3.12.25.
+  // Step 5: If ! ReadableStreamHasDefaultReader(stream) is true and
   //         ! ReadableStreamGetNumReadRequests(stream) > 0, return true.
-  // Steps 5-6 of 3.12.24 are equivalent in our implementation.
+  // Step 6: If ! ReadableStreamHasBYOBReader(stream) is true and
+  //         ! ReadableStreamGetNumReadIntoRequests(stream) > 0, return true.
+  //
+  // All of these amount to the same thing in this implementation:
   if (unwrappedStream->locked() &&
       ReadableStreamGetNumReadRequests(unwrappedStream) > 0) {
     return true;
   }
 
-  // Step 6: Let desiredSize be
-  //         ReadableStreamDefaultControllerGetDesiredSize(controller).
+  // Step 5 (or 7):
+  //      Let desiredSize be
+  //      ! ReadableStreamDefaultControllerGetDesiredSize(controller).
+  //      (ReadableByteStreamControllerGetDesiredSize in 3.12.25.)
   double desiredSize =
       ReadableStreamControllerGetDesiredSizeUnchecked(unwrappedController);
 
-  // Step 7: If desiredSize > 0, return true.
-  // Step 8: Return false.
-  // Steps 7-8 of 3.12.24 are equivalent in our implementation.
+  // Step 6 (or 8): Assert: desiredSize is not null (implicit).
+  // Step 7 (or 9): If desiredSize > 0, return true.
+  // Step 8 (or 10): Return false.
   return desiredSize > 0;
 }
 
 /**
  * Streams spec, 3.9.4.
  *      ReadableStreamDefaultControllerClearAlgorithms ( controller )
  * and 3.12.4.
  *      ReadableByteStreamControllerClearAlgorithms ( controller )
@@ -2934,23 +2946,23 @@ static void ReadableStreamControllerClea
  * Streams spec, 3.9.5. ReadableStreamDefaultControllerClose ( controller )
  */
 static MOZ_MUST_USE bool ReadableStreamDefaultControllerClose(
     JSContext* cx,
     Handle<ReadableStreamDefaultController*> unwrappedController) {
   // Step 1: Let stream be controller.[[controlledReadableStream]].
   Rooted<ReadableStream*> unwrappedStream(cx, unwrappedController->stream());
 
-  // Step 2: Assert: controller.[[closeRequested]] is false.
+  // Step 2: Assert:
+  //         ! ReadableStreamDefaultControllerCanCloseOrEnqueue(controller)
+  //         is true.
   MOZ_ASSERT(!unwrappedController->closeRequested());
-
-  // Step 3: Assert: stream.[[state]] is "readable".
   MOZ_ASSERT(unwrappedStream->readable());
 
-  // Step 4: Set controller.[[closeRequested]] to true.
+  // Step 3: Set controller.[[closeRequested]] to true.
   unwrappedController->setCloseRequested();
 
   // Step 5: If controller.[[queue]] is empty, perform
   //         ! ReadableStreamClose(stream).
   Rooted<ListObject*> unwrappedQueue(cx, unwrappedController->queue());
   if (unwrappedQueue->length() == 0) {
     return ReadableStreamCloseInternal(cx, unwrappedStream);
   }
@@ -3003,20 +3015,20 @@ static MOZ_MUST_USE bool ReadableStreamD
     }
 
     // Step d: Let enqueueResult be
     //         EnqueueValueWithSize(controller, chunk, chunkSize).
     if (success) {
       success = EnqueueValueWithSize(cx, unwrappedController, chunk, chunkSize);
     }
 
+    // Step b: If result is an abrupt completion,
+    // and
+    // Step e: If enqueueResult is an abrupt completion,
     if (!success) {
-      // Step b: If result is an abrupt completion,
-      // and
-      // Step e: If enqueueResult is an abrupt completion,
       RootedValue exn(cx);
       if (!cx->isExceptionPending() || !GetAndClearException(cx, &exn)) {
         // Uncatchable error. Die immediately without erroring the
         // stream.
         return false;
       }
 
       // Step b.i: Perform ! ReadableStreamDefaultControllerError(
@@ -3030,36 +3042,36 @@ static MOZ_MUST_USE bool ReadableStreamD
       // Step b.ii: Return result.
       // Step e.ii: Return enqueueResult.
       // (I.e., propagate the exception.)
       cx->setPendingException(exn);
       return false;
     }
   }
 
-  // Step 6: Perform
+  // Step 5: Perform
   //         ! ReadableStreamDefaultControllerCallPullIfNeeded(controller).
-  // Step 7: Return.
   return ReadableStreamControllerCallPullIfNeeded(cx, unwrappedController);
 }
 
 static MOZ_MUST_USE bool ReadableByteStreamControllerClearPendingPullIntos(
     JSContext* cx, Handle<ReadableByteStreamController*> unwrappedController);
 
 /**
  * Streams spec, 3.9.7. ReadableStreamDefaultControllerError ( controller, e )
  * Streams spec, 3.12.11. ReadableByteStreamControllerError ( controller, e )
  */
 static MOZ_MUST_USE bool ReadableStreamControllerError(
     JSContext* cx, Handle<ReadableStreamController*> unwrappedController,
     HandleValue e) {
   MOZ_ASSERT(!cx->isExceptionPending());
   AssertSameCompartment(cx, e);
 
-  // Step 1: Let stream be controller.[[controlledReadableStream]].
+  // Step 1: Let stream be controller.[[controlledReadableStream]]
+  //         (or controller.[[controlledReadableByteStream]]).
   Rooted<ReadableStream*> unwrappedStream(cx, unwrappedController->stream());
 
   // Step 2: If stream.[[state]] is not "readable", return.
   if (!unwrappedStream->readable()) {
     return true;
   }
 
   // Step 3 of 3.12.10:
@@ -3209,23 +3221,21 @@ static MOZ_MUST_USE bool SetUpReadableSt
 
   // Step 11: Upon fulfillment of startPromise, [...]
   // Step 12: Upon rejection of startPromise with reason r, [...]
   RootedObject onStartFulfilled(
       cx, NewHandler(cx, ControllerStartHandler, controller));
   if (!onStartFulfilled) {
     return false;
   }
-
   RootedObject onStartRejected(
       cx, NewHandler(cx, ControllerStartFailedHandler, controller));
   if (!onStartRejected) {
     return false;
   }
-
   if (!JS::AddPromiseReactions(cx, startPromise, onStartFulfilled,
                                onStartRejected)) {
     return false;
   }
 
   return true;
 }
 
@@ -3273,17 +3283,16 @@ SetUpReadableStreamDefaultControllerFrom
           cx, underlyingSource, "ReadableStream source.cancel method",
           cx->names().cancel, &cancelMethod)) {
     return false;
   }
 
   // Step 6. Perform ? SetUpReadableStreamDefaultController(stream,
   //             controller, startAlgorithm, pullAlgorithm, cancelAlgorithm,
   //             highWaterMark, sizeAlgorithm).
-
   return SetUpReadableStreamDefaultController(
       cx, stream, sourceAlgorithms, underlyingSource, pullMethod, cancelMethod,
       highWaterMark, sizeAlgorithm);
 }
 
 /*** 3.10. Class ReadableByteStreamController *******************************/
 
 #if 0  // disable user-defined byte streams
@@ -3415,18 +3424,18 @@ bool ReadableByteStreamController::const
   // Step 1: Throw a TypeError exception.
   JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr,
                             JSMSG_BOGUS_CONSTRUCTOR,
                             "ReadableByteStreamController");
   return false;
 }
 
 /**
- * Version of the ReadableByteStreamConstructor that's specialized for
- * handling external, embedding-provided, underlying sources.
+ * Version of SetUpReadableByteStreamController that's specialized for handling
+ * external, embedding-provided, underlying sources.
  */
 static MOZ_MUST_USE bool SetUpExternalReadableByteStreamController(
     JSContext* cx, Handle<ReadableStream*> stream,
     JS::ReadableStreamUnderlyingSource* source) {
   // Done elsewhere in the standard: Create the controller object.
   Rooted<ReadableByteStreamController*> controller(
       cx, NewBuiltinClassInstance<ReadableByteStreamController>(cx));
   if (!controller) {
@@ -3557,17 +3566,17 @@ CLASS_SPEC(ReadableByteStreamController,
 static MOZ_MUST_USE bool ReadableByteStreamControllerHandleQueueDrain(
     JSContext* cx, Handle<ReadableStreamController*> unwrappedController);
 
 /**
  * Streams spec, 3.10.5.2. [[PullSteps]] ( forAuthorCode )
  */
 static MOZ_MUST_USE JSObject* ReadableByteStreamControllerPullSteps(
     JSContext* cx, Handle<ReadableByteStreamController*> unwrappedController) {
-  // Step 1: Let stream be this.[[controlledReadableStream]].
+  // Step 1: Let stream be this.[[controlledReadableByteStream]].
   Rooted<ReadableStream*> unwrappedStream(cx, unwrappedController->stream());
 
   // Step 2: Assert: ! ReadableStreamHasDefaultReader(stream) is true.
 #ifdef DEBUG
   bool result;
   if (!ReadableStreamHasDefaultReader(cx, unwrappedStream, &result)) {
     return nullptr;
   }
@@ -3695,17 +3704,18 @@ static MOZ_MUST_USE JSObject* ReadableBy
     }
 
     RootedArrayBufferObject buffer(cx, &bufferObj->as<ArrayBufferObject>());
 
     // Step 5.c: Let pullIntoDescriptor be
     //           Record {[[buffer]]: buffer.[[Value]],
     //                   [[byteOffset]]: 0,
     //                   [[byteLength]]: autoAllocateChunkSize,
-    //                   [[bytesFilled]]: 0, [[elementSize]]: 1,
+    //                   [[bytesFilled]]: 0,
+    //                   [[elementSize]]: 1,
     //                   [[ctor]]: %Uint8Array%,
     //                   [[readerType]]: `"default"`}.
     RootedObject pullIntoDescriptor(
         cx, PullIntoDescriptor::create(cx, buffer, 0, autoAllocateChunkSize, 0,
                                        1, nullptr, ReaderType_Default));
     if (!pullIntoDescriptor) {
       return PromiseRejectedWithPendingError(cx);
     }
@@ -3715,17 +3725,17 @@ static MOZ_MUST_USE JSObject* ReadableBy
     if (!AppendToListAtSlot(cx, unwrappedController,
                             ReadableByteStreamController::Slot_PendingPullIntos,
                             pullIntoDescriptor)) {
       return nullptr;
     }
   }
 
   // Step 6: Let promise be ! ReadableStreamAddReadRequest(stream,
-  // forAuthorCode).
+  //                                                       forAuthorCode).
   RootedObject promise(
       cx, ReadableStreamAddReadOrReadIntoRequest(cx, unwrappedStream));
   if (!promise) {
     return nullptr;
   }
 
   // Step 7: Perform ! ReadableByteStreamControllerCallPullIfNeeded(this).
   if (!ReadableStreamControllerCallPullIfNeeded(cx, unwrappedController)) {
@@ -3790,17 +3800,17 @@ static MOZ_MUST_USE bool ReadableByteStr
                     ReadableByteStreamController::Slot_PendingPullIntos);
 }
 
 /**
  * Streams spec, 3.12.6. ReadableByteStreamControllerClose ( controller )
  */
 static MOZ_MUST_USE bool ReadableByteStreamControllerClose(
     JSContext* cx, Handle<ReadableByteStreamController*> unwrappedController) {
-  // Step 1: Let stream be controller.[[controlledReadableStream]].
+  // Step 1: Let stream be controller.[[controlledReadableByteStream]].
   Rooted<ReadableStream*> unwrappedStream(cx, unwrappedController->stream());
 
   // Step 2: Assert: controller.[[closeRequested]] is false.
   MOZ_ASSERT(!unwrappedController->closeRequested());
 
   // Step 3: Assert: stream.[[state]] is "readable".
   MOZ_ASSERT(unwrappedStream->readable());
 
@@ -4089,29 +4099,27 @@ inline static MOZ_MUST_USE bool DequeueV
   MOZ_ASSERT(unwrappedPair);
 
   // Step 5: Set container.[[queueTotalSize]] to
   //         container.[[queueTotalSize]] − pair.[[size]].
   // Step 6: If container.[[queueTotalSize]] < 0, set
   //         container.[[queueTotalSize]] to 0.
   //         (This can occur due to rounding errors.)
   double totalSize = unwrappedContainer->queueTotalSize();
-
   totalSize -= unwrappedPair->size();
   if (totalSize < 0) {
     totalSize = 0;
   }
   unwrappedContainer->setQueueTotalSize(totalSize);
 
+  // Step 7: Return pair.[[value]].
   RootedValue val(cx, unwrappedPair->value());
   if (!cx->compartment()->wrap(cx, &val)) {
     return false;
   }
-
-  // Step 7: Return pair.[[value]].
   chunk.set(val);
   return true;
 }
 
 /**
  * Streams spec, 6.2.2. EnqueueValueWithSize ( container, value, size ) throws
  */
 static MOZ_MUST_USE bool EnqueueValueWithSize(
@@ -4160,19 +4168,16 @@ static MOZ_MUST_USE bool EnqueueValueWit
   unwrappedContainer->setQueueTotalSize(unwrappedContainer->queueTotalSize() +
                                         size);
 
   return true;
 }
 
 /**
  * Streams spec, 6.2.4. ResetQueue ( container ) nothrow
- *
- * Note: can operate on unwrapped container instances from another
- * compartment.
  */
 inline static MOZ_MUST_USE bool ResetQueue(
     JSContext* cx, Handle<ReadableStreamController*> unwrappedContainer) {
   // Step 1: Assert: container has [[queue]] and [[queueTotalSize]] internal
   //         slots (implicit).
   // Step 2: Set container.[[queue]] to a new empty List.
   if (!SetNewList(cx, unwrappedContainer, StreamController::Slot_Queue)) {
     return false;
@@ -4258,16 +4263,17 @@ static MOZ_MUST_USE bool CreateAlgorithm
 
   // Step 7: Return an algorithm which returns a promise resolved with
   //         undefined (implicit).
   return true;
 }
 
 /**
  * Streams spec, 6.3.2. InvokeOrNoop ( O, P, args )
+ * As it happens, all callers pass exactly one argument.
  */
 inline static MOZ_MUST_USE bool InvokeOrNoop(JSContext* cx, HandleValue O,
                                              HandlePropertyName P,
                                              HandleValue arg,
                                              MutableHandleValue rval) {
   cx->check(O, P, arg);
 
   // Step 1: Assert: P is a valid property key (omitted).
@@ -4677,22 +4683,26 @@ JS_PUBLIC_API bool JS::ReadableStreamUpd
     RootedValue chunk(cx, ObjectValue(*transferredView));
     if (!ReadableStreamFulfillReadOrReadIntoRequest(cx, unwrappedStream, chunk,
                                                     false)) {
       return false;
     }
 
     unwrappedController->setQueueTotalSize(availableData - bytesWritten);
   } else {
-    // Step b: Otherwise,
-    // Step i: Assert: ! IsReadableStreamLocked(stream) is false.
+    // Step 9: Otherwise, if ! ReadableStreamHasBYOBReader(stream) is true,
+    //         [...]
+    // (Omitted. BYOB readers are not implemented.)
+
+    // Step 10: Otherwise,
+    // Step a: Assert: ! IsReadableStreamLocked(stream) is false.
     MOZ_ASSERT(!unwrappedStream->locked());
 
-    // Step ii: Perform ! ReadableByteStreamControllerEnqueueChunkToQueue(
-    //              controller, transferredBuffer, byteOffset, byteLength).
+    // Step b: Perform ! ReadableByteStreamControllerEnqueueChunkToQueue(
+    //         controller, transferredBuffer, byteOffset, byteLength).
     // (Not needed for external underlying sources.)
   }
 
   return true;
 }
 
 JS_PUBLIC_API bool JS::ReadableStreamTee(JSContext* cx, HandleObject streamObj,
                                          MutableHandleObject branch1Obj,
@@ -4710,17 +4720,16 @@ JS_PUBLIC_API bool JS::ReadableStreamTee
   Rooted<ReadableStream*> branch2Stream(cx);
   if (!ReadableStreamTee(cx, unwrappedStream, false, &branch1Stream,
                          &branch2Stream)) {
     return false;
   }
 
   branch1Obj.set(branch1Stream);
   branch2Obj.set(branch2Stream);
-
   return true;
 }
 
 JS_PUBLIC_API bool JS::ReadableStreamGetDesiredSize(JSContext* cx,
                                                     JSObject* streamObj,
                                                     bool* hasValue,
                                                     double* value) {
   ReadableStream* unwrappedStream =