Bug 1504464 - Part 3: Update CreateExternalReadableByteStreamController to the current standard. r=jwalden
authorJason Orendorff <jorendorff@mozilla.com>
Mon, 14 Jan 2019 20:31:55 +0000
changeset 510917 0030c59cdea424b2f7a4dd77a83b9ba5d4b71dd4
parent 510916 d087b9c8c3891aac295ca973277ffd37e7fe2daa
child 510918 d35260c2032c61c08e1e9af2f5f9fda142097de8
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 3: Update CreateExternalReadableByteStreamController to the current standard. r=jwalden Differential Revision: https://phabricator.services.mozilla.com/D14498
js/src/builtin/Stream.cpp
js/src/builtin/Stream.h
--- a/js/src/builtin/Stream.cpp
+++ b/js/src/builtin/Stream.cpp
@@ -463,52 +463,32 @@ const Class TeeState::class_ = {"TeeStat
                              classOps, &cls::classSpec_};                   \
                                                                             \
   const Class cls::protoClass_ = {"object",                                 \
                                   JSCLASS_HAS_CACHED_PROTO(JSProto_##cls),  \
                                   JS_NULL_CLASS_OPS, &cls::classSpec_};
 
 /*** 3.2. Class ReadableStream **********************************************/
 
-/**
- * Characterizes the family of algorithms, (startAlgorithm, pullAlgorithm,
- * cancelAlgorithm), associated with a readable stream.
- *
- * See the comment on SetUpReadableStreamDefaultController().
- */
-enum class SourceAlgorithms {
-  Script,
-  Tee,
-};
-
-static MOZ_MUST_USE bool SetUpReadableStreamDefaultController(
-    JSContext* cx, Handle<ReadableStream*> stream, SourceAlgorithms algorithms,
-    HandleValue underlyingSource, HandleValue pullMethod,
-    HandleValue cancelMethod, double highWaterMark, HandleValue size);
-
-static MOZ_MUST_USE ReadableByteStreamController*
-CreateExternalReadableByteStreamController(
+static MOZ_MUST_USE bool SetUpExternalReadableByteStreamController(
     JSContext* cx, Handle<ReadableStream*> stream,
     JS::ReadableStreamUnderlyingSource* source);
 
 ReadableStream* ReadableStream::createExternalSourceStream(
     JSContext* cx, JS::ReadableStreamUnderlyingSource* source,
     HandleObject proto /* = nullptr */) {
   Rooted<ReadableStream*> stream(cx, create(cx, proto));
   if (!stream) {
     return nullptr;
   }
 
-  Rooted<ReadableStreamController*> controller(cx);
-  controller = CreateExternalReadableByteStreamController(cx, stream, source);
-  if (!controller) {
+  if (!SetUpExternalReadableByteStreamController(cx, stream, source)) {
     return nullptr;
   }
 
-  stream->setController(controller);
   return stream;
 }
 
 static MOZ_MUST_USE bool MakeSizeAlgorithmFromSizeFunction(JSContext* cx,
                                                            HandleValue size);
 
 static MOZ_MUST_USE bool ValidateAndNormalizeHighWaterMark(
     JSContext* cx, HandleValue highWaterMarkVal, double* highWaterMark);
@@ -818,16 +798,32 @@ CLASS_SPEC(ReadableStream, 0, SlotCount,
 
 // Streams spec, 3.3.1. AcquireReadableStreamBYOBReader ( stream )
 // Always inlined.
 
 // Streams spec, 3.3.2. AcquireReadableStreamDefaultReader ( stream )
 // Always inlined. See CreateReadableStreamDefaultReader.
 
 /**
+ * Characterizes the family of algorithms, (startAlgorithm, pullAlgorithm,
+ * cancelAlgorithm), associated with a readable stream.
+ *
+ * See the comment on SetUpReadableStreamDefaultController().
+ */
+enum class SourceAlgorithms {
+  Script,
+  Tee,
+};
+
+static MOZ_MUST_USE bool SetUpReadableStreamDefaultController(
+    JSContext* cx, Handle<ReadableStream*> stream, SourceAlgorithms algorithms,
+    HandleValue underlyingSource, HandleValue pullMethod,
+    HandleValue cancelMethod, double highWaterMark, HandleValue size);
+
+/**
  * Streams spec, 3.3.3. CreateReadableStream (
  *                          startAlgorithm, pullAlgorithm, cancelAlgorithm
  *                          [, highWaterMark [, sizeAlgorithm ] ] )
  *
  * The start/pull/cancelAlgorithm arguments are represented instead as four
  * arguments: sourceAlgorithms, underlyingSource, pullMethod, cancelMethod.
  * See the comment on SetUpReadableStreamDefaultController.
  */
@@ -3422,89 +3418,102 @@ bool ReadableByteStreamController::const
                             "ReadableByteStreamController");
   return false;
 }
 
 /**
  * Version of the ReadableByteStreamConstructor that's specialized for
  * handling external, embedding-provided, underlying sources.
  */
-static MOZ_MUST_USE ReadableByteStreamController*
-CreateExternalReadableByteStreamController(
+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) {
-    return nullptr;
-  }
-
-  // Step 3: Set this.[[controlledReadableStream]] to stream.
+    return false;
+  }
+
+  // Step 1: Assert: stream.[[readableStreamController]] is undefined.
+  MOZ_ASSERT(!stream->hasController());
+
+  // Step 2: If autoAllocateChunkSize is not undefined, [...]
+  // (It's treated as undefined.)
+
+  // Step 3: Set controller.[[controlledReadableByteStream]] to stream.
   controller->setStream(stream);
 
-  // Step 4: Set this.[[underlyingByteSource]] to underlyingByteSource.
-  controller->setExternalSource(source);
-
-  // Step 5: Set this.[[pullAgain]] and this.[[pulling]] to false (implicit).
+  // Step 4: Set controller.[[pullAgain]] and controller.[[pulling]] to false.
+  controller->setFlags(0);
   MOZ_ASSERT(!controller->pullAgain());
   MOZ_ASSERT(!controller->pulling());
 
-  // Step 6: Perform ! ReadableByteStreamControllerClearPendingPullIntos(this).
-  // Omitted.
-
-  // Step 7: Perform ! ResetQueue(this).
+  // Step 5: Perform
+  //         ! ReadableByteStreamControllerClearPendingPullIntos(controller).
+  // Omitted. This step is apparently redundant; see
+  // <https://github.com/whatwg/streams/issues/975>.
+
+  // Step 6: Perform ! ResetQueue(this).
   controller->setQueueTotalSize(0);
 
-  // Step 8: Set this.[[started]] and this.[[closeRequested]] to false.
-  // Step 9: Set this.[[strategyHWM]] to
+  // Step 7: Set controller.[[closeRequested]] and controller.[[started]] to
+  //         false (implicit).
+  MOZ_ASSERT(!controller->closeRequested());
+  MOZ_ASSERT(!controller->started());
+
+  // Step 8: Set controller.[[strategyHWM]] to
   //         ? ValidateAndNormalizeHighWaterMark(highWaterMark).
   controller->setStrategyHWM(0);
 
-  // Step 10: Let autoAllocateChunkSize be
-  //          ? GetV(underlyingByteSource, "autoAllocateChunkSize").
-  // Step 11: If autoAllocateChunkSize is not undefined,
-  // Step 12: Set this.[[autoAllocateChunkSize]] to autoAllocateChunkSize.
-  // Omitted.
-
-  // Step 13: Set this.[[pendingPullIntos]] to a new empty List.
+  // Step 9: Set controller.[[pullAlgorithm]] to pullAlgorithm.
+  // Step 10: Set controller.[[cancelAlgorithm]] to cancelAlgorithm.
+  // (These algorithms are given by source's virtual methods.)
+  controller->setExternalSource(source);
+
+  // Step 11: Set controller.[[autoAllocateChunkSize]] to
+  //          autoAllocateChunkSize (implicit).
+  MOZ_ASSERT(controller->autoAllocateChunkSize().isUndefined());
+
+  // Step 12: Set this.[[pendingPullIntos]] to a new empty List.
   if (!SetNewList(cx, controller,
                   ReadableByteStreamController::Slot_PendingPullIntos)) {
-    return nullptr;
-  }
-
-  // Step 14: Let controller be this (implicit).
-  // Step 15: Let startResult be
-  //          ? InvokeOrNoop(underlyingSource, "start", « this »).
-  // Omitted.
-
-  // Step 16: Let startPromise be a promise resolved with startResult:
+    return false;
+  }
+
+  // Step 13: Set stream.[[readableStreamController]] to controller.
+  stream->setController(controller);
+
+  // Step 14: Let startResult be the result of performing startAlgorithm.
+  // (For external sources, this algorithm does nothing and returns undefined.)
+  // Step 15: Let startPromise be a promise resolved with startResult.
   RootedObject startPromise(
       cx, PromiseObject::unforgeableResolve(cx, UndefinedHandleValue));
   if (!startPromise) {
-    return nullptr;
-  }
-
+    return false;
+  }
+
+  // Step 16: Upon fulfillment of startPromise, [...]
+  // Step 17: Upon rejection of startPromise with reason r, [...]
   RootedObject onStartFulfilled(
       cx, NewHandler(cx, ControllerStartHandler, controller));
   if (!onStartFulfilled) {
-    return nullptr;
-  }
-
+    return false;
+  }
   RootedObject onStartRejected(
       cx, NewHandler(cx, ControllerStartFailedHandler, controller));
   if (!onStartRejected) {
-    return nullptr;
-  }
-
+    return false;
+  }
   if (!JS::AddPromiseReactions(cx, startPromise, onStartFulfilled,
                                onStartRejected)) {
-    return nullptr;
-  }
-
-  return controller;
+    return false;
+  }
+
+  return true;
 }
 
 static const JSPropertySpec ReadableByteStreamController_properties[] = {
     JS_PS_END};
 
 static const JSFunctionSpec ReadableByteStreamController_methods[] = {
     JS_FS_END};
 
--- a/js/src/builtin/Stream.h
+++ b/js/src/builtin/Stream.h
@@ -308,19 +308,18 @@ class ReadableStreamController : public 
     static_assert(alignof(JS::ReadableStreamUnderlyingSource) >= 2,
                   "External underling sources are stored as PrivateValues, "
                   "so they must have even addresses");
     MOZ_ASSERT(hasExternalSource());
     return static_cast<JS::ReadableStreamUnderlyingSource*>(
         underlyingSource().toPrivate());
   }
   void setExternalSource(JS::ReadableStreamUnderlyingSource* underlyingSource) {
-    MOZ_ASSERT(getFixedSlot(Slot_Flags).isUndefined());
     setUnderlyingSource(JS::PrivateValue(underlyingSource));
-    setFlags(Flag_ExternalSource);
+    addFlags(Flag_ExternalSource);
   }
   double strategyHWM() const {
     return getFixedSlot(Slot_StrategyHWM).toNumber();
   }
   void setStrategyHWM(double highWaterMark) {
     setFixedSlot(Slot_StrategyHWM, NumberValue(highWaterMark));
   }
   uint32_t flags() const { return getFixedSlot(Slot_Flags).toInt32(); }