From 76f69afc0373c3d620329d49218a7bea0a988193 Mon Sep 17 00:00:00 2001 From: Andrea Marchesini Date: Thu, 10 Aug 2017 18:04:56 -0700 Subject: [PATCH] Bug 1128959 - Implement the WHATWG Streams spec - part 15 - setting the correct global when ReadableStream.getReader() is called, r=bz --- dom/fetch/Fetch.cpp | 4 ++ dom/fetch/FetchStreamReader.cpp | 16 +++---- .../mochitest/fetch/common_readableStreams.js | 44 +++++++++++++++++++ .../mochitest/fetch/test_readableStreams.html | 4 ++ 4 files changed, 58 insertions(+), 10 deletions(-) diff --git a/dom/fetch/Fetch.cpp b/dom/fetch/Fetch.cpp index fcfd4e9989c7..ace8308eef0d 100644 --- a/dom/fetch/Fetch.cpp +++ b/dom/fetch/Fetch.cpp @@ -1158,6 +1158,10 @@ FetchBody::LockStream(JSContext* aCx, JS::HandleObject aStream, ErrorResult& aRv) { + MOZ_ASSERT(JS::ReadableStreamGetMode(aStream) == + JS::ReadableStreamMode::ExternalSource); + + // This is native stream, creating a reader will not execute any JS code. JS::Rooted reader(aCx, JS::ReadableStreamGetReader(aCx, aStream, JS::ReadableStreamReaderMode::Default)); diff --git a/dom/fetch/FetchStreamReader.cpp b/dom/fetch/FetchStreamReader.cpp index 136912bcf57b..f6195d5942f1 100644 --- a/dom/fetch/FetchStreamReader.cpp +++ b/dom/fetch/FetchStreamReader.cpp @@ -170,17 +170,13 @@ FetchStreamReader::OnOutputStreamReady(nsIAsyncOutputStream* aStream) return WriteBuffer(); } - AutoJSAPI jsapi; - if (NS_WARN_IF(!jsapi.Init(mGlobal))) { - CloseAndRelease(NS_ERROR_DOM_INVALID_STATE_ERR); - return NS_ERROR_FAILURE; - } + // TODO: We need to verify this is the correct global per the spec. + // See bug 1385890. + AutoEntryScript aes(mGlobal, "ReadableStreamReader.read", !mWorkerHolder); - JSContext* cx = jsapi.cx(); - - JS::Rooted reader(cx, mReader); - JS::Rooted promise(cx, - JS::ReadableStreamDefaultReaderRead(cx, + JS::Rooted reader(aes.cx(), mReader); + JS::Rooted promise(aes.cx(), + JS::ReadableStreamDefaultReaderRead(aes.cx(), reader)); if (NS_WARN_IF(!promise)) { // Let's close the stream. diff --git a/dom/tests/mochitest/fetch/common_readableStreams.js b/dom/tests/mochitest/fetch/common_readableStreams.js index df3199183ca6..d75d0a548b74 100644 --- a/dom/tests/mochitest/fetch/common_readableStreams.js +++ b/dom/tests/mochitest/fetch/common_readableStreams.js @@ -1,6 +1,7 @@ const SAME_COMPARTMENT = "same-compartment"; const IFRAME_COMPARTMENT = "iframe-compartment"; const BIG_BUFFER_SIZE = 1000000; +const ITER_MAX = 10; function makeBuffer(size) { let buffer = new Uint8Array(size); @@ -269,6 +270,49 @@ async function test_codeExecution_continue(r, that) { that.next(); }; +async function test_global(compartment) { + info("test_global: " + compartment); + + self.foo = 42; + self.iter = ITER_MAX; + + let r = new Response(new ReadableStream({ + start(c) { + self.controller = c; + }, + pull() { + if (!("iter" in self) || self.iter < 0 || self.iter > ITER_MAX) { + throw "Something bad is happening here!" + } + + let buffer = new Uint8Array(1); + buffer.fill(self.foo); + self.controller.enqueue(buffer); + + if (--self.iter == 0) { + controller.close(); + } + } + })); + + apply_compartment(compartment, + { func: "test_global_continue", + args: r }); +} + +async function test_global_continue(r, that) { + let a = await r.arrayBuffer(); + + that.is(Object.getPrototypeOf(a), that.ArrayBuffer.prototype, "Body is an array buffer"); + that.is(a.byteLength, ITER_MAX, "Body length is correct"); + + for (let i = 0; i < ITER_MAX; ++i) { + that.is(new Uint8Array(a)[i], 42, "Byte " + i + " is correct"); + } + + that.next(); +}; + function workify(func) { info("Workifing " + func); diff --git a/dom/tests/mochitest/fetch/test_readableStreams.html b/dom/tests/mochitest/fetch/test_readableStreams.html index ef8b104ee0da..7bcede94897a 100644 --- a/dom/tests/mochitest/fetch/test_readableStreams.html +++ b/dom/tests/mochitest/fetch/test_readableStreams.html @@ -48,6 +48,10 @@ let tests = [ function() { test_codeExecution(SAME_COMPARTMENT); }, function() { test_codeExecution(IFRAME_COMPARTMENT); }, + + function() { test_global(SAME_COMPARTMENT); }, + function() { test_global(IFRAME_COMPARTMENT); }, + function() { workify('test_global'); }, ]; function next() {