Diff
Modified: trunk/LayoutTests/ChangeLog (214264 => 214265)
--- trunk/LayoutTests/ChangeLog 2017-03-22 18:04:19 UTC (rev 214264)
+++ trunk/LayoutTests/ChangeLog 2017-03-22 18:07:49 UTC (rev 214265)
@@ -1,3 +1,15 @@
+2017-03-22 Romain Bellessort <romain.belless...@crf.canon.fr>
+
+ [Readable Streams API] Implement ReadableStreamBYOBRequest respond() (readable stream state)
+ https://bugs.webkit.org/show_bug.cgi?id=169759
+
+ Reviewed by Youenn Fablet.
+
+ Added new tests to check code that can currently be reached.
+
+ * streams/readable-stream-byob-request-expected.txt: Updated.
+ * streams/readable-stream-byob-request.js: Updated.
+
2017-03-22 Youenn Fablet <you...@apple.com>
Move LayoutTests/webrtc/rtcconfiguration-icecandidatepoolsize.html to web-platform-tests
Modified: trunk/LayoutTests/imported/w3c/ChangeLog (214264 => 214265)
--- trunk/LayoutTests/imported/w3c/ChangeLog 2017-03-22 18:04:19 UTC (rev 214264)
+++ trunk/LayoutTests/imported/w3c/ChangeLog 2017-03-22 18:07:49 UTC (rev 214265)
@@ -1,3 +1,15 @@
+2017-03-22 Romain Bellessort <romain.belless...@crf.canon.fr>
+
+ [Readable Streams API] Implement ReadableStreamBYOBRequest respond() (readable stream state)
+ https://bugs.webkit.org/show_bug.cgi?id=169759
+
+ Reviewed by Youenn Fablet.
+
+ Updated test expectations.
+
+ * web-platform-tests/streams/readable-byte-streams/general-expected.txt:
+ * web-platform-tests/streams/readable-byte-streams/general.dedicatedworker-expected.txt:
+
2017-03-22 Youenn Fablet <you...@apple.com>
Move LayoutTests/webrtc/rtcconfiguration-icecandidatepoolsize.html to web-platform-tests
Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/streams/readable-byte-streams/general-expected.txt (214264 => 214265)
--- trunk/LayoutTests/imported/w3c/web-platform-tests/streams/readable-byte-streams/general-expected.txt 2017-03-22 18:04:19 UTC (rev 214264)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/streams/readable-byte-streams/general-expected.txt 2017-03-22 18:07:49 UTC (rev 214265)
@@ -15,8 +15,8 @@
PASS ReadableStream with byte source: releaseLock() on ReadableStreamReader with pending read() must throw
PASS ReadableStream with byte source: Automatic pull() after start()
PASS ReadableStream with byte source: Automatic pull() after start() and read()
-FAIL ReadableStream with byte source: autoAllocateChunkSize assert_equals: pull() must have been invoked once expected 1 but got 0
-FAIL ReadableStream with byte source: Mix of auto allocate and BYOB promise_test: Unhandled rejection with value: object "TypeError: Readable state is not yet supported"
+PASS ReadableStream with byte source: autoAllocateChunkSize
+FAIL ReadableStream with byte source: Mix of auto allocate and BYOB promise_test: Unhandled rejection with value: object "TypeError: ReadableStreamBYOBReader is not implemented"
PASS ReadableStream with byte source: Automatic pull() after start() and read(view)
PASS ReadableStream with byte source: enqueue(), getReader(), then read()
PASS ReadableStream with byte source: Push source that doesn't understand pull signal
Modified: trunk/LayoutTests/imported/w3c/web-platform-tests/streams/readable-byte-streams/general.dedicatedworker-expected.txt (214264 => 214265)
--- trunk/LayoutTests/imported/w3c/web-platform-tests/streams/readable-byte-streams/general.dedicatedworker-expected.txt 2017-03-22 18:04:19 UTC (rev 214264)
+++ trunk/LayoutTests/imported/w3c/web-platform-tests/streams/readable-byte-streams/general.dedicatedworker-expected.txt 2017-03-22 18:07:49 UTC (rev 214265)
@@ -15,8 +15,8 @@
PASS ReadableStream with byte source: releaseLock() on ReadableStreamReader with pending read() must throw
PASS ReadableStream with byte source: Automatic pull() after start()
PASS ReadableStream with byte source: Automatic pull() after start() and read()
-FAIL ReadableStream with byte source: autoAllocateChunkSize assert_equals: pull() must have been invoked once expected 1 but got 0
-FAIL ReadableStream with byte source: Mix of auto allocate and BYOB promise_test: Unhandled rejection with value: object "TypeError: Readable state is not yet supported"
+PASS ReadableStream with byte source: autoAllocateChunkSize
+FAIL ReadableStream with byte source: Mix of auto allocate and BYOB promise_test: Unhandled rejection with value: object "TypeError: ReadableStreamBYOBReader is not implemented"
PASS ReadableStream with byte source: Automatic pull() after start() and read(view)
PASS ReadableStream with byte source: enqueue(), getReader(), then read()
PASS ReadableStream with byte source: Push source that doesn't understand pull signal
Modified: trunk/LayoutTests/streams/readable-stream-byob-request-expected.txt (214264 => 214265)
--- trunk/LayoutTests/streams/readable-stream-byob-request-expected.txt 2017-03-22 18:04:19 UTC (rev 214264)
+++ trunk/LayoutTests/streams/readable-stream-byob-request-expected.txt 2017-03-22 18:07:49 UTC (rev 214265)
@@ -8,6 +8,8 @@
PASS Calling respond() with a positive infinity bytesWritten value should throw a RangeError
PASS Calling respond() with a bytesWritten value different from 0 when stream is closed should throw a TypeError
PASS Calling respond() with a bytesWritten value of 0 when stream is closed should succeed
+PASS Calling respond() with a bytesWritten value greater than autoAllocateChunkSize should fail
+PASS Calling respond() with a bytesWritten value lower than autoAllocateChunkSize should succeed
PASS ReadableStreamBYOBRequest instances should have the correct list of properties
PASS By default, byobRequest should be undefined
PASS byobRequest.view length should be equal to autoAllocateChunkSize
@@ -17,4 +19,6 @@
PASS Calling respond() with a positive infinity bytesWritten value should throw a RangeError
PASS Calling respond() with a bytesWritten value different from 0 when stream is closed should throw a TypeError
PASS Calling respond() with a bytesWritten value of 0 when stream is closed should succeed
+PASS Calling respond() with a bytesWritten value greater than autoAllocateChunkSize should fail
+PASS Calling respond() with a bytesWritten value lower than autoAllocateChunkSize should succeed
Modified: trunk/LayoutTests/streams/readable-stream-byob-request.js (214264 => 214265)
--- trunk/LayoutTests/streams/readable-stream-byob-request.js 2017-03-22 18:04:19 UTC (rev 214264)
+++ trunk/LayoutTests/streams/readable-stream-byob-request.js 2017-03-22 18:07:49 UTC (rev 214265)
@@ -198,4 +198,47 @@
}, "Calling respond() with a bytesWritten value of 0 when stream is closed should succeed");
+test(function() {
+
+ let controller;
+ const rs = new ReadableStream({
+ autoAllocateChunkSize: 16,
+ start: function(c) {
+ controller = c;
+ },
+ type: "bytes"
+ });
+
+ rs.getReader().read();
+ const byobReq = controller.byobRequest;
+ assert_throws(new RangeError("bytesWritten value is too great"),
+ function() { byobReq.respond(17); });
+
+}, "Calling respond() with a bytesWritten value greater than autoAllocateChunkSize should fail");
+
+promise_test(function() {
+
+ const rs = new ReadableStream({
+ autoAllocateChunkSize: 16,
+ pull: function(controller) {
+ const br = controller.byobRequest;
+ br.view[0] = 1;
+ br.view[1] = 2;
+ br.respond(2);
+ },
+ type: "bytes"
+ });
+
+ return rs.getReader().read().then(result => {
+ assert_equals(result.value.byteLength, 2);
+ assert_equals(result.value.byteOffset, 0);
+ assert_equals(result.value.buffer.byteLength, 16);
+ assert_equals(result.value[0], 1);
+ assert_equals(result.value[1], 2);
+ });
+}, "Calling respond() with a bytesWritten value lower than autoAllocateChunkSize should succeed");
+
+// FIXME: when ReadableStreamBYOBReader is implemented, add tests with elementSize different from 1
+// so that more code can be covered.
+
done();
Modified: trunk/Source/WebCore/ChangeLog (214264 => 214265)
--- trunk/Source/WebCore/ChangeLog 2017-03-22 18:04:19 UTC (rev 214264)
+++ trunk/Source/WebCore/ChangeLog 2017-03-22 18:07:49 UTC (rev 214265)
@@ -1,3 +1,27 @@
+2017-03-22 Romain Bellessort <romain.belless...@crf.canon.fr>
+
+ [Readable Streams API] Implement ReadableStreamBYOBRequest respond() (readable stream state)
+ https://bugs.webkit.org/show_bug.cgi?id=169759
+
+ Reviewed by Youenn Fablet.
+
+ Implemented readable state part of respond() function. Parts of code cannot
+ currently be reached as they require ReadableStreamBYOBReader to be implemented.
+
+ Added new tests and updated expectations.
+
+ * Modules/streams/ReadableByteStreamInternals.js:
+ (readableByteStreamControllerEnqueue): Name shortened.
+ (readableByteStreamControllerRespondInternal): Updated with readable state case.
+ (cloneArrayBuffer): Added.
+ (readableByteStreamControllerRespondInReadableState): Added.
+ (readableByteStreamControllerRespondInClosedState): Updated.
+ (readableByteStreamControllerProcessPullDescriptors): Added.
+ (readableByteStreamControllerFillDescriptorFromQueue): Added.
+ (readableByteStreamControllerShiftPendingDescriptor): Name shortened.
+ (readableByteStreamControllerCommitDescriptor): Name shortened.
+ (readableByteStreamControllerConvertDescriptor): Name shortened.
+
2017-03-22 Youenn Fablet <you...@apple.com>
RTCPeerConnection is crashing if no backend is created
Modified: trunk/Source/WebCore/Modules/streams/ReadableByteStreamInternals.js (214264 => 214265)
--- trunk/Source/WebCore/Modules/streams/ReadableByteStreamInternals.js 2017-03-22 18:04:19 UTC (rev 214264)
+++ trunk/Source/WebCore/Modules/streams/ReadableByteStreamInternals.js 2017-03-22 18:07:49 UTC (rev 214265)
@@ -314,7 +314,7 @@
if (@readableStreamHasDefaultReader(stream)) {
if (!stream.@reader.@readRequests.length)
- @readableByteStreamControllerEnqueueChunkToQueue(controller, transferredBuffer, byteOffset, byteLength);
+ @readableByteStreamControllerEnqueueChunk(controller, transferredBuffer, byteOffset, byteLength);
else {
@assert(!controller.@queue.length);
let transferredView = new @Uint8Array(transferredBuffer, byteOffset, byteLength);
@@ -331,10 +331,11 @@
}
@assert(!@isReadableStreamLocked(stream));
- @readableByteStreamControllerEnqueueChunkToQueue(controller, transferredBuffer, byteOffset, byteLength);
+ @readableByteStreamControllerEnqueueChunk(controller, transferredBuffer, byteOffset, byteLength);
}
-function readableByteStreamControllerEnqueueChunkToQueue(controller, buffer, byteOffset, byteLength)
+// Spec name: readableByteStreamControllerEnqueueChunkToQueue.
+function readableByteStreamControllerEnqueueChunk(controller, buffer, byteOffset, byteLength)
{
"use strict";
@@ -372,12 +373,51 @@
@throwTypeError("bytesWritten is different from 0 even though stream is closed");
@readableByteStreamControllerRespondInClosedState(controller, firstDescriptor);
} else {
- // FIXME: Also implement case of readable state (distinct patch to avoid adding too many different cases
- // in a single patch).
- @throwTypeError("Readable state is not yet supported");
+ @assert(stream.@state === @streamReadable);
+ @readableByteStreamControllerRespondInReadableState(controller, bytesWritten, firstDescriptor);
}
}
+function cloneArrayBuffer(srcBuffer, srcByteOffset, srcLength)
+{
+ "use strict";
+
+ // FIXME: Below implementation returns the appropriate data but does not perform
+ // exactly what is described by ECMAScript CloneArrayBuffer operation. This should
+ // be fixed in a follow up patch implementing cloneArrayBuffer in JSC (similarly to
+ // structuredCloneArrayBuffer implementation).
+ return srcBuffer.slice(srcByteOffset, srcByteOffset + srcLength);
+}
+
+function readableByteStreamControllerRespondInReadableState(controller, bytesWritten, pullIntoDescriptor)
+{
+ "use strict";
+
+ if (pullIntoDescriptor.bytesFilled + bytesWritten > pullIntoDescriptor.byteLength)
+ @throwRangeError("bytesWritten value is too great");
+
+ @assert(controller.@pendingPullIntos.length === 0 || controller.@pendingPullIntos[0] === pullIntoDescriptor);
+ @readableByteStreamControllerInvalidateBYOBRequest(controller);
+ pullIntoDescriptor.bytesFilled += bytesWritten;
+
+ if (pullIntoDescriptor.bytesFilled < pullIntoDescriptor.elementSize)
+ return;
+
+ @readableByteStreamControllerShiftPendingDescriptor(controller);
+ const remainderSize = pullIntoDescriptor.bytesFilled % pullIntoDescriptor.elementSize;
+
+ if (remainderSize > 0) {
+ const end = pullIntoDescriptor.byteOffset + pullIntoDescriptor.bytesFilled;
+ const remainder = @cloneArrayBuffer(pullIntoDescriptor.buffer, end - remainderSize, remainderSize);
+ @readableByteStreamControllerEnqueueChunk(controller, remainder, 0, remainder.byteLength);
+ }
+
+ pullIntoDescriptor.buffer = @transferBufferToCurrentRealm(pullIntoDescriptor.buffer);
+ pullIntoDescriptor.bytesFilled -= remainderSize;
+ @readableByteStreamControllerCommitDescriptor(controller.@controlledReadableStream, pullIntoDescriptor);
+ @readableByteStreamControllerProcessPullDescriptors(controller);
+}
+
function readableByteStreamControllerRespondInClosedState(controller, firstDescriptor)
{
"use strict";
@@ -393,15 +433,90 @@
return;
while (controller.@reader.@readIntoRequests.length > 0) {
- let pullIntoDescriptor = @readableByteStreamControllerShiftPendingPullInto(controller);
- @readableByteStreamControllerCommitPullIntoDescriptor(controller.@controlledReadableStream, pullIntoDescriptor);
+ let pullIntoDescriptor = @readableByteStreamControllerShiftPendingDescriptor(controller);
+ @readableByteStreamControllerCommitDescriptor(controller.@controlledReadableStream, pullIntoDescriptor);
}
}
-function readableByteStreamControllerShiftPendingPullInto(controller)
+// Spec name: readableByteStreamControllerProcessPullIntoDescriptorsUsingQueue (shortened for readability).
+function readableByteStreamControllerProcessPullDescriptors(controller)
{
"use strict";
+ @assert(!controller.@closeRequested);
+ while (controller.@pendingPullIntos.length > 0) {
+ if (controller.@totalQueuedBytes === 0)
+ return;
+ let pullIntoDescriptor = controller.@pendingPullIntos[0];
+ if (@readableByteStreamControllerFillDescriptorFromQueue(controller, pullIntoDescriptor)) {
+ @readableByteStreamControllerShiftPendingDescriptor(controller);
+ @readableByteStreamControllerCommitDescriptor(controller.@controlledReadableStream, pullIntoDescriptor);
+ }
+ }
+}
+
+// Spec name: readableByteStreamControllerFillPullIntoDescriptorFromQueue (shortened for readability).
+function readableByteStreamControllerFillDescriptorFromQueue(controller, pullIntoDescriptor)
+{
+ "use strict";
+
+ const currentAlignedBytes = pullIntoDescriptor.bytesFilled - (pullIntoDescriptor.bytesFilled % pullIntoDescriptor.elementSize);
+ const maxBytesToCopy = controller.@totalQueuedBytes < pullIntoDescriptor.byteLength - pullIntoDescriptor.bytesFilled ?
+ controller.@totalQueuedBytes : pullIntoDescriptor.byteLength - pullIntoDescriptor.bytesFilled;
+ const maxBytesFilled = pullIntoDescriptor.bytesFilled + maxBytesToCopy;
+ const maxAlignedBytes = maxBytesFilled - (maxBytesFilled % pullIntoDescriptor.elementSize);
+ let totalBytesToCopyRemaining = maxBytesToCopy;
+ let ready = false;
+
+ if (maxAlignedBytes > currentAlignedBytes) {
+ totalBytesToCopyRemaining = maxAlignedBytes - pullIntoDescriptor.bytesFilled;
+ ready = true;
+ }
+
+ while (totalBytesToCopyRemaining > 0) {
+ let headOfQueue = controller.@queue[0];
+ const bytesToCopy = totalBytesToCopyRemaining < headOfQueue.byteLength ? totalBytesToCopyRemaining : headOfQueue.byteLength;
+ // Copy appropriate part of pullIntoDescriptor.buffer to headOfQueue.buffer.
+ // Remark: this implementation is not completely aligned on the definition of CopyDataBlockBytes
+ // operation of ECMAScript (the case of Shared Data Block is not considered here, but it doesn't seem to be an issue).
+ let fromIndex = pullIntoDescriptor.byteOffset + pullIntoDescriptor.bytesFilled;
+ let count = bytesToCopy;
+ let toIndex = headOfQueue.byteOffset;
+ while (count > 0) {
+ headOfQueue.buffer[toIndex] = pullIntoDescriptor.buffer[fromIndex];
+ toIndex++;
+ fromIndex++;
+ count--;
+ }
+
+ if (headOfQueue.byteLength === bytesToCopy)
+ controller.@queue.@shift();
+ else {
+ headOfQueue.byteOffset += bytesToCopy;
+ headOfQueue.byteLength -= bytesToCopy;
+ }
+
+ controller.@totalQueuedBytes -= bytesToCopy;
+ @assert(controller.@pendingPullIntos.length === 0 || controller.@pendingPullIntos[0] === pullIntoDescriptor);
+ @readableByteStreamControllerInvalidateBYOBRequest(controller);
+ pullIntoDescriptor.bytesFilled += bytesToCopy;
+ totalBytesToCopyRemaining -= bytesToCopy;
+ }
+
+ if (!ready) {
+ @assert(controller.@totalQueuedBytes === 0);
+ @assert(pullIntoDescriptor.bytesFilled > 0);
+ @assert(pullIntoDescriptor.bytesFilled < pullIntoDescriptor.elementSize);
+ }
+
+ return ready;
+}
+
+// Spec name: readableByteStreamControllerShiftPendingPullInto (renamed for consistency).
+function readableByteStreamControllerShiftPendingDescriptor(controller)
+{
+ "use strict";
+
let descriptor = controller.@pendingPullIntos.@shift();
@readableByteStreamControllerInvalidateBYOBRequest(controller);
return descriptor;
@@ -418,7 +533,8 @@
controller.@byobRequest = @undefined;
}
-function readableByteStreamControllerCommitPullIntoDescriptor(stream, pullIntoDescriptor)
+// Spec name: readableByteStreamControllerCommitPullIntoDescriptor (shortened for readability).
+function readableByteStreamControllerCommitDescriptor(stream, pullIntoDescriptor)
{
"use strict";
@@ -428,7 +544,7 @@
@assert(!pullIntoDescriptor.bytesFilled);
done = true;
}
- let filledView = @readableByteStreamControllerConvertPullIntoDescriptor(pullIntoDescriptor);
+ let filledView = @readableByteStreamControllerConvertDescriptor(pullIntoDescriptor);
if (pullIntoDescriptor.readerType === "default")
@readableStreamFulfillReadRequest(stream, filledView, done);
else {
@@ -437,11 +553,12 @@
}
}
-function readableByteStreamControllerConvertPullIntoDescriptor(pullIntoDescriptor)
+// Spec name: readableByteStreamControllerConvertPullIntoDescriptor (shortened for readability).
+function readableByteStreamControllerConvertDescriptor(pullIntoDescriptor)
{
"use strict";
- @assert(pullIntoDescriptor.bytesFilled <= pullIntoDescriptor.bytesLength);
+ @assert(pullIntoDescriptor.bytesFilled <= pullIntoDescriptor.byteLength);
@assert(pullIntoDescriptor.bytesFilled % pullIntoDescriptor.elementSize === 0);
return new pullIntoDescriptor.ctor(pullIntoDescriptor.buffer, pullIntoDescriptor.byteOffset, pullIntoDescriptor.bytesFilled / pullIntoDescriptor.elementSize);