From 7f4f1df4f14b38a613a226e12614267a170c8c92 Mon Sep 17 00:00:00 2001 From: isonmad Date: Sat, 5 Nov 2016 02:39:47 +0000 Subject: [PATCH 1/4] add ReadableByteStreamControllerGetBYOBRequest abstract op --- index.bs | 22 +++++++++++------ .../lib/readable-stream.js | 24 +++++++++++-------- 2 files changed, 29 insertions(+), 17 deletions(-) diff --git a/index.bs b/index.bs index ac3e82e05..e6f567133 100644 --- a/index.bs +++ b/index.bs @@ -1885,13 +1885,7 @@ ReadableByteStreamController(stream, underlyingByteSource, 1. If IsReadableByteStreamController(*this*) is *false*, throw a *TypeError* exception. - 1. If *this*.[[byobRequest]] is *undefined* and *this*.[[pendingPullIntos]] is not empty, - 1. Let _firstDescriptor_ be the first element of *this*.[[pendingPullIntos]]. - 1. Let _view_ be ! Construct(%Uint8Array%, « _firstDescriptor_.[[buffer]], - _firstDescriptor_.[[byteOffset]] + _firstDescriptor_.[[bytesFilled]], _firstDescriptor_.[[byteLength]] − - _firstDescriptor_.[[bytesFilled]] »). - 1. Set *this*.[[byobRequest]] to ! Construct(`ReadableStreamBYOBRequest`, « *this*, _view_ »). - 1. Return *this*.[[byobRequest]]. + 1. Return ! ReadableByteStreamControllerGetBYOBRequest(*this*).
get desiredSize
@@ -2285,6 +2279,20 @@ nothrow>ReadableByteStreamControllerFillPullIntoDescriptorFromQueue ( contr 1. Return _ready_. +

ReadableByteStreamControllerGetBYOBRequest ( controller )

+ + + 1. If _controller_.[[byobRequest]] is *undefined* and _controller_.[[pendingPullIntos]] is not empty, + 1. Let _firstDescriptor_ be the first element of _controller_.[[pendingPullIntos]]. + 1. Let _view_ be ! Construct(%Uint8Array%, « _firstDescriptor_.[[buffer]], + _firstDescriptor_.[[byteOffset]] + _firstDescriptor_.[[bytesFilled]], _firstDescriptor_.[[byteLength]] − + _firstDescriptor_.[[bytesFilled]] »). + 1. Set _controller_.[[byobRequest]] to ! Construct(`ReadableStreamBYOBRequest`, + « _controller_, _view_ »). + 1. Return _controller_.[[byobRequest]]. + +

ReadableByteStreamControllerGetDesiredSize ( controller )

diff --git a/reference-implementation/lib/readable-stream.js b/reference-implementation/lib/readable-stream.js index 4852188fe..038d86d27 100644 --- a/reference-implementation/lib/readable-stream.js +++ b/reference-implementation/lib/readable-stream.js @@ -1212,16 +1212,7 @@ class ReadableByteStreamController { throw byteStreamControllerBrandCheckException('byobRequest'); } - if (this._byobRequest === undefined && this._pendingPullIntos.length > 0) { - const firstDescriptor = this._pendingPullIntos[0]; - const view = new Uint8Array(firstDescriptor.buffer, - firstDescriptor.byteOffset + firstDescriptor.bytesFilled, - firstDescriptor.byteLength - firstDescriptor.bytesFilled); - - this._byobRequest = new ReadableStreamBYOBRequest(this, view); - } - - return this._byobRequest; + return ReadableByteStreamControllerGetBYOBRequest(this); } get desiredSize() { @@ -1772,6 +1763,19 @@ function ReadableByteStreamControllerError(controller, e) { ReadableStreamError(stream, e); } +function ReadableByteStreamControllerGetBYOBRequest(controller) { + if (controller._byobRequest === undefined && controller._pendingPullIntos.length > 0) { + const firstDescriptor = controller._pendingPullIntos[0]; + const view = new Uint8Array(firstDescriptor.buffer, + firstDescriptor.byteOffset + firstDescriptor.bytesFilled, + firstDescriptor.byteLength - firstDescriptor.bytesFilled); + + controller._byobRequest = new ReadableStreamBYOBRequest(controller, view); + } + + return controller._byobRequest; +} + function ReadableByteStreamControllerGetDesiredSize(controller) { return controller._strategyHWM - controller._totalQueuedBytes; } From d53cb793991bafb2f3b9f55fe7d521722f6ec310 Mon Sep 17 00:00:00 2001 From: isonmad Date: Sat, 5 Nov 2016 02:59:50 +0000 Subject: [PATCH 2/4] add assert in ReadableByteStreamControllerEnqueue --- index.bs | 2 ++ reference-implementation/lib/readable-stream.js | 1 + 2 files changed, 3 insertions(+) diff --git a/index.bs b/index.bs index e6f567133..4e83d060e 100644 --- a/index.bs +++ b/index.bs @@ -2181,6 +2181,8 @@ nothrow>ReadableByteStreamControllerEnqueue ( controller, chunk< 1. Let _stream_ be _controller_.[[controlledReadableStream]]. 1. Assert: _controller_.[[closeRequested]] is *false*. 1. Assert: _stream_.[[state]] is `"readable"`. + 1. Assert: Type(_chunk_) is Object. + 1. Assert: _chunk_ has a [[ViewedArrayBuffer]] internal slot. 1. Let _buffer_ be _chunk_.[[ViewedArrayBuffer]]. 1. Let _byteOffset_ be _chunk_.[[ByteOffset]]. 1. Let _byteLength_ be _chunk_.[[ByteLength]]. diff --git a/reference-implementation/lib/readable-stream.js b/reference-implementation/lib/readable-stream.js index 038d86d27..ae3ab4e01 100644 --- a/reference-implementation/lib/readable-stream.js +++ b/reference-implementation/lib/readable-stream.js @@ -1726,6 +1726,7 @@ function ReadableByteStreamControllerEnqueue(controller, chunk) { assert(controller._closeRequested === false); assert(stream._state === 'readable'); + assert(ArrayBuffer.isView(chunk) === true); const buffer = chunk.buffer; const byteOffset = chunk.byteOffset; From d2b184a5baac3c41365cbc76ebfa9c90525be037 Mon Sep 17 00:00:00 2001 From: isonmad Date: Sat, 5 Nov 2016 03:21:49 +0000 Subject: [PATCH 3/4] add "bytes" type to TransformStream --- .../lib/readable-stream.js | 5 + .../lib/transform-stream.js | 107 ++++++++++++++---- 2 files changed, 88 insertions(+), 24 deletions(-) diff --git a/reference-implementation/lib/readable-stream.js b/reference-implementation/lib/readable-stream.js index ae3ab4e01..164f783a3 100644 --- a/reference-implementation/lib/readable-stream.js +++ b/reference-implementation/lib/readable-stream.js @@ -256,6 +256,11 @@ class ReadableStream { module.exports = { ReadableStream, IsReadableStreamDisturbed, + ReadableByteStreamControllerClose, + ReadableByteStreamControllerEnqueue, + ReadableByteStreamControllerError, + ReadableByteStreamControllerGetBYOBRequest, + ReadableByteStreamControllerGetDesiredSize, ReadableStreamDefaultControllerClose, ReadableStreamDefaultControllerEnqueue, ReadableStreamDefaultControllerError, diff --git a/reference-implementation/lib/transform-stream.js b/reference-implementation/lib/transform-stream.js index cf0ab5154..a165e5f3e 100644 --- a/reference-implementation/lib/transform-stream.js +++ b/reference-implementation/lib/transform-stream.js @@ -3,7 +3,10 @@ const assert = require('assert'); const { InvokeOrNoop, PromiseInvokeOrPerformFallback, PromiseInvokeOrNoop, typeIsObject } = require('./helpers.js'); const { ReadableStream, ReadableStreamDefaultControllerClose, ReadableStreamDefaultControllerEnqueue, ReadableStreamDefaultControllerError, - ReadableStreamDefaultControllerGetDesiredSize } = require('./readable-stream.js'); + ReadableStreamDefaultControllerGetDesiredSize, + ReadableByteStreamControllerClose, ReadableByteStreamControllerEnqueue, + ReadableByteStreamControllerError, ReadableByteStreamControllerGetBYOBRequest, + ReadableByteStreamControllerGetDesiredSize } = require('./readable-stream.js'); const { WritableStream, WritableStreamDefaultControllerError } = require('./writable-stream.js'); // Methods on the transform stream controller object @@ -37,19 +40,28 @@ function TransformStreamEnqueueToReadable(transformStream, chunk) { // accept TransformStreamEnqueueToReadable() calls. const controller = transformStream._readableController; + const type = transformStream._readableType; + assert(type === undefined || type === 'bytes'); - try { - ReadableStreamDefaultControllerEnqueue(controller, chunk); - } catch (e) { - // This happens when readableStrategy.size() throws. - // The ReadableStream has already errored itself. - transformStream._readableClosed = true; - TransformStreamErrorIfNeeded(transformStream, e); - - throw transformStream._storedError; + if (type === 'bytes') { + if (ArrayBuffer.isView(chunk) === false) { + throw new TypeError('You can only enqueue array buffer views when readableType is "bytes"'); + } + ReadableByteStreamControllerEnqueue(controller, chunk); + } else if (type === undefined) { + try { + ReadableStreamDefaultControllerEnqueue(controller, chunk); + } catch (e) { + // This happens when readableStrategy.size() throws. + // The ReadableStream has already errored itself. + transformStream._readableClosed = true; + TransformStreamErrorIfNeeded(transformStream, e); + + throw transformStream._storedError; + } } - const desiredSize = ReadableStreamDefaultControllerGetDesiredSize(controller); + const desiredSize = TransformStreamGetDesiredSize(transformStream); const maybeBackpressure = desiredSize <= 0; if (maybeBackpressure === true && transformStream._backpressure === false) { @@ -76,10 +88,14 @@ function TransformStreamCloseReadableInternal(transformStream) { assert(transformStream._errored === false); assert(transformStream._readableClosed === false); - try { - ReadableStreamDefaultControllerClose(transformStream._readableController); - } catch (e) { - assert(false); + const readableController = transformStream._readableController; + const type = transformStream._readableType; + assert(type === undefined || type === 'bytes'); + + if (type === 'bytes') { + ReadableByteStreamControllerClose(readableController); + } else if (type === undefined) { + ReadableStreamDefaultControllerClose(readableController); } transformStream._readableClosed = true; @@ -99,11 +115,23 @@ function TransformStreamErrorInternal(transformStream, e) { transformStream._errored = true; transformStream._storedError = e; + const writableController = transformStream._writableController; + const readableController = transformStream._readableController; + + const writableType = transformStream._writableType; + const readableType = transformStream._readableType; + assert(writableType === undefined); + assert(readableType === 'bytes' || readableType === undefined); + if (transformStream._writableDone === false) { - WritableStreamDefaultControllerError(transformStream._writableController, e); + WritableStreamDefaultControllerError(writableController, e); } if (transformStream._readableClosed === false) { - ReadableStreamDefaultControllerError(transformStream._readableController, e); + if (readableType === 'bytes') { + ReadableByteStreamControllerError(readableController, e); + } else if (readableType === undefined) { + ReadableStreamDefaultControllerError(readableController, e); + } } } @@ -176,6 +204,19 @@ function TransformStreamTransform(transformStream, chunk) { e => TransformStreamErrorIfNeeded(transformStream, e)); } +function TransformStreamGetDesiredSize(transformStream) { + const type = transformStream._readableType; + const controller = transformStream._readableController; + + assert(type === undefined || type === 'bytes'); + + if (type === 'bytes') { + return ReadableByteStreamControllerGetDesiredSize(controller); + } else if (type === undefined) { + return ReadableStreamDefaultControllerGetDesiredSize(controller); + } +} + function IsTransformStreamDefaultController(x) { if (!typeIsObject(x)) { return false; @@ -201,9 +242,10 @@ function IsTransformStream(x) { } class TransformStreamSink { - constructor(transformStream, startPromise) { + constructor(transformStream, startPromise, type) { this._transformStream = transformStream; this._startPromise = startPromise; + this.type = type; } start(c) { @@ -256,9 +298,10 @@ class TransformStreamSink { } class TransformStreamSource { - constructor(transformStream, startPromise) { + constructor(transformStream, startPromise, type) { this._transformStream = transformStream; this._startPromise = startPromise; + this.type = type; } start(c) { @@ -321,15 +364,28 @@ class TransformStreamDefaultController { this._controlledTransformStream = transformStream; } + get byobRequest() { + if (IsTransformStreamDefaultController(this) === false) { + throw defaultControllerBrandCheckException('byobRequest'); + } + + if (this._readableType !== 'bytes') { + return undefined; + } + + const readableController = this._readableController; + + return ReadableByteStreamControllerGetBYOBRequest(readableController); + } + get desiredSize() { if (IsTransformStreamDefaultController(this) === false) { throw defaultControllerBrandCheckException('desiredSize'); } const transformStream = this._controlledTransformStream; - const readableController = transformStream._readableController; - return ReadableStreamDefaultControllerGetDesiredSize(readableController); + return TransformStreamGetDesiredSize(transformStream); } enqueue(chunk) { @@ -379,23 +435,26 @@ class TransformStream { this._transformStreamController = new TransformStreamDefaultController(this); + this._readableType = transformer.readableType; + this._writableType = transformer.writableType; + let startPromise_resolve; const startPromise = new Promise(resolve => { startPromise_resolve = resolve; }); - const source = new TransformStreamSource(this, startPromise); + const source = new TransformStreamSource(this, startPromise, this._readableType); this._readable = new ReadableStream(source, readableStrategy); - const sink = new TransformStreamSink(this, startPromise); + const sink = new TransformStreamSink(this, startPromise, this._writableType); this._writable = new WritableStream(sink, writableStrategy); assert(this._writableController !== undefined); assert(this._readableController !== undefined); - const desiredSize = ReadableStreamDefaultControllerGetDesiredSize(this._readableController); + const desiredSize = TransformStreamGetDesiredSize(this); // Set _backpressure based on desiredSize. As there is no read() at this point, we can just interpret // desiredSize being non-positive as backpressure. TransformStreamSetBackpressure(this, desiredSize <= 0); From e1a390d006c34ca003a7fcf9ae202d123213b991 Mon Sep 17 00:00:00 2001 From: isonmad Date: Sat, 5 Nov 2016 16:18:40 +0000 Subject: [PATCH 4/4] check types in transformstream --- reference-implementation/lib/transform-stream.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/reference-implementation/lib/transform-stream.js b/reference-implementation/lib/transform-stream.js index a165e5f3e..370292161 100644 --- a/reference-implementation/lib/transform-stream.js +++ b/reference-implementation/lib/transform-stream.js @@ -243,6 +243,9 @@ function IsTransformStream(x) { class TransformStreamSink { constructor(transformStream, startPromise, type) { + if (type !== undefined) { + throw TypeError(`writableType cannot be ${type}`); + } this._transformStream = transformStream; this._startPromise = startPromise; this.type = type; @@ -299,6 +302,9 @@ class TransformStreamSink { class TransformStreamSource { constructor(transformStream, startPromise, type) { + if (type !== undefined && type !== 'bytes') { + throw TypeError(`readableType cannot be ${type}`); + } this._transformStream = transformStream; this._startPromise = startPromise; this.type = type;