--- a/Overview.htm Thu Jan 23 19:50:26 2014 +0900
+++ b/Overview.htm Tue Jan 28 13:01:17 2014 +0900
@@ -794,77 +794,41 @@
<dt>Promise&lt;StreamReadResult> readUpTo()</dt>
<dd>
<p>
- This method reads data from the ReadableStream.
- The returned <a>Promise</a> is fulfilled only when the total cost of produced data becomes equal to or greater than the specified <a>cost</a> or the EOF is reached.
- The cost of data returned by this method is the same or less than the specified <var>size</var> argument.
- The cost of data returned by this method can be less than <var>size</var> when data cannot be fully converted into the type specified by <code>readBinaryAs</code> or an EOF was reached.
+ This method reads binary data from the ReadableStream.
+ The returned <a>Promise</a> is fulfilled when any of the following conditions is met:
+ <ul>
+ <li>The total size of produced bytes becomes equal to <var></var></li>
+ <li>The EOF is reached</li>
+ </ul>
+ The <a>cost</a> of data returned by this method can be less than <var>size</var> when data cannot be fully converted into the type specified by <a href="#widl-ReadableStream-readBinaryAs">readBinaryAs</a> or the EOF is reached.
</p>
<p>
- This method must run the steps below:
+ This method must run these steps:
<ol>
- <li>If <a href="#widl-ReadableStream-readBinaryAs">readBinaryAs</a> is "<code>text</code>", return a <a>Promise</a> rejected with a "<code><a>SyntaxError</a></code>"</li>
+ <li>If <a href="#widl-ReadableStream-readBinaryAs">readBinaryAs</a> is "<code>as-is</code>", return a <a>Promise</a> rejected with a "<code><a>SyntaxError</a></code>"</li>
- <li>If <a>readPending</a> is set, return a <a>Promise</a> rejected with an "<code><a>InvalidStateError</a></code>"</li>
- <li>Set <a>readPending</a></li>
+ <li>If <a>pendingRead</a> is not <code>null</code>, return a <a>Promise</a> rejected with an "<code><a>InvalidStateError</a></code>"</li>
- <li>Let <var>latchedType</var> be the current value of <a href="#widl-ReadableStream-readBinaryAs">readBinaryAs</a></li>
- <li>Let <var>latchedEncoding</var> be the current value of <a href="#widl-ReadableStream-readEncoding">readEncoding</a></li>
+ <li>Set <a>pendingRead</a> to a newly-created <a>PendingReadDescriptor</a></li>
+
+ <li>Set <a>pendingRead</a>.<var>binaryAs</var> to the current value of <a href="#widl-ReadableStream-readBinaryAs">readBinaryAs</a></li>
+ <li>Set <a>pendingRead</a>.<var>encoding</var> to the current value of <a href="#widl-ReadableStream-readEncoding">readEncoding</a></li>
+ <li>Set <a>pendingRead</a>.<var>size</var> to <var>size</var></li>
+ <li>Set <a>pendingRead</a>.<var>promise</var> to a newly-created <a>Promise</a></li>
<li>Set <a>readUpToPullAmount</a> to <var>size</var></li>
<li>Set <a>amountBeingReturned</a> to 0</li>
<li><a>Retrieve data</a></li>
- <li>Let <var>readPromise</var> be a newly-created <a>Promise</a></li>
- <li>Return <var>readPromise</var>, and then continue to process the steps in this algorithm</li>
-
- <li>Wait until the total cost of data in <a>readDataBuffer</a> becomes equal to or greater than <var>size</var> or <a>eofReached</a> is set</li>
-
- <li>
- Queue a task which runs the steps below:
- <ol>
- <li>Let <var>readableAmount</var> be the total cost of data in <a>readDataBuffer</a></li>
- <li>Let <var>maxAmountToConsume</var> be min(<var>size</var>, <var>readableAmount</var>)</li>
-
- <li>Let <var>result</var> be a newly-created <a>StreamReadResult</a></li>
- <li>
- <dl class="switch">
- <dt>If <var>latchedType</var> is "<code>none</code>"</dt>
- <dd>
- <ol>
- <li>Set <var>result</var>.<a href="#widl-StreamReadResult-data">data</a> to <code>undefined</code></li>
- <li>Pop data from <a>readDataBuffer</a> as much as possible but up to <var>maxAmountToConsume</var></li>
- </ol>
- </dd>
- <dt>Otherwise</dt>
- <dd>
- <ol>
- <li>Set <var>result</var>.<a href="#widl-StreamReadResult-data">data</a> to an object of the type specified by <var>latchedType</var> that can be created by consuming as much data as possible from <a>readDataBuffer</a> but up to <var>maxAmountToConsume</var></li>
- <li>Pop the consumed data from <a>readDataBuffer</a></li>
- </dd>
- </dl>
- </li>
- <li>Let <var>amountConsumed</var> be the total cost of data consumed in the last step</li>
- <li>Set <a href="#widl-StreamReadResult-amountConsumed">amountConsumed</a> of <var>result</var> to <var>amountConsumed</var></li>
- <li>Set <a href="#widl-StreamReadResult-eof">eof</a> of <var>result</var> to <code>true</code> if <a>readDataBuffer</a> is empty and <a>eofReached</a> is set</li>
- <li>Set <var>result</var>.<a href="#widl-StreamReadResult-error">error</a> to <a>sourceErrorDetail</a></li>
-
- <li>Set <a>amountBeingReturned</a> to <var>amountConsumed</var></li>
-
- <li>Set <a>readUpToPullAmount</a> to 0</li>
-
- <li>Unset <a>readPending</a></li>
-
- <li>Fulfill <var>readPromise</var> with <var>result</var></li>
- </ol>
- </li>
+ <li>Return <a>pendingRead</a>.<var>promise</var></li>
</ol>
</p>
<dl class="parameters">
<dt>[Clamp] unsigned long long size</dt>
- <dd>Max number of bytes to read.</dd>
+ <dd>Upper limit of total cost of data to be read</dd>
</dl>
<section class="note">
@@ -881,123 +845,27 @@
<p>
This method reads data from the ReadableStream.
The speed of reading can be roughly adjusted by using <a href="#widl-StreamReadResult-pullAmount">pullAmount</a>.
- pullAmount doesn't necessarily limit the size of data being read by this method.
+ <a href="#widl-StreamReadResult-pullAmount">pullAmount</a> doesn't necessarily limit the size of data being read by this method.
</p>
<p>
- This method must run the steps below:
+ This method must run these steps:
<ol>
- <li>If <a>readPending</a> is set, return a Promise reject with an "<code><a>InvalidStateError</a></code>"</li>
- <li>Set <a>readPending</a></li>
+ <li>If <a>pendingRead</a> is not <code>null</code>, return a Promise reject with an "<code><a>InvalidStateError</a></code>"</li>
- <li>Let <var>latchedType</var> be the current value of <a href="#widl-ReadableStream-readBinaryAs">readBinaryAs</a> attribute</li>
- <li>Let <var>latchedEncoding</var> be the current value of <a href="#widl-ReadableStream-readEncoding">readEncoding</a> attribute</li>
+ <li>Set <a>pendingRead</a> to a newly-created <a>PendingReadDescriptor</a></li>
+
+ <li>Set <a>pendingRead</a>.<var>binaryAs</var> to the current value of <a href="#widl-ReadableStream-readBinaryAs">readBinaryAs</a></li>
+ <li>Set <a>pendingRead</a>.<var>encoding</var> to the current value of <a href="#widl-ReadableStream-readEncoding">readEncoding</a></li>
+ <li>Set <a>pendingRead</a>.<var>size</var> to <code>undefined</code></li>
+ <li>Set <a>pendingRead</a>.<var>promise</var> to a newly-created <a>Promise</a></li>
<li>Set <a>amountBeingReturned</a> to 0</li>
<li><a>Retrieve data</a></li>
- <li>Let <var>readPromise</var> be a newly-created <a>Promise</a></li>
- <li>Return <var>readPromise</var>, and then continue to process the steps in this algorithm</li>
-
- <li>
- <dl class="switch">
- <dt>If <var>latchedType</var> is "<code>text</code>"</dt>
- <dd>
- Wait until any of the following conditions is met, and then run the steps for the condition:
- <dl class="switch">
- <dt>All or part of bytes in <a>readDataBuffer</a> can be converted into a non-empty <a>DOMString</a> when decoded using <var>latchedEncoding</var></dt>
- <dd>
- <ol>
- <li>Pop the bytes from <a>readDataBuffer</a></li>
- <li>Let <var>amountConsumed</var> be the number of the popped bytes</li>
- <li>Let <var>readData</var> be the result of decoding</li>
- </ol>
- </dd>
- <dt>It's clear decoding bytes in <a>readDataBuffer</a> using <var>latchedEncoding</var> fails regardless bytes to be retrieved in the future are</dt>
- <dd>
- <ol>
- <li>Reject <var>readPromise</var> with an "<code><a>InvalidStateError</a></code>"</li>
- <li>Terminate these steps</li>
- </ol>
- </dd>
- <dt>Anything that doesn't represent bytes in <a>readDataBuffer</a> is encountered</dt>
- <dd>
- <ol>
- <li>Reject <var>readPromise</var> with an "<code><a>InvalidStateError</a></code>"</li>
- <li>Terminate these steps</li>
- </ol>
- </dd>
- </dl>
- </dd>
- <dt>If <var>latchedType</var> is "<code>arraybuffer</code>" or "<code>blob</code>"</dt>
- <dd>
- Wait until any of the following conditions is met, and then run the steps for the condition:
- <dl class="switch">
- <dt>There're non-zero number of bytes in <a>readDataBuffer</a></dt>
- <dd>
- <ol>
- <li>
- Pop the bytes from <a>readDataBuffer</a>, and then let <var>readBytes</var> be the popped bytes
- <section class="note">
- Implementations may choose to pop only part of bytes readable if it helps reducing memory copy.
- </section>
- </li>
- <li>Let <var>readData</var> be an object of the type specified by <var>latchedType</var> which represents <var>readBytes</var></li>
- <li>Let <var>amountConsumed</var> be the number of the popped bytes</li>
- </ol>
- </dd>
- <dt>Anything that doesn't represent bytes in <a>readDataBuffer</a> is encountered</dt>
- <dd>
- <ol>
- <li>Reject <var>readPromise</var> with an "<code><a>InvalidStateError</a></code>"</li>
- <li>Terminate these steps</li>
- </ol>
- </dd>
- </dl>
- </dd>
- <dt>Otherwise</dt>
- <dd>
- <ol>
- <li>Wait until <a>readDataBuffer</a> becomes non-empty or <a>eofReached</a> is set</li>
- <li>
- <dl class="switch">
- <dt>If <var>latchedType</var> is "<code>none</code>"</dt>
- <dd>
- <ol>
- <li>Pop data from <a>readDataBuffer</a></li>
- <li>Let <var>readData</var> be <code>undefined</code></li>
- </ol>
- </dd>
- <dt>Otherwise</dt>
- <dd>
- <ol>
- <li>Pop data from <a>readDataBuffer</a></li>
- <li>Let <var>readData</var> be an object representing the data</li>
- <li>Let <var>amountConsumed</var> be the <a>cost</a> of the data</li>
- </ol>
- </dd>
- </dl>
- </li>
- </ol>
- </dd>
- </dl>
- </li>
-
- <li>Queue a task which runs the rest of this algorithm</li>
-
- <li>Let <var>result</var> be a newly-created <a>StreamReadResult</a>.</li>
- <li>Set <var>result</var>.<a href="#widl-StreamReadResult-data">data</a> to <var>readData</var></li>
- <li>Set <var>result</var>.<a href="#widl-StreamReadResult-eof">eof</a> to <code>true</code> if <a>eofReached</a> is set and <a>readDataBuffer</a> is empty</li>
- <li>Set <var>result</var>.<a href="#widl-StreamReadResult-amountConsumed">amountConsumed</a> to <var>amountConsumed</var></li>
- <li>Set <var>result</var>.<a href="#widl-StreamReadResult-error">error</a> to <a>sourceErrorDetail</a></li>
-
- <li>Set <a>amountBeingReturned</a> to <var>amountConsumed</var></li>
-
- <li>Unset <a>readPending</a></li>
-
- <li>Fulfill <var>readPromise</var> with <var>result</var></li>
+ <li>Return <a>pendingRead</a>.<var>promise</var></li>
</ol>
</p>
@@ -1183,10 +1051,15 @@
This method must run the steps below:
<ol>
<li>Let <var>abortPromise</var> be a newly-created <a>Promise</a></li>
- <li>Return <var>abortPromise</var>, and then continue the process the steps in this algorithm</li>
- <li><a>Read-abort</a> <a>dataSource</a> with <var>reason</var></li>
- <li>Wait until <a>dataSource</a> acknowledges the read-abort</li>
- <li>Fulfill <var>abortPromise</var> with <code>undefined</code></li>
+ <li>
+ Run these steps asynchronously:
+ <ol>
+ <li><a>Read-abort</a> <a>dataSource</a> with <var>reason</var></li>
+ <li>Wait until <a>dataSource</a> acknowledges the read-abort</li>
+ <li>Fulfill <var>abortPromise</var> with <code>undefined</code></li>
+ </ol>
+ </li>
+ <li>Return <var>abortPromise</var></li>
</ol>
</p>
</dd>
@@ -1307,6 +1180,21 @@
</p>
<p>
+ A struct type <dfn>PendingReadDescriptor</dfn> has the following members:
+ <ul>
+ <li>A <a>Promise</a> <var>promise</var></li>
+ <li>An integer <var>amount</var></li>
+ <li>A <a>DOMString</a> <var>binaryAs</var></li>
+ <li>A <a>DOMString</a> <var>encoding</var></li>
+ </ul>
+ </p>
+
+ <p>
+ A WritableStream has an associated <a>PendingReadDescriptor</a> <dfn>pendingRead</dfn>.
+ This variable is initialized to <code>null</code>.
+ </p>
+
+ <p>
An associated flag <dfn>eofReached</dfn> which indicates that the EOF was received from the <a>dataSource</a>.
</p>
@@ -1325,12 +1213,151 @@
</p>
<p>
+ To <dfn>output data</dfn>, run these steps:
+
+ <ol>
+ <li>Let <var>result</var> be a newly-created <a>StreamReadResult</a></li>
+
+ <li>
+ <dl class="switch">
+ <dt>If <a>pendingRead<a>.<var>binaryAs</var> is "<code>as-is</code>"</dt>
+ <dd>
+ <dl class="switch">
+ <dt>If <a>pendingRead</a>.<var>size</var> is <code>undefined</code></dt>
+ <dd>
+ <ol>
+ <li>Pop one element from <a>readDataBuffer</a>, and set <var>result</var>.<a href="#widl-StreamReadResult-data">data</a> to the element</li>
+ <li>Let <var>amountConsumed</var> be <a>cost</a> of the element</li>
+ </ol>
+ </dd>
+ <dt>Otherwise</dt>
+ <dd>Reject <var>pendingRead.promise</var> with a "<code><a>SyntaxError</a></code>"</dd>
+ </dl>
+ </dd>
+
+ <dt>Otherwise</dt>
+ <dd>
+ <ol>
+ <li>Let <var>temporaryBuffer</var> be an empty queue</li>
+ <li>Let <var>remainingSize</var> be <code>undefined</code></li>
+ <li>If <a>pendingRead</a>.<var>size</var> is <code>undefined</code>, set <var>remainingSize</var> to <var>pendingRead.size</var></li>
+ <li>
+ <dl class="switch">
+ <dd>
+ Repeat these steps while <a>readDataBuffer</a> is not empty:
+ <ol>
+ <li>Let <var>head</var> be the first element in <a>readDataBuffer</a></li>
+ <li>
+ <dl class="switch">
+ <dt>If <var>remainingSize</var> is 0</dt>
+ <dd>
+ Exit from this loop
+ </dd>
+ <dt>If <var>head</var> is not an object representing binary data</dt>
+ <dd>
+ <ol>
+ <li>Reject <var>pendingRead.promise</var> with an "<code><a>InvalidStateError</a></code>"</li>
+ <li>Exit from this loop</li>
+ </ol>
+ </dd>
+ <dt>If <var>remainingSize</var> is <code>undefined</code></dt>
+ <dd>
+ <ol>
+ <li>Pop <var>head</var> from <a>readDataBuffer</a></li>
+ <li>Push <var>head</var> to <var>temporaryBuffer</var></li>
+ </ol>
+
+ <section class="note">
+ Implementations may choose to pop only part of bytes readable if it helps reducing memory copy.
+ </section>
+ </dd>
+ <dt>If <var>remainingSize</var> is not <code>undefined</code> and <a>cost</a> of <var>head</var> is not greater than <var>remainingSize</var></dt>
+ <dd>
+ <ol>
+ <li>Pop <var>head</var> from <a>readDataBuffer</a></li>
+ <li>Push <var>head</var> to <var>temporaryBuffer</var></li>
+ <li>Set <var>remainingSize</var> to <var>remainingSize</var> - (<a>cost</a> of <var>head</var>)</li>
+ </ol>
+ </dd>
+ <dt>Otherwise</dt>
+ <dd>
+ <ol>
+ <li>Split <var>head</var> into two elements <var>first</var> and <var>last</var> where size of <var>first</var> is <var>remainingSize</var></li>
+ <li>Replace <var>head</var> in <a>readDataBuffer</a> with <var>last</var></li>
+ <li>Push <var>first</var> to <var>temporaryBuffer</var></li>
+ <li>Set <var>remainingSize</var> to 0</li>
+ </ol>
+ </dd>
+ </dl>
+ </li>
+ </ol>
+ </dd>
+ <dt>Otherwise</dt>
+ <dd>
+
+ </dd>
+ </dl>
+ </li>
+
+ <li>
+ <dl class="switch">
+ <dt>If <a>pendingRead</a>.<var>binaryAs</var> is any of "<code>arraybuffer</code>" or "<code>blob</code>"</dt>
+ <dd>
+ <ol>
+ <li>Set <var>result</var>.<a href="#widl-StreamReadResult-data">data</a> to an object of the type specified by <var>pendingRead.binaryAs</var> that represents binary data stored in <var>temporaryBuffer</var></li>
+ <li>Let <var>amountConsumed</var> be the number of bytes in <var>temporaryBuffer</var></li>
+ </ol>
+ </dd>
+ <dt>If <a>pendingRead</a>.<var>binaryAs</var> is "<code>text</code>"</dt>
+ <dd>
+ <ol>
+ <li>Set <var>result</var>.<a href="#widl-StreamReadResult-data">data</a> to a DOMString that is the result of decoding as many bytes in <var>temporaryBuffer</var> as possible using <var>pendingRead.encoding</var></li>
+ <li>Let <var>unusedBytes</var> be the bytes in <var>temporaryBuffer</var> which were not used in the step 1</li>
+ <li>If <a>eofReached</a> is set and <var>unusedBytes</var> is not empty, reject <var>pendingRead.promise</var> with "<code><a>EncodingError</a></code>"</li>
+ <li>Prepend <var>unusedBytes</var> to <a>readDataBuffer</a></li>
+ <li>Let <var>amountConsumed</var> be the number of bytes in <var>temporaryBuffer</var> used in the step 1</li>
+ </ol>
+ </dd>
+ <dt>If <a>pendingRead</a>.<var>binaryAs</var> is "<code>none</code>"</dt>
+ <dd>
+ <ol>
+ <li>Set <var>result</var>.<a href="#widl-StreamReadResult-data">data</a> to <code>undefined</code></li>
+ <li>Let <var>amountConsumed</var> be the number of bytes in <var>temporaryBuffer</var></li>
+ </ol>
+ </dd>
+ </dl>
+ </li>
+ <li>Clear <var>temporaryBuffer</var></li>
+ </ol>
+ </dd>
+ </dl>
+ </li>
+
+ <li>Set <var>result</var>.<a href="#widl-StreamReadResult-size">size</a> to <var>amountConsumed</var></li>
+ <li>Set <var>result</var>.<a href="#widl-StreamReadResult-eof">eof</a> to <code>true</code> if <a>readDataBuffer</a> is empty and <a>eofReached</a> is set</li>
+ <li>Set <var>result</var>.<a href="#widl-StreamReadResult-error">error</a> to <a>sourceErrorDetail</a></li>
+
+ <li>Set <a>amountBeingReturned</a> to <var>amountConsumed</var></li>
+
+ <li>Set <a>readUpToPullAmount</a> to 0</li>
+
+ <li>Let <var>readPromise</var> to <var>pendingRead.promise</var></li>
+ <li>Set <a>pendingRead</a> to null</li>
+ <li>Fulfill <var>readPromise</var> with <var>result</var></li>
+ </ol>
+ </p>
+
+ <p>
When data is received from <a>dataSource</a>, queue a task which runs the steps below:
<ol>
<li>Let <var>receivedData</var> be the received bytes</li>
<li>Let <var>receivedAmount</var> be the size of <var>receivedData</var></li>
<li>Set <a>amountRequested</a> to <a>amountRequested</a> - <var>receivedAmount</var></li>
<li>Push <var>receivedData</var> to <a>readDataBuffer</a></li>
+
+ <li>
+ If <a>pendingRead</a> is not null, <a>output data</a>
+ </li>
</ol>
</p>