Bug 1507952 - Part 4: Update SetUpReadableStreamDefaultController to match the standard. r=arai
authorJason Orendorff <jorendorff@mozilla.com>
Thu, 22 Nov 2018 13:42:31 +0000
changeset 504206 51f31e8ac73a27c2a1e71de4e546f2069a243bc7
parent 504205 7687d5a601cb074ba03e97af24ad93d0176867ca
child 504207 f02a0ed71bcabad55dd6ea1a9eab39e58e82fc2d
push id10290
push userffxbld-merge
push dateMon, 03 Dec 2018 16:23:23 +0000
treeherdermozilla-beta@700bed2445e6 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersarai
bugs1507952
milestone65.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 1507952 - Part 4: Update SetUpReadableStreamDefaultController to match the standard. r=arai Differential Revision: https://phabricator.services.mozilla.com/D12458
js/src/builtin/Stream.cpp
--- a/js/src/builtin/Stream.cpp
+++ b/js/src/builtin/Stream.cpp
@@ -483,22 +483,22 @@ const Class cls::protoClass_ = { \
     JSCLASS_HAS_CACHED_PROTO(JSProto_##cls), \
     JS_NULL_CLASS_OPS, \
     &cls::classSpec_ \
 };
 
 
 /*** 3.2. Class ReadableStream **********************************************/
 
-static MOZ_MUST_USE ReadableStreamDefaultController*
+static MOZ_MUST_USE bool
 SetUpReadableStreamDefaultController(JSContext* cx,
                                      Handle<ReadableStream*> stream,
                                      HandleValue underlyingSource,
-                                     HandleValue size,
-                                     double highWaterMarkVal);
+                                     double highWaterMarkVal,
+                                     HandleValue size);
 
 /**
  * Streams spec, 3.2.3., steps 1-4, 8.
  */
 ReadableStream*
 ReadableStream::createDefaultStream(JSContext* cx, HandleValue underlyingSource,
                                     HandleValue size, double highWaterMark,
                                     HandleObject proto /* = nullptr */)
@@ -512,23 +512,19 @@ ReadableStream::createDefaultStream(JSCo
     if (!stream) {
         return nullptr;
     }
 
     // Step 8.b: Set this.[[readableStreamController]] to
     //           ? Construct(ReadableStreamDefaultController,
     //                       « this, underlyingSource, size,
     //                         highWaterMark »).
-    ReadableStreamDefaultController* controller =
-        SetUpReadableStreamDefaultController(cx, stream, underlyingSource, size,
-                                             highWaterMark);
-    if (!controller) {
+    if (!SetUpReadableStreamDefaultController(cx, stream, underlyingSource, highWaterMark, size)) {
         return nullptr;
     }
-    stream->setController(controller);
     return stream;
 }
 
 static MOZ_MUST_USE ReadableByteStreamController*
 CreateExternalReadableByteStreamController(JSContext* cx, Handle<ReadableStream*> stream,
                                            void* underlyingSource);
 
 ReadableStream*
@@ -3071,91 +3067,108 @@ ReadableStreamControllerGetDesiredSizeUn
 }
 
 /**
  * Streams spec, 3.9.11.
  *      SetUpReadableStreamDefaultController(stream, controller,
  *          startAlgorithm, pullAlgorithm, cancelAlgorithm, highWaterMark,
  *          sizeAlgorithm )
  *
+ * The standard algorithm takes a `controller` argument which must be a new,
+ * blank object. This implementation creates a new controller instead.
+ *
+ * The standard algorithm takes startAlgorithm, pullAlgorithm, and
+ * cancelAlgorithm as separate arguments. We will do the same, but for now all
+ * of them are passed as a single underlyingSource argument--with a few
+ * user-visible differences in behavior (bug 1507943).
+ *
  * Note: All arguments must be same-compartment with cx. ReadableStream
  * controllers are always created in the same compartment as the stream.
  */
-static MOZ_MUST_USE ReadableStreamDefaultController*
+static MOZ_MUST_USE bool
 SetUpReadableStreamDefaultController(JSContext* cx,
                                      Handle<ReadableStream*> stream,
                                      HandleValue underlyingSource,
-                                     HandleValue size,
-                                     double highWaterMark)
+                                     double highWaterMark,
+                                     HandleValue size)
 {
     cx->check(stream, underlyingSource, size);
     MOZ_ASSERT(highWaterMark >= 0);
     MOZ_ASSERT(size.isUndefined() || IsCallable(size));
 
+    // Done elsewhere in the standard: Create the new controller.
     Rooted<ReadableStreamDefaultController*> controller(cx,
         NewBuiltinClassInstance<ReadableStreamDefaultController>(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: Set controller.[[controlledReadableStream]] to stream.
     controller->setStream(stream);
 
-    // Step 4: Set this.[[underlyingSource]] to underlyingSource.
-    controller->setUnderlyingSource(underlyingSource);
-
-    // Step 5: Perform ! ResetQueue(this).
+    // Step 3: Set controller.[[queue]] and controller.[[queueTotalSize]] to
+    //         undefined (implicit), then perform ! ResetQueue(controller).
     if (!ResetQueue(cx, controller)) {
-        return nullptr;
-    }
-
-    // Step 6: Set this.[[started]], this.[[closeRequested]], this.[[pullAgain]],
-    //         and this.[[pulling]] to false.
+        return false;
+    }
+
+    // Step 4: Set controller.[[started]], controller.[[closeRequested]],
+    //         controller.[[pullAgain]], and controller.[[pulling]] to false.
     controller->setFlags(0);
 
-    // Step 7: Let normalizedStrategy be
-    //         ? ValidateAndNormalizeQueuingStrategy(size, highWaterMark)
-    //         (implicit).
-
-    // Step 8: Set this.[[strategySize]] to normalizedStrategy.[[size]] and
-    //         this.[[strategyHWM]] to normalizedStrategy.[[highWaterMark]].
+    // Step 5: Set controller.[[strategySizeAlgorithm]] to sizeAlgorithm
+    //         and controller.[[strategyHWM]] to highWaterMark.
     controller->setStrategySize(size);
     controller->setStrategyHWM(highWaterMark);
 
-    // Step 9: Let controller be this (implicit).
-
-    // Step 10: Let startResult be
-    //          ? InvokeOrNoop(underlyingSource, "start", « this »).
+    // Step 6: Set controller.[[pullAlgorithm]] to pullAlgorithm.
+    // Step 7: Set controller.[[cancelAlgorithm]] to cancelAlgorithm.
+    //
+    // For the moment, these algorithms are represented using the
+    // underlyingSource (bug 1507943). For example, when the underlying source
+    // is a TeeState, we use the ReadableStreamTee algorithms for pulling and
+    // canceling.
+    controller->setUnderlyingSource(underlyingSource);
+
+    // Step 8: Set stream.[[readableStreamController]] to controller.
+    stream->setController(controller);
+
+    // Step 9: Let startResult be the result of performing startAlgorithm.
     RootedValue startResult(cx);
     RootedValue controllerVal(cx, ObjectValue(*controller));
     if (!InvokeOrNoop(cx, underlyingSource, cx->names().start, controllerVal, &startResult)) {
-        return nullptr;
-    }
-
-    // Step 11: Let startPromise be a promise resolved with startResult:
+        return false;
+    }
+
+    // Step 10: Let startPromise be a promise resolved with startResult.
     RootedObject startPromise(cx, PromiseObject::unforgeableResolve(cx, startResult));
     if (!startPromise) {
-        return nullptr;
-    }
-
+        return false;
+    }
+
+    // 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 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;
 }
 
 
 /*** 3.10. Class ReadableByteStreamController *******************************/
 
 #if 0 // disable user-defined byte streams
 
 /**