Skip to content

Commit

Permalink
Cleanups to typed array manipulation
Browse files Browse the repository at this point in the history
We now validate in the public API and then internal methods can assume they are using real array buffer views
  • Loading branch information
domenic committed Mar 10, 2016
1 parent a07ed09 commit c5d63de
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 52 deletions.
61 changes: 20 additions & 41 deletions index.bs
Expand Up @@ -1207,6 +1207,8 @@ Instances of <code>ReadableStreamBYOBReader</code> are created with the internal
<emu-alg>
1. If IsReadableStreamBYOBReader(*this*) is *false*, return a promise rejected with a *TypeError* exception.
1. If *this*@[[ownerReadableStream]] is *undefined*, return a promise rejected with a *TypeError* exception.
1. If Type(_view_) is not Object, return a promise rejected with a *TypeError* exception.
1. If _view_ does not have a [[ViewedArrayBuffer]] internal slot, return a promise rejected with a *TypeError* exception.
1. Return ReadableStreamBYOBReaderRead(*this*, _view_).
</emu-alg>

Expand Down Expand Up @@ -1286,15 +1288,11 @@ Instances of <code>ReadableStreamBYOBReader</code> are created with the internal
1. Let _stream_ be _reader_@[[ownerReadableStream]].
1. Assert: _stream_ is not *undefined*.
1. Set _stream_@[[disturbed]] to *true*.
1. If _view_ is *undefined* or ArrayBuffer.isView(_view_) is *false*, return a promise rejected with a *TypeError* exception.
1. Let _ctor_ be _view_'s constructor.
1. Let _elementSize_ be 1.
1. If _ctor_ is `Int16Array` or _ctor_ is `Uint16Array` or _ctor_ is `Int32Array` or _ctor_ is `Uint32Array` or _ctor_ is `Float32Array` or _ctor_ is `Float64Array` or _ctor_ is `Int8Array` or _ctor_ is `Uint8Array` or _ctor_ is `Uint8ClampedArray`, let _elementSize_ be _ctor_.BYTES_PER_ELEMENT.
1. Otherwise,
1. If _ctor_ is not `DataView`, return a promise rejected with a *TypeError* exception.
1. If _view_@[[byteLength]] is 0, return a promise rejected with a *TypeError* exception.
1. If _view_ has a [[TypedArrayName]] internal slot (i.e., it is not a `DataView`), set _elementSize_ to the element size specified in <a href="https://tc39.github.io/ecma262/#table-49">The TypedArray Constructors table</a> for _view_@[[TypedArrayName]].
1. If _view_@[[ByteLength]] is 0, return a promise rejected with a *TypeError* exception.
1. If _stream_@[[state]] is `"errored"`, return a promise rejected with _stream_@[[storedError]].
1. Return ReadableStreamBYOBControllerPullInto(_stream_@[[readableStreamController]], _view_.[[ViewedArrayBuffer]], _view_@[[ByteOffset]], _view_@[[ByteLength]], _ctor_, _elementSize_).
1. Return ReadableStreamBYOBControllerPullInto(_stream_@[[readableStreamController]], _view_@[[ViewedArrayBuffer]], _view_@[[ByteOffset]], _view_@[[ByteLength]], _ctor_, _elementSize_).
</emu-alg>

<h4 id="readable-stream-default-reader-read" aoid="ReadableStreamDefaultReaderRead" nothrow>ReadableStreamDefaultReaderRead ( reader )</h4>
Expand Down Expand Up @@ -1794,6 +1792,8 @@ table:
1. If IsReadableStreamBYOBController(*this*) is *false*, throw a *TypeError* exception.
1. If *this*@[[closeRequested]] is *true*, throw a *TypeError* exception.
1. If *this*@[[controlledReadableStream]]@[[state]] is not `"readable"`, throw a *TypeError* exception.
1. If Type(_chunk_) is not Object, throw a *TypeError* exception.
1. If _chunk_ does not have a [[ViewedArrayBuffer]] internal slot, throw a *TypeError* exception.
1. Return ReadableStreamBYOBControllerEnqueue(*this*, _chunk_).
</emu-alg>

Expand Down Expand Up @@ -1838,7 +1838,7 @@ controllers.
1. Remove _entry_ from *this*@[[queue]], shifting all other elements downward (so that the second becomes the first, and so on).
1. Subtract _entry_.[[byteLength]] from *this*@[[totalQueuedBytes]].
1. Perform ReadableStreamBYOBControllerHandleQueueDrain(*this*).
1. Let _view_ be Construct(`Uint8Array`, «_entry_.[[buffer]], _entry_.[[byteOffset]], _entry_.[[byteLength]]»).
1. Let _view_ be Construct(%Uint8Array%, «_entry_.[[buffer]], _entry_.[[byteOffset]], _entry_.[[byteLength]]»).
1. Return a promise resolved with CreateIterResultObject(_view_, *false*).
1. Let _promise_ be ReadableStreamAddReadRequest(_stream_).
1. Perform ReadableStreamDefaultControllerCallPullIfNeeded(*this*).
Expand Down Expand Up @@ -1919,6 +1919,8 @@ table:
<emu-alg>
1. If IsReadableStreamBYOBRequest(*this*) is *false*, throw a *TypeError* exception.
1. If *this*@[[associatedReadableStreamBYOBController]] is *undefined*, throw a *TypeError* exception.
1. If Type(_chunk_) is not Object, throw a *TypeError* exception.
1. If _view_ does not have a [[ViewedArrayBuffer]] internal slot, throw a *TypeError* exception.
1. Return ReadableStreamBYOBControllerRespondWithNewView(*this*@[[associatedReadableStreamBYOBController]], _view_).
</emu-alg>

Expand Down Expand Up @@ -2056,7 +2058,7 @@ table:
1. Let _e_ be a *TypeError* exception.
1. Perform ReadableStreamBYOBControllerError(_controller_, _e_).
1. Return a promise rejected with _e_.
1. Transfer _pullIntoDescriptor_@[[buffer]] and set _pullIntoDescriptor_.[[buffer]] to the result.
1. Transfer _pullIntoDescriptor_.[[buffer]] and set _pullIntoDescriptor_.[[buffer]] to the result.
1. Append _pullIntoDescriptor_ as the last element of _controller_@[[pendingPullIntos]].
1. Let _promise_ be ReadableStreamAddReadIntoRequest(_stream_, _byteOffset_, _byteLength_, _ctor_, _elementSize_).
1. Perform ReadableStreamBYOBControllerCallPullIfNeeded(_controller_).
Expand Down Expand Up @@ -2099,7 +2101,7 @@ table:
1. If _remainderSize_ &gt; 0,
1. Let _end_ be _pullIntoDescriptor_.[[byteOffset]] + _pullIntoDescriptor_.[[bytesFilled]].
1. Let _remainder_ be a new ArrayBuffer containing the _remainderSize_ bytes of _pullIntoDescriptor_.[[buffer]] at offset _end_ - _remainderSize_.
1. Perform ReadableStreamBYOBControllerEnqueueChunkToQueue(_controller_, _remainder_, 0, _remainder_@[[byteLength]]).
1. Perform ReadableStreamBYOBControllerEnqueueChunkToQueue(_controller_, _remainder_, 0, _remainder_@[[ByteLength]]).
1. Perform ReadableStreamRespondToReadIntoRequest(_controller_@[[controlledReadableStream]], _transferredBuffer_, _pullIntoDescriptor_.[[bytesFilled]] - _remainderSize_).
1. Perform ReadableStreamBYOBControllerRespondToReadIntoRequestsFromQueue(_controller_).
</emu-alg>
Expand Down Expand Up @@ -2164,17 +2166,17 @@ table:
1. Let _stream_ be _controller_@[[controlledReadableStream]].
1. Assert: _controller_@[[closeRequested]] is *false*.
1. Assert: _controller_@[[state]] is `"readable"`.
1. Let _buffer_ be _chunk_@[[buffer]].
1. Let _byteOffset_ be _chunk_@[[byteOffset]].
1. Let _byteLength_ be _chunk_@[[byteLength]].
1. Let _buffer_ be _chunk_@[[ViewedArrayBuffer]].
1. Let _byteOffset_ be _chunk_@[[ByteOffset]].
1. Let _byteLength_ be _chunk_@[[ByteLength]].
1. If ReadableStreamHasReader(_stream_) is *true*
1. If ReadableStreamGetNumReadRequests(_stream_) is 0,
1. Transfer _buffer_ and let _transferredBuffer_ be the result.
1. Perform ReadableStreamBYOBControllerEnqueueChunkToQueue(_controller_, _transferredBuffer_, _byteOffset_, _byteLength_).
1. Otherwise,
1. Assert: _controller_@[[queue]] is empty.
1. Transfer _buffer_ and let _transferredBuffer_ be the result.
1. Let _transferredView_ be Construct(`Uint8Array`, «_transferredBuffer_, _byteOffset_, _byteLength_»).
1. Let _transferredView_ be Construct(%Uint8Array%, «_transferredBuffer_, _byteOffset_, _byteLength_»).
1. Perform ReadableStreamRespondToReadRequest(_stream_, _transferredView_).
1. Otherwise,
1. If ReadableStreamHasBYOBReader(_stream_) is *true*,
Expand Down Expand Up @@ -2218,12 +2220,12 @@ table:
<emu-alg>
1. Assert: _controller_@[[pendingPullIntos]] is not empty.
1. Let _firstDescriptor_ be the first element of _controller_@[[pendingPullIntos]].
1. If _firstDescriptor_.[[byteOffset]] + _firstDescriptor_.[[bytesFilled]] is not _view_@[[byteOffset]],
1. If _firstDescriptor_.[[byteOffset]] + _firstDescriptor_.[[bytesFilled]] is not _view_@[[ByteOffset]],
1. Throw a *RangeError* exception.
1. If _firstDescriptor_.[[byteLength]] is not _view_@[[byteOffset]],
1. If _firstDescriptor_.[[byteLength]] is not _view_@[[ByteOffset]],
1. Throw a *RangeError* exception.
1. Set _firstDescriptor_.[[buffer]] to _view_@[[buffer]].
1. Return ReadableStreamBYOBControllerRespondInternal(_controller_, _view_@[[byteLength]]).
1. Set _firstDescriptor_.[[buffer]] to _view_@[[ViewedArrayBuffer]].
1. Return ReadableStreamBYOBControllerRespondInternal(_controller_, _view_@[[ByteLength]]).
</emu-alg>

<h5 id="readable-stream-byob-request-invalidate" aoid="ReadableStreamBYOBRequestInvalidate" nothrow>ReadableStreamBYOBRequestInvalidate ( request )</h4>
Expand Down Expand Up @@ -2889,29 +2891,6 @@ throughout the rest of this standard.

A few abstract operations are used in this specification for utility purposes. We define them here.

<h4 id="get-viewed-array-buffer" aoid="GetViewedArrayBuffer" throws>GetViewedArrayBuffer ( O )</h4>

<emu-alg>
1. Return the result of the same algorithm as used by the get accessor function of the original value of %TypedArray%.prototype.buffer, with _O_ in place of *this*.
</emu-alg>

<div class="note">
Ideally, this operation and its counterparts <a href="https://bugs.ecmascript.org/show_bug.cgi?id=4369">would be
defined by ECMAScript</a>.
</div>

<h4 id="get-byte-length" aoid="GetByteLength" throws>GetByteLength ( O )</h4>

<emu-alg>
1. Return the result of the same algorithm as used by the get accessor function of the original value of %TypedArray%.prototype.byteLength, with _O_ in place of *this*.
</emu-alg>

<h4 id="get-byte-offset" aoid="GetByteOffset" throws>GetByteOffset ( O )</h4>

<emu-alg>
1. Return the result of the same algorithm as used by the get accessor function of the original value of %TypedArray%.prototype.byteOffset, with _O_ in place of *this*.
</emu-alg>

<h4 id="is-finite-non-negative-number" aoid="IsFiniteNonNegativeNumber" nothrow>IsFiniteNonNegativeNumber ( v )</h4>

<emu-alg>
Expand Down
25 changes: 14 additions & 11 deletions reference-implementation/lib/readable-stream.js
Expand Up @@ -658,6 +658,10 @@ class ReadableStreamBYOBReader {
return Promise.reject(new TypeError('Cannot read from a released reader'));
}

if (!ArrayBuffer.isView(view)) {
return Promise.reject(new TypeError('view must be an array buffer view'));
}

return ReadableStreamBYOBReaderRead(this, view);
}

Expand Down Expand Up @@ -758,18 +762,9 @@ function ReadableStreamBYOBReaderRead(reader, view) {

stream._disturbed = true;

if (view === undefined || ArrayBuffer.isView(view) === false) {
return Promise.reject(new TypeError('Valid view must be provided'));
}

const ctor = view.constructor;
let elementSize = 1;
if (ctor === Int16Array || ctor === Uint16Array || ctor === Int32Array || ctor === Uint32Array ||
ctor === Float32Array || ctor === Float64Array || ctor === Int8Array || ctor === Uint8Array ||
ctor === Uint8ClampedArray) {
elementSize = ctor.BYTES_PER_ELEMENT;
} else if (ctor !== DataView) {
return Promise.reject(new TypeError('view is of an unsupported type'));
if (view.constructor !== DataView) {
elementSize = view.constructor.BYTES_PER_ELEMENT;
}

if (view.byteLength === 0) {
Expand Down Expand Up @@ -1111,6 +1106,10 @@ class ReadableStreamBYOBRequest {
throw new TypeError('This BYOB request has been invalidated');
}

if (!ArrayBuffer.isView(chunk)) {
throw new TypeError('You can only respond with array buffer views');
}

ReadableStreamBYOBControllerRespondWithNewView(this._associatedReadableStreamBYOBController, view);
}

Expand Down Expand Up @@ -1228,6 +1227,10 @@ class ReadableStreamBYOBController {
throw new TypeError('The stream is not in the readable state and cannot be enqueued to');
}

if (!ArrayBuffer.isView(chunk)) {
throw new TypeError('You can only enqueue array buffer views when using a ReadableStreamBYOBController');
}

ReadableStreamBYOBControllerEnqueue(this, chunk);
}

Expand Down

0 comments on commit c5d63de

Please sign in to comment.