Bug 1503718 - Part 3: Use the `unwrapped` prefix. Covers spec sections 3.10 and 3.12. r=tcampbell
authorJason Orendorff <jorendorff@mozilla.com>
Fri, 16 Nov 2018 12:39:59 +0000
changeset 503186 1918d21eb212e46e671c7fdfd008406d4fee2ebb
parent 503185 c87bb95c2447c77beb835e7f2476fe1f066008c0
child 503187 0771df5c7ac5b20852b8d5060515c7e3b4ec9173
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)
reviewerstcampbell
bugs1503718
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 1503718 - Part 3: Use the `unwrapped` prefix. Covers spec sections 3.10 and 3.12. r=tcampbell Differential Revision: https://phabricator.services.mozilla.com/D11685
js/src/builtin/Stream.cpp
--- a/js/src/builtin/Stream.cpp
+++ b/js/src/builtin/Stream.cpp
@@ -3069,27 +3069,29 @@ ReadableStreamControllerGetDesiredSizeUn
 
 #if 0 // disable user-defined byte streams
 
 /**
  * Streams spec, 3.10.3 new ReadableByteStreamController ( stream, underlyingSource,
  *                                                         highWaterMark )
  * Steps 3 - 16.
  *
- * Note: can NOT operate on unwrapped ReadableStream instances from
- * another compartment: ReadableStream controllers must be created in the same
- * compartment as the stream.
+ * 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 ReadableByteStreamController*
-CreateReadableByteStreamController(JSContext* cx, Handle<ReadableStream*> stream,
+CreateReadableByteStreamController(JSContext* cx,
+                                   Handle<ReadableStream*> stream,
                                    HandleValue underlyingByteSource,
                                    HandleValue highWaterMarkVal)
 {
-    Rooted<ReadableByteStreamController*> controller(cx);
-    controller = NewBuiltinClassInstance<ReadableByteStreamController>(cx);
+    cx->check(stream, underlyingByteSource, highWaterMarkVal);
+
+    Rooted<ReadableByteStreamController*> controller(cx,
+        NewBuiltinClassInstance<ReadableByteStreamController>(cx));
     if (!controller) {
         return nullptr;
     }
 
     // Step 3: Set this.[[controlledReadableStream]] to stream.
     controller->setStream(stream);
 
     // Step 4: Set this.[[underlyingByteSource]] to underlyingByteSource.
@@ -3178,36 +3180,41 @@ CreateReadableByteStreamController(JSCon
         return nullptr;
     }
 
     return controller;
 }
 
 #endif  // user-defined byte streams
 
-// Streams spec, 3.10.3.
-// new ReadableByteStreamController ( stream, underlyingByteSource,
-//                                    highWaterMark )
+/**
+ * Streams spec, 3.10.3.
+ * new ReadableByteStreamController ( stream, underlyingByteSource,
+ *                                    highWaterMark )
+ */
 bool
 ReadableByteStreamController::constructor(JSContext* cx, unsigned argc, Value* vp)
 {
     // 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 the ReadableByteStreamConstructor that's specialized for
+ * handling external, embedding-provided, underlying sources.
+ */
 static MOZ_MUST_USE ReadableByteStreamController*
-CreateExternalReadableByteStreamController(JSContext* cx, Handle<ReadableStream*> stream,
+CreateExternalReadableByteStreamController(JSContext* cx,
+                                           Handle<ReadableStream*> stream,
                                            void* underlyingSource)
 {
-    Rooted<ReadableByteStreamController*> controller(cx);
-    controller = NewBuiltinClassInstance<ReadableByteStreamController>(cx);
+    Rooted<ReadableByteStreamController*> controller(cx,
+        NewBuiltinClassInstance<ReadableByteStreamController>(cx));
     if (!controller) {
         return nullptr;
     }
 
     // Step 3: Set this.[[controlledReadableStream]] to stream.
     controller->setStream(stream);
 
     // Step 4: Set this.[[underlyingByteSource]] to underlyingByteSource.
@@ -3310,378 +3317,359 @@ static const ClassOps ReadableByteStream
 CLASS_SPEC(ReadableByteStreamController, 3, SlotCount, ClassSpec::DontDefineConstructor,
            JSCLASS_BACKGROUND_FINALIZE, &ReadableByteStreamControllerClassOps);
 
 // Streams spec, 3.10.5.1. [[CancelSteps]] ()
 // Unified with 3.8.5.1 above.
 
 static MOZ_MUST_USE bool
 ReadableByteStreamControllerHandleQueueDrain(JSContext* cx,
-                                             Handle<ReadableStreamController*> controller);
+                                             Handle<ReadableStreamController*> unwrappedController);
 
 /**
  * Streams spec, 3.10.5.2. [[PullSteps]] ()
- *
- * Note: can operate on unwrapped instances from other compartments for
- * |controller|. Any instances created in the course of this
- * function's operation are created in the current cx compartment.
  */
 static MOZ_MUST_USE JSObject*
 ReadableByteStreamControllerPullSteps(JSContext* cx,
-                                      Handle<ReadableByteStreamController*> controller)
+                                      Handle<ReadableByteStreamController*> unwrappedController)
 {
     // Step 1: Let stream be this.[[controlledReadableStream]].
-    Rooted<ReadableStream*> stream(cx, controller->stream());
+    Rooted<ReadableStream*> unwrappedStream(cx, unwrappedController->stream());
 
     // Step 2: Assert: ! ReadableStreamHasDefaultReader(stream) is true.
 #ifdef DEBUG
     bool result;
-    if (!ReadableStreamHasDefaultReader(cx, stream, &result)) {
+    if (!ReadableStreamHasDefaultReader(cx, unwrappedStream, &result)) {
         return nullptr;
     }
     MOZ_ASSERT(result);
 #endif
 
     RootedValue val(cx);
     // Step 3: If this.[[queueTotalSize]] > 0,
-    double queueTotalSize = controller->queueTotalSize();
+    double queueTotalSize = unwrappedController->queueTotalSize();
     if (queueTotalSize > 0) {
         // Step 3.a: Assert: ! ReadableStreamGetNumReadRequests(_stream_) is 0.
-        MOZ_ASSERT(ReadableStreamGetNumReadRequests(stream) == 0);
+        MOZ_ASSERT(ReadableStreamGetNumReadRequests(unwrappedStream) == 0);
 
         RootedObject view(cx);
 
-        if (stream->mode() == JS::ReadableStreamMode::ExternalSource) {
-            void* underlyingSource = controller->underlyingSource().toPrivate();
+        if (unwrappedStream->mode() == JS::ReadableStreamMode::ExternalSource) {
+            void* underlyingSource = unwrappedController->underlyingSource().toPrivate();
 
             view = JS_NewUint8Array(cx, queueTotalSize);
             if (!view) {
                 return nullptr;
             }
 
             size_t bytesWritten;
             {
-                AutoRealm ar(cx, stream);
+                AutoRealm ar(cx, unwrappedStream);
                 JS::AutoSuppressGCAnalysis suppressGC(cx);
                 JS::AutoCheckCannotGC noGC;
                 bool dummy;
                 void* buffer = JS_GetArrayBufferViewData(view, &dummy, noGC);
 
                 auto cb = cx->runtime()->readableStreamWriteIntoReadRequestCallback;
                 MOZ_ASSERT(cb);
                 // TODO: use bytesWritten to correctly update the request's state.
-                cb(cx, stream, underlyingSource, stream->embeddingFlags(), buffer,
-                   queueTotalSize, &bytesWritten);
+                cb(cx, unwrappedStream, underlyingSource, unwrappedStream->embeddingFlags(),
+                   buffer, queueTotalSize, &bytesWritten);
             }
 
             queueTotalSize = queueTotalSize - bytesWritten;
         } else {
             // Step 3.b: Let entry be the first element of this.[[queue]].
             // Step 3.c: Remove entry from this.[[queue]], shifting all other elements
             //           downward (so that the second becomes the first, and so on).
-            RootedNativeObject queue(cx, controller->queue());
-            Rooted<ByteStreamChunk*> entry(cx);
-            entry = ToUnwrapped<ByteStreamChunk>(cx, ShiftFromList<JSObject>(cx, queue));
-            if (!entry) {
+            RootedNativeObject unwrappedQueue(cx, unwrappedController->queue());
+            Rooted<ByteStreamChunk*> unwrappedEntry(cx,
+                ToUnwrapped<ByteStreamChunk>(cx, ShiftFromList<JSObject>(cx, unwrappedQueue)));
+            if (!unwrappedEntry) {
                 return nullptr;
             }
 
-            queueTotalSize = queueTotalSize - entry->byteLength();
+            queueTotalSize = queueTotalSize - unwrappedEntry->byteLength();
 
             // Step 3.f: Let view be ! Construct(%Uint8Array%, « entry.[[buffer]],
             //                                   entry.[[byteOffset]], entry.[[byteLength]] »).
             // (reordered)
-            RootedObject buffer(cx, entry->buffer());
+            RootedObject buffer(cx, unwrappedEntry->buffer());
             if (!cx->compartment()->wrap(cx, &buffer)) {
                 return nullptr;
             }
 
-            uint32_t byteOffset = entry->byteOffset();
-            view = JS_NewUint8ArrayWithBuffer(cx, buffer, byteOffset, entry->byteLength());
+            uint32_t byteOffset = unwrappedEntry->byteOffset();
+            view = JS_NewUint8ArrayWithBuffer(cx, buffer, byteOffset, unwrappedEntry->byteLength());
             if (!view) {
                 return nullptr;
             }
         }
 
         // Step 3.d: Set this.[[queueTotalSize]] to
         //           this.[[queueTotalSize]] − entry.[[byteLength]].
         // (reordered)
-        controller->setQueueTotalSize(queueTotalSize);
+        unwrappedController->setQueueTotalSize(queueTotalSize);
 
         // Step 3.e: Perform ! ReadableByteStreamControllerHandleQueueDrain(this).
         // (reordered)
-        if (!ReadableByteStreamControllerHandleQueueDrain(cx, controller)) {
+        if (!ReadableByteStreamControllerHandleQueueDrain(cx, unwrappedController)) {
             return nullptr;
         }
 
         // Step 3.g: Return a promise resolved with ! CreateIterResultObject(view, false).
         val.setObject(*view);
         RootedObject iterResult(cx, CreateIterResultObject(cx, val, false));
         if (!iterResult) {
             return nullptr;
         }
         val.setObject(*iterResult);
 
         return PromiseObject::unforgeableResolve(cx, val);
     }
 
     // Step 4: Let autoAllocateChunkSize be this.[[autoAllocateChunkSize]].
-    val = controller->autoAllocateChunkSize();
+    val = unwrappedController->autoAllocateChunkSize();
 
     // Step 5: If autoAllocateChunkSize is not undefined,
     if (!val.isUndefined()) {
         double autoAllocateChunkSize = val.toNumber();
 
         // Step 5.a: Let buffer be Construct(%ArrayBuffer%, « autoAllocateChunkSize »).
-        RootedObject bufferObj(cx, JS_NewArrayBuffer(cx, autoAllocateChunkSize));
+        JSObject* bufferObj = JS_NewArrayBuffer(cx, autoAllocateChunkSize);
 
         // Step 5.b: If buffer is an abrupt completion,
         //           return a promise rejected with buffer.[[Value]].
         if (!bufferObj) {
             return PromiseRejectedWithPendingError(cx);
         }
 
         RootedArrayBufferObject buffer(cx, &bufferObj->as<ArrayBufferObject>());
 
         // Step 5.c: Let pullIntoDescriptor be Record {[[buffer]]: buffer.[[Value]],
         //                                             [[byteOffset]]: 0,
         //                                             [[byteLength]]: autoAllocateChunkSize,
         //                                             [[bytesFilled]]: 0, [[elementSize]]: 1,
         //                                             [[ctor]]: %Uint8Array%,
         //                                             [[readerType]]: `"default"`}.
-        RootedObject pullIntoDescriptor(cx);
-        pullIntoDescriptor = PullIntoDescriptor::create(cx, buffer, 0,
-                                                        autoAllocateChunkSize, 0, 1,
-                                                        nullptr,
-                                                        ReaderType_Default);
+        RootedObject pullIntoDescriptor(cx,
+            PullIntoDescriptor::create(cx, buffer, 0,
+                                       autoAllocateChunkSize, 0, 1,
+                                       nullptr,
+                                       ReaderType_Default));
         if (!pullIntoDescriptor) {
             return PromiseRejectedWithPendingError(cx);
         }
 
         // Step 5.d: Append pullIntoDescriptor as the last element of this.[[pendingPullIntos]].
         if (!AppendToListAtSlot(cx,
-                                controller,
+                                unwrappedController,
                                 ReadableByteStreamController::Slot_PendingPullIntos,
                                 pullIntoDescriptor))
         {
             return nullptr;
         }
     }
 
     // Step 6: Let promise be ! ReadableStreamAddReadRequest(stream).
-    RootedObject promise(cx, ReadableStreamAddReadOrReadIntoRequest(cx, stream));
+    RootedObject promise(cx, ReadableStreamAddReadOrReadIntoRequest(cx, unwrappedStream));
     if (!promise) {
         return nullptr;
     }
 
     // Step 7: Perform ! ReadableByteStreamControllerCallPullIfNeeded(this).
-    if (!ReadableStreamControllerCallPullIfNeeded(cx, controller)) {
+    if (!ReadableStreamControllerCallPullIfNeeded(cx, unwrappedController)) {
         return nullptr;
     }
 
     // Step 8: Return promise.
     return promise;
 }
 
 /**
  * Unified implementation of ReadableStream controllers' [[PullSteps]] internal
  * methods.
  * Streams spec, 3.8.5.2. [[PullSteps]] ()
  * and
  * Streams spec, 3.10.5.2. [[PullSteps]] ()
- *
- * Note: can operate on unwrapped ReadableStream controller instances from
- * another compartment.
  */
 static MOZ_MUST_USE JSObject*
-ReadableStreamControllerPullSteps(JSContext* cx, Handle<ReadableStreamController*> controller)
+ReadableStreamControllerPullSteps(JSContext* cx, Handle<ReadableStreamController*> unwrappedController)
 {
-    if (controller->is<ReadableStreamDefaultController>()) {
-        Rooted<ReadableStreamDefaultController*> defaultController(cx,
-            &controller->as<ReadableStreamDefaultController>());
-        return ReadableStreamDefaultControllerPullSteps(cx, defaultController);
-    }
-
-    Rooted<ReadableByteStreamController*> byteController(cx,
-        &controller->as<ReadableByteStreamController>());
-    return ReadableByteStreamControllerPullSteps(cx, byteController);
+    if (unwrappedController->is<ReadableStreamDefaultController>()) {
+        Rooted<ReadableStreamDefaultController*> unwrappedDefaultController(cx,
+            &unwrappedController->as<ReadableStreamDefaultController>());
+        return ReadableStreamDefaultControllerPullSteps(cx, unwrappedDefaultController);
+    }
+
+    Rooted<ReadableByteStreamController*> unwrappedByteController(cx,
+        &unwrappedController->as<ReadableByteStreamController>());
+    return ReadableByteStreamControllerPullSteps(cx, unwrappedByteController);
 }
 
 
 /*** 3.12. Readable stream BYOB controller abstract operations ***********************************/
 
 // Streams spec, 3.12.1. IsReadableStreamBYOBRequest ( x )
 // Implemented via is<ReadableStreamBYOBRequest>()
 
 // Streams spec, 3.12.2. IsReadableByteStreamController ( x )
 // Implemented via is<ReadableByteStreamController>()
 
 // Streams spec, 3.12.3. ReadableByteStreamControllerCallPullIfNeeded ( controller )
 // Unified with 3.9.2 above.
 
 static MOZ_MUST_USE bool
 ReadableByteStreamControllerInvalidateBYOBRequest(JSContext* cx,
-                                                  Handle<ReadableByteStreamController*> controller);
+                                                  Handle<ReadableByteStreamController*> unwrappedController);
 
 /**
  * Streams spec, 3.12.5. ReadableByteStreamControllerClearPendingPullIntos ( controller )
- *
- * Note: can operate on unwrapped instances from other compartments for
- * |controller|. The List created in step 2 is guaranteed to be in the same
- * compartment as the controller.
  */
 static MOZ_MUST_USE bool
 ReadableByteStreamControllerClearPendingPullIntos(JSContext* cx,
-                                                  Handle<ReadableByteStreamController*> controller)
+                                                  Handle<ReadableByteStreamController*> unwrappedController)
 {
     // Step 1: Perform ! ReadableByteStreamControllerInvalidateBYOBRequest(controller).
-    if (!ReadableByteStreamControllerInvalidateBYOBRequest(cx, controller)) {
+    if (!ReadableByteStreamControllerInvalidateBYOBRequest(cx, unwrappedController)) {
         return false;
     }
 
     // Step 2: Set controller.[[pendingPullIntos]] to a new empty List.
-    return SetNewList(cx, controller, ReadableByteStreamController::Slot_PendingPullIntos);
+    return SetNewList(cx, unwrappedController, ReadableByteStreamController::Slot_PendingPullIntos);
 }
 
 /**
  * Streams spec, 3.12.6. ReadableByteStreamControllerClose ( controller )
- *
- * Note: can operate on unwrapped ReadableByteStreamController instances from
- * another compartment.
  */
 static MOZ_MUST_USE bool
-ReadableByteStreamControllerClose(JSContext* cx, Handle<ReadableByteStreamController*> controller)
+ReadableByteStreamControllerClose(JSContext* cx,
+                                  Handle<ReadableByteStreamController*> unwrappedController)
 {
     // Step 1: Let stream be controller.[[controlledReadableStream]].
-    Rooted<ReadableStream*> stream(cx, controller->stream());
+    Rooted<ReadableStream*> unwrappedStream(cx, unwrappedController->stream());
 
     // Step 2: Assert: controller.[[closeRequested]] is false.
-    MOZ_ASSERT(!controller->closeRequested());
+    MOZ_ASSERT(!unwrappedController->closeRequested());
 
     // Step 3: Assert: stream.[[state]] is "readable".
-    MOZ_ASSERT(stream->readable());
+    MOZ_ASSERT(unwrappedStream->readable());
 
     // Step 4: If controller.[[queueTotalSize]] > 0,
-    if (controller->queueTotalSize() > 0) {
+    if (unwrappedController->queueTotalSize() > 0) {
         // Step a: Set controller.[[closeRequested]] to true.
-        controller->setCloseRequested();
-
-        // Step b: Return
+        unwrappedController->setCloseRequested();
+
+        // Step b: Return.
         return true;
     }
 
     // Step 5: If controller.[[pendingPullIntos]] is not empty,
-    RootedNativeObject pendingPullIntos(cx, controller->pendingPullIntos());
-    if (pendingPullIntos->getDenseInitializedLength() != 0) {
+    RootedNativeObject unwrappedPendingPullIntos(cx, unwrappedController->pendingPullIntos());
+    if (unwrappedPendingPullIntos->getDenseInitializedLength() != 0) {
         // Step a: Let firstPendingPullInto be the first element of
         //         controller.[[pendingPullIntos]].
-        Rooted<PullIntoDescriptor*> firstPendingPullInto(cx);
-        firstPendingPullInto = ToUnwrapped<PullIntoDescriptor>(cx,
-                                                               PeekList<JSObject>(pendingPullIntos));
-        if (!firstPendingPullInto) {
+        Rooted<PullIntoDescriptor*> unwrappedFirstPendingPullInto(cx,
+            ToUnwrapped<PullIntoDescriptor>(cx, PeekList<JSObject>(unwrappedPendingPullIntos)));
+        if (!unwrappedFirstPendingPullInto) {
             return false;
         }
 
         // Step b: If firstPendingPullInto.[[bytesFilled]] > 0,
-        if (firstPendingPullInto->bytesFilled() > 0) {
+        if (unwrappedFirstPendingPullInto->bytesFilled() > 0) {
             // Step i: Let e be a new TypeError exception.
             JS_ReportErrorNumberASCII(cx, GetErrorMessage, nullptr,
                                       JSMSG_READABLEBYTESTREAMCONTROLLER_CLOSE_PENDING_PULL);
             RootedValue e(cx);
             if (!cx->isExceptionPending() || !GetAndClearException(cx, &e)) {
                 // Uncatchable error. Die immediately without erroring the
                 // stream.
                 return false;
             }
 
             // Step ii: Perform ! ReadableByteStreamControllerError(controller, e).
-            if (!ReadableStreamControllerError(cx, controller, e)) {
+            if (!ReadableStreamControllerError(cx, unwrappedController, e)) {
                 return false;
             }
 
             // Step iii: Throw e.
             cx->setPendingException(e);
             return false;
         }
     }
 
     // Step 6: Perform ! ReadableStreamClose(stream).
-    return ReadableStreamCloseInternal(cx, stream);
+    return ReadableStreamCloseInternal(cx, unwrappedStream);
 }
 
 // Streams spec, 3.12.11. ReadableByteStreamControllerError ( controller, e )
 // Unified with 3.9.7 above.
 
 // Streams spec 3.12.14. ReadableByteStreamControllerGetDesiredSize ( controller )
 // Unified with 3.9.8 above.
 
 /**
  * Streams spec, 3.12.15. ReadableByteStreamControllerHandleQueueDrain ( controller )
- *
- * Note: can operate on unwrapped instances from other compartments for
- * |controller|.
  */
 static MOZ_MUST_USE bool
 ReadableByteStreamControllerHandleQueueDrain(JSContext* cx,
-                                             Handle<ReadableStreamController*> controller)
+                                             Handle<ReadableStreamController*> unwrappedController)
 {
-    MOZ_ASSERT(controller->is<ReadableByteStreamController>());
+    MOZ_ASSERT(unwrappedController->is<ReadableByteStreamController>());
 
     // Step 1: Assert: controller.[[controlledReadableStream]].[[state]] is "readable".
-    Rooted<ReadableStream*> stream(cx, controller->stream());
-    MOZ_ASSERT(stream->readable());
+    Rooted<ReadableStream*> unwrappedStream(cx, unwrappedController->stream());
+    MOZ_ASSERT(unwrappedStream->readable());
 
     // Step 2: If controller.[[queueTotalSize]] is 0 and
     //         controller.[[closeRequested]] is true,
-    if (controller->queueTotalSize() == 0 && controller->closeRequested()) {
+    if (unwrappedController->queueTotalSize() == 0 && unwrappedController->closeRequested()) {
         // Step a: Perform ! ReadableStreamClose(controller.[[controlledReadableStream]]).
-        return ReadableStreamCloseInternal(cx, stream);
+        return ReadableStreamCloseInternal(cx, unwrappedStream);
     }
 
     // Step 3: Otherwise,
     // Step a: Perform ! ReadableByteStreamControllerCallPullIfNeeded(controller).
-    return ReadableStreamControllerCallPullIfNeeded(cx, controller);
+    return ReadableStreamControllerCallPullIfNeeded(cx, unwrappedController);
 }
 
 enum BYOBRequestSlots {
     BYOBRequestSlot_Controller,
     BYOBRequestSlot_View,
     BYOBRequestSlotCount
 };
 
 /**
  * Streams spec 3.12.16. ReadableByteStreamControllerInvalidateBYOBRequest ( controller )
- *
- * Note: can operate on unwrapped instances from other compartments for
- * |controller|.
  */
 static MOZ_MUST_USE bool
 ReadableByteStreamControllerInvalidateBYOBRequest(JSContext* cx,
-                                                  Handle<ReadableByteStreamController*> controller)
+                                                  Handle<ReadableByteStreamController*> unwrappedController)
 {
     // Step 1: If controller.[[byobRequest]] is undefined, return.
-    RootedValue byobRequestVal(cx, controller->byobRequest());
-    if (byobRequestVal.isUndefined()) {
+    RootedValue unwrappedBYOBRequestVal(cx, unwrappedController->byobRequest());
+    if (unwrappedBYOBRequestVal.isUndefined()) {
         return true;
     }
 
-    RootedNativeObject byobRequest(cx, ToUnwrapped<NativeObject>(cx, byobRequestVal));
-    if (!byobRequest) {
+    RootedNativeObject unwrappedBYOBRequest(cx,
+        ToUnwrapped<NativeObject>(cx, unwrappedBYOBRequestVal));
+    if (!unwrappedBYOBRequest) {
         return false;
     }
 
     // Step 2: Set controller.[[byobRequest]].[[associatedReadableByteStreamController]]
     //         to undefined.
-    byobRequest->setFixedSlot(BYOBRequestSlot_Controller, UndefinedValue());
+    unwrappedBYOBRequest->setFixedSlot(BYOBRequestSlot_Controller, UndefinedValue());
 
     // Step 3: Set controller.[[byobRequest]].[[view]] to undefined.
-    byobRequest->setFixedSlot(BYOBRequestSlot_View, UndefinedValue());
+    unwrappedBYOBRequest->setFixedSlot(BYOBRequestSlot_View, UndefinedValue());
 
     // Step 4: Set controller.[[byobRequest]] to undefined.
-    controller->clearBYOBRequest();
+    unwrappedController->clearBYOBRequest();
 
     return true;
 }
 
 // Streams spec, 3.12.25. ReadableByteStreamControllerShouldCallPull ( controller )
 // Unified with 3.9.3 above.
 
 
@@ -4353,16 +4341,19 @@ JS::ReadableStreamUpdateDataAvailableFro
     if (hasDefaultReader) {
         // Step b: Otherwise,
         // Step i: Assert: controller.[[queue]] is empty.
         MOZ_ASSERT(oldAvailableData == 0);
 
         // Step ii: Let transferredView be
         //          ! Construct(%Uint8Array%, transferredBuffer, byteOffset, byteLength).
         JSObject* viewObj = JS_NewUint8Array(cx, availableData);
+        if (!viewObj) {
+            return false;
+        }
         Rooted<ArrayBufferViewObject*> transferredView(cx, &viewObj->as<ArrayBufferViewObject>());
         if (!transferredView) {
             return false;
         }
 
         void* underlyingSource = controller->underlyingSource().toPrivate();
 
         size_t bytesWritten;