Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fetch request body as ReadableStream #628

Merged
merged 13 commits into from
Nov 17, 2021
7 changes: 4 additions & 3 deletions api-reports/2_12.txt
Original file line number Diff line number Diff line change
Expand Up @@ -15856,16 +15856,17 @@ ReadableStream[JT] def tee(): js.Array[_ <: ReadableStream[T]]
ReadableStream[SO] def apply[T](underlyingSource: js.UndefOr[ReadableStreamUnderlyingSource[T]]?, queuingStrategy: js.UndefOr[QueuingStrategy[T]]?): ReadableStream[T]
ReadableStreamController[JC] def close(): Unit
ReadableStreamController[JC] def desiredSize: Int
ReadableStreamController[JC] def enqueue(chunk: T): js.UndefOr[Int]
ReadableStreamController[JC] def enqueue(): Unit
ReadableStreamController[JC] def enqueue(chunk: T): Unit
ReadableStreamController[JC] def error(e: Any): Unit
ReadableStreamReader[JC] def cancel(): js.Promise[Unit]
ReadableStreamReader[JC] def cancel[U](reason: U): js.Promise[U]
ReadableStreamReader[JC] def cancel[U](reason: U): js.Promise[Unit]
ReadableStreamReader[JC] def closed: js.Promise[ReadableStreamReader[T]]
ReadableStreamReader[JC] def read(): js.Promise[Chunk[T]]
ReadableStreamReader[JC] def releaseLock(): Unit
ReadableStreamType[JT]
ReadableStreamType[SO] val bytes: ReadableStreamType
ReadableStreamUnderlyingSource[JT] var autoAllocateChunkSize: js.UndefOr[Double]
ReadableStreamUnderlyingSource[JT] var autoAllocateChunkSize: js.UndefOr[Int]
ReadableStreamUnderlyingSource[JT] var cancel: js.UndefOr[js.Function1[js.Any, js.UndefOr[js.Promise[Unit]]]]
ReadableStreamUnderlyingSource[JT] var pull: js.UndefOr[js.Function1[ReadableStreamController[T], js.UndefOr[js.Promise[Unit]]]]
ReadableStreamUnderlyingSource[JT] var start: js.UndefOr[js.Function1[ReadableStreamController[T], js.UndefOr[js.Promise[Unit]]]]
Expand Down
7 changes: 4 additions & 3 deletions api-reports/2_13.txt
Original file line number Diff line number Diff line change
Expand Up @@ -15856,16 +15856,17 @@ ReadableStream[JT] def tee(): js.Array[_ <: ReadableStream[T]]
ReadableStream[SO] def apply[T](underlyingSource: js.UndefOr[ReadableStreamUnderlyingSource[T]]?, queuingStrategy: js.UndefOr[QueuingStrategy[T]]?): ReadableStream[T]
ReadableStreamController[JC] def close(): Unit
ReadableStreamController[JC] def desiredSize: Int
ReadableStreamController[JC] def enqueue(chunk: T): js.UndefOr[Int]
ReadableStreamController[JC] def enqueue(): Unit
ReadableStreamController[JC] def enqueue(chunk: T): Unit
ReadableStreamController[JC] def error(e: Any): Unit
ReadableStreamReader[JC] def cancel(): js.Promise[Unit]
ReadableStreamReader[JC] def cancel[U](reason: U): js.Promise[U]
ReadableStreamReader[JC] def cancel[U](reason: U): js.Promise[Unit]
ReadableStreamReader[JC] def closed: js.Promise[ReadableStreamReader[T]]
ReadableStreamReader[JC] def read(): js.Promise[Chunk[T]]
ReadableStreamReader[JC] def releaseLock(): Unit
ReadableStreamType[JT]
ReadableStreamType[SO] val bytes: ReadableStreamType
ReadableStreamUnderlyingSource[JT] var autoAllocateChunkSize: js.UndefOr[Double]
ReadableStreamUnderlyingSource[JT] var autoAllocateChunkSize: js.UndefOr[Int]
ReadableStreamUnderlyingSource[JT] var cancel: js.UndefOr[js.Function1[js.Any, js.UndefOr[js.Promise[Unit]]]]
ReadableStreamUnderlyingSource[JT] var pull: js.UndefOr[js.Function1[ReadableStreamController[T], js.UndefOr[js.Promise[Unit]]]]
ReadableStreamUnderlyingSource[JT] var start: js.UndefOr[js.Function1[ReadableStreamController[T], js.UndefOr[js.Promise[Unit]]]]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,8 @@ class ReadableStreamController[-T] private[this] () extends js.Object {
* @return
* seems like its an undefOr[Int] of the size
*/
def enqueue(chunk: T): js.UndefOr[Int] = js.native
def enqueue(chunk: T): Unit = js.native
def enqueue(): Unit = js.native

/** The error method will error the readable stream, making all future interactions with it fail with the given error
* e.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ class ReadableStreamReader[+T](stream: ReadableStream[T]) extends js.Object {
* If the reader is active, the cancel method behaves the same as that for the associated stream. When done, it
* automatically releases the lock.
*/
def cancel[U](reason: U): js.Promise[U] = js.native
def cancel[U](reason: U): js.Promise[Unit] = js.native
ptrdom marked this conversation as resolved.
Show resolved Hide resolved
def cancel(): js.Promise[Unit] = js.native

/** See [[https://streams.spec.whatwg.org/#reader-read 3.4.4.3. read()]] of whatwg Stream spec.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,5 +53,5 @@ trait ReadableStreamUnderlyingSource[T] extends js.Object {
* Can be set to a positive integer to cause the implementation to automatically allocate buffers for the underlying
* source code to write into.
*/
var autoAllocateChunkSize: js.UndefOr[Double] = js.undefined
var autoAllocateChunkSize: js.UndefOr[Int] = js.undefined
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,32 @@ import org.junit.Test
import org.scalajs.dom.QueuingStrategy
import org.scalajs.dom.ReadableStream
import org.scalajs.dom.ReadableStreamController
import org.scalajs.dom.ReadableStreamReader
import org.scalajs.dom.ReadableStreamUnderlyingSource
import org.scalajs.dom.tests.shared.AsyncTesting.AsyncResult
import org.scalajs.dom.tests.shared.AsyncTesting._
import org.scalajs.dom.tests.shared.AsyncTesting.async

import scala.concurrent.Future
import scala.concurrent.Promise
import scala.scalajs.js
import scala.scalajs.js.Thenable.Implicits._
import scala.util.Try

trait BrowserTests {

def read[T](reader: ReadableStreamReader[T])(tunas: Seq[T]): Future[Seq[T]] = {
reader
.read()
.flatMap { chunk =>
if (chunk.done) {
Future.successful(tunas)
} else {
read(reader)(tunas :+ chunk.value)
}
}
}

@Test
final def ReadableStreamConstructionAndConsumptionTest: AsyncResult = async {
case class Tuna(color: String)
Expand All @@ -35,20 +50,7 @@ trait BrowserTests {
}
)

val reader = stream.getReader()

def read(tunas: Seq[Tuna]): Future[Seq[Tuna]] = {
reader
.read()
.flatMap { chunk =>
if (chunk.done) {
Future.successful(tunas)
} else {
read(tunas :+ chunk.value)
}
}
}
read(Seq.empty)
read(stream.getReader())(Seq.empty)
.map { receivedTunas =>
assertEquals(receivedTunas, expectedTunas)
}
Expand Down Expand Up @@ -77,22 +79,53 @@ trait BrowserTests {
}
)

val reader = stream.getReader()

def read(strings: Seq[String]): Future[Seq[String]] = {
reader
.read()
.flatMap { chunk =>
if (chunk.done) {
Future.successful(strings)
} else {
read(strings :+ chunk.value)
}
}
}
read(Seq.empty)
read(stream.getReader())(Seq.empty)
.map { receivedStrings =>
assertEquals(receivedStrings, expectedStrings)
}
}

@Test
final def ReadableStreamReaderCancelUnitTest: AsyncResult = async {
val reasonPromise = Promise[Unit]()
val stream = ReadableStream[Unit](
new ReadableStreamUnderlyingSource[Unit] {
cancel = js.defined({ (reason: Any) =>
reasonPromise.tryComplete(Try(reason.asInstanceOf[Unit]))
(): js.UndefOr[js.Promise[Unit]]
}): js.UndefOr[js.Function1[Any, js.UndefOr[js.Promise[Unit]]]]
}
)

for {
_ <- stream
.getReader()
.cancel()
.map(assertEquals((), _))
_ <- reasonPromise.future.map(assertEquals((), _))
} yield ()
}

@Test
final def ReadableStreamReaderCancelPromiseTest: AsyncResult = async {
armanbilge marked this conversation as resolved.
Show resolved Hide resolved
val expectedReason = "probably a good one"

val reasonPromise = Promise[String]()
val stream = ReadableStream[Unit](
new ReadableStreamUnderlyingSource[Unit] {
cancel = js.defined({ (reason: Any) =>
reasonPromise.tryComplete(Try(reason.asInstanceOf[String]))
(): js.UndefOr[js.Promise[Unit]]
}): js.UndefOr[js.Function1[Any, js.UndefOr[js.Promise[Unit]]]]
}
)

for {
_ <- stream
.getReader()
.cancel(expectedReason)
.map(assertEquals((), _))
_ <- reasonPromise.future.map(assertEquals(expectedReason, _))
} yield ()
}
}