--- a/preview.html Wed Dec 04 00:59:38 2013 +0900
+++ b/preview.html Wed Dec 04 02:42:45 2013 +0900
@@ -1,1549 +1,166 @@
-<!DOCTYPE html>
-
-<html>
-
-<head>
- <title>Streams API (Preview version)</title>
- <meta content="text/html;charset=utf-8" http-equiv="Content-Type">
-
- <!-- <script class=remove src="http://dev.w3.org/2009/dap/ReSpec.js/js/respec.js"></script> -->
- <script class="remove" src="https://www.w3.org/Tools/respec/respec-w3c-common"></script>
- <!-- <script class="remove" src="respec-w3c-common.js"></script> -->
-
- <script class="remove">
-var respecConfig = {
- // specification status (e.g. WD, LCWD, NOTE, etc.). If in doubt use ED.
- specStatus: "ED",
-
- // the specification's short name, as in http://www.w3.org/TR/short-name/
- shortName: "streams-api",
-
- // if your specification has a subtitle that goes below the main
- // formal title, define it here
- // subtitle : "an excellent document",
-
- // if you wish the publication date to be other than today, set this
- // publishDate: "yyyy-mm-dd",
-
- // if the specification's copyright date is a range of years, specify
- // the start date here:
- // copyrightStart: "2005"
-
- // if there is a previously published draft, uncomment this and set its YYYY-MM-DD date
- // and its maturity status
- // previousPublishDate: "yyyy-mm-dd",
- // previousMaturity: "WD",
-
- // if there a publicly available Editor's Draft, this is the link
- edDraftURI: "http://dvcs.w3.org/hg/streams-api/raw-file/tip/Overview.htm",
-
- // if this is a LCWD, uncomment and set the end of its review period
- // lcEnd: "2009-08-05",
-
- // if you want to have extra CSS, append them to this list
- // it is recommended that the respec.css stylesheet be kept
- //extraCSS: ["http://dev.w3.org/2009/dap/ReSpec.js/css/respec.css",
- // "http://www.w3.org/StyleSheets/TR/W3C-ED.css",
- // ],
-
- // editors, add as many as you like
- // only "name" is required
-
- localBiblio: {
- "EncodingDetermination": {
- title: "Encoding",
- href: "http://encoding.spec.whatwg.org/",
- authors: ["Anne van Kesteren", "Joshua Bell"],
- publisher: "WHATWG"
- }
- },
-
- editors: [
- { name: "Feras Moussa", url: "mailto:feras.moussa@hotmail.com",
- company: "Invited Expert", },
- { name: "Takeshi Yoshino", url: "mailto:tyoshino@google.com",
- company: "Google, Inc.", },
- ],
-
- // authors, add as many as you like.
- // This is optional, uncomment if you have authors as well as editors.
- // only "name" is required. Same format as editors.
-
- //authors: [
- // { name: "Your Name", url: "http://example.org/",
- // company: "Your Company", companyURL: "http://example.com/" },
- //],
-
- // name of the WG
- wg: "W3C Web Applications (WebApps)",
-
- // URI of the public WG page
- wgURI: "http://www.w3.org/2008/webapps/",
-
- // name (with the @w3c.org) of the public mailing to which comments are due
- wgPublicList: "public-webapps",
-
- // URI of the patent status for this WG, for Rec-track documents
- // !!!! IMPORTANT !!!!
- // This is important for Rec-track documents, do not copy a patent URI from a random
- // document unless you know what you're doing. If in doubt ask your friendly neighbourhood
- // Team Contact.
- wgPatentURI: "",
-};
-</script>
-
- <!-- Styles to mimic File API spec -->
- <!-- <style type="text/css"> -->
- <!-- table.error { border-collapse:collapse; border-style:hidden hidden none hidden } -->
- <!-- table.error thead { border-bottom:solid } -->
- <!-- table.error tbody th:first-child { border-left:solid } -->
- <!-- table.error td, table th { border-left:solid; border-right:solid; border-bottom:solid thin; vertical-align:top; padding:0.2em } -->
- <!-- </style> -->
-
-</head>
-<body>
-
- <section id="sotd">
- <p>
- This document is not complete.
- It is subject to major changes and, while early experimentations are encouraged, it is therefore not intended for implementation.
- </p>
-
- <p>
- To check recent changes and rationale for them, please visit <a href="https://dvcs.w3.org/hg/streams-api/">Mercurial history</a>.
- Check open bugs at Bugzilla using <a href="https://www.w3.org/Bugs/Public/buglist.cgi?component=Streams%20API">this link</a>.
- If you wish to submit a bug, please use <a href="https://www.w3.org/Bugs/Public/enter_bug.cgi?product=WebAppsWG&component=Streams%20API">this link</a>.
- All comments and bug reports are welcome.
- </p>
- </section>
-
- <section id="abstract">
- <section class="note">
- This spec has now been moved out of preview and to the editor draft located <a href="http://dvcs.w3.org/hg/streams-api/raw-file/tip/Overview.htm">here</a>. This document has been left here temporarily, and will be removed at some point in the future.
- </section>
-
- <p>
- This specification provides an API for representing a byte stream in web applications, as well as programmatically reading and writing it.
- This includes:
- </p>
- <ul>
- <li>
- An interface named <a>WritableByteStream</a> which defines a general protocol for data consuming APIs (<a href="#consumers">consumers</a>) to communicate with data producing code (<a href="#producers">producers</a>).
- </li>
- <li>
- An interface named <a>ReadableByteStream</a> which defines a general protocol for data producing APIs to communicate with data consuming code.
- </li>
- <li>
- An interface named <a>ByteStream</a> which inherits both WritableByteStream and ReadableByteStream and represents a byte sequence.
- </li>
- <li>
- A tuple named <a>ByteStreamReadResult</a> which represents the result of consuming operations such as <code>read()</code> and <code>pipe()</code>.
- It holds a chunk of content read from a <a>ReadableByteStream</a>, the number of bytes consumed, and EOF signal.
- </li>
- <li>
- An enum <a>ByteStreamReadType</a> which represents data types as which data can be read from a <a>ReadableByteStream</a>.
- </li>
- <li>
- A list of notable byte stream <a href="#producers">producers</a> and <a href="#consumers">consumers</a> for which we can apply either or both of <a>ReadableByteStream</a> and <a>WritableByteStream</a> model.
- </li>
- <li>
- Extensions to <a href="http://dev.w3.org/2006/webapi/XMLHttpRequest-2/#the-xmlhttprequest-interface">XMLHttpRequest</a> [[!XMLHTTPREQUEST2]] to add support for uploading data via <a>WritableByteStream</a> and downloading a response as a <a>ReadableByteStream</a>.
- </li>
- <li>
- Extensions to <a href="http://dev.w3.org/2006/webapi/FileAPI/#dfn-createObjectURL">URL.createObjectURL</a> and
- <a href="http://dev.w3.org/2006/webapi/FileAPI/#dfn-revokeObjectURL">URL.revokeObjectURL</a> to add support for <a>ReadableByteStream</a>.
- </li>
- </ul>
-
- <p>
- This API is designed to be used in conjunction with other APIs and elements on the web platform, notably:
- <a href="http://dev.w3.org/2006/webapi/FileAPI">File</a> [[!FILE-API]],
- <a href="http://dev.w3.org/2006/webapi/XMLHttpRequest-2">XMLHttpRequest</a>
- (e.g. with an overloaded <a href="http://dev.w3.org/2006/webapi/XMLHttpRequest-2/#the-send-method"><code>send()</code></a> method
- and <a href="http://dev.w3.org/2006/webapi/XMLHttpRequest-2/#the-responsetype-attribute"><code>response</code></a> object for <a>ReadableByteStream</a> objects) [[!XMLHTTPREQUEST2]],
- <a href="http://dev.w3.org/html5/postmsg/#dom-window-postmessage"><code>postMessage</code></a>, and
- Web Workers [[!WEBWORKERS]].
- </p>
- </section>
-
- <section id="introduction" class="section informative">
- <h2>Introduction</h2>
-
- <p>
- Web applications should have the ability to acquire, manipulate, and pass data in a wide variety of forms, including as a sequence of data made available over time.
- This specification defines the basic representation for byte streams, and programmatic ways to read and write streams of data and errors raised on those operations.
- </p>
-
- <p>
- The <a>WritableByteStream</a> interface defines a general protocol for <a href="#consumers">data consuming APIs</a> to communicate with data producing code. In these cases, the data consuming API, such as a decoder, provides a <a>WritableByteStream</a> for other applications to write to, enabling the decoder to begin decoding data as it becomes available. The data is written to the internal data sink of a data consuming API using:
- <ul>
- <li>The <code>write()</code> method for writing bytes to the data sink as a <a>ArrayBufferView</a>, <a>DOMString</a> or <a>Blob</a></li>
- <li>The <code>awaitSpaceAvailable()</code> method for allowing a data-producer to write to the stream only when a data-consumer specifies it is now available to consume more data. This is useful for cases where an app may want to avoid backpressure and filling the internal buffer.</li>
- </ul>
- Actual transfer of bytes to the data sink may happen either synchronously or asynchronously.
- <a>WritableByteStream</a> hides the details of actual communication with the data sink while allowing for an efficient transfer of bytes.
- </p>
-
- <p>
- The <a>ReadableByteStream</a> interface defines a general protocol for <a href="#producers">data producing APIs</a> to communicate with data consuming code.
- This interface represents the potential for an infinite amount of bytes which are obtained over time and read once.
- Data consuming code reads data from the data source inside a data producing API using:
- <ul>
- <li>The <code>read()</code> and <code>readExact()</code> methods for reading bytes from the data source as a <a>ArrayBufferView</a>, <a>DOMString</a> or <a>Blob</a></li>
- <li>The <code>pullAmount</code> attribute to pace data retrieval from the data source</li>
- <li>The <code>pipe()</code> method for transferring data in bulk from the data source into the data sink of a <a>WritableByteStream</a> from another API</li>
- </ul>
- Actual transfer of bytes from the data source may happen either synchronously or asynchronously.
- <a>ReadableByteStream</a> hides the details of actual communication with the data source while allowing for an efficient transfer of bytes.
- </p>
-
- <p>
- With the combination of the following features, this interface suite responds to various simple and complex needs of byte stream handling.
- <ul>
- <li>Delayed notification of completion by using <a>Promise</a>s</li>
- <li>Explicit back pressure management by propagating room for consumption back to producers</li>
- <li><a>WritableByteStream</a> always accepts incoming data synchronously</li>
- </ul>
- </p>
-
- <p>
- The <a>ByteStream</a> is a simple implementation of both the <a>WritableByteStream</a> and <a>ReadableByteStream</a> interface.
- A ByteStream has a single queue of bytes and it works as a data sink for the WritableByteStream interface and as a data source for the ReadableByteStream interface.
- </p>
-
- <p>
- Read and write operations on these interfaces are implemented using <a>Promise</a>.
- When an operation completes, the Promise returned by a method will be fulfilled, and then the fulfill callback set to the Promise will handle the result.
- Error conditions that may arise during an operation will be handled by the reject callback set to the Promise.
- An example will be illustrative.
- </p>
-
- <p>
- In the example below, different code blocks handle progress, error, and success conditions.
- The example demonstrates how to read a chunk of data from a <a>ReadableByteStream</a> using <code>read()</code>.
- The <a>ReadableByteStream</a> may of come from a <a href="#producers">producer</a> such as <code>XMLHttpRequest</code>.
- Additionally, it demonstrates how to read a stream until an EOF is encountered.
- </p>
-
- <pre class="example">// Read up to 1024 bytes from the ReadableByteStream
-stream.readEncoding = "UTF-8";
-stream.readType = "arraybuffer";
-stream.read(1024).then(
- function (result) {
- // Process data
- },
- function (error) {
- // Handle error
- });</pre>
-
- <pre class="example">// Read data from the ReadableByteStream repeatedly
-function readUntilEof() {
- stream.read().then(
- function (result) {
- processData(result.data);
-
- if (!result.eof) {
- readUntilEof();
- }
- },
- function (error) {
- // Handle error
- });
-}
-
-readUntilEof();</pre>
-
- <p>
- In the example below, different code blocks handle progress, error, and success conditions.
- The example below demonstrates how to obtain a <a>ReadableByteStream</a> from <a>XMLHttpRequest</a> to begin playing a large video in <code>readystate</code> LOADING.
- The example takes the <a>ReadableByteStream</a> from a <a href="#producers">producer</a>, <a>XMLHttpRequest</a>, and gives it to a <a href="#consumers">consumer</a>, the video tag.
- </p>
-
- <pre class="example">function handler() {
- if(this.readyState == this.LOADING) {
- var theStream = this.response;
- var streamURL = URL.createObjectURL(theStream);
- document.getElementById("myVideoTag").src = streamURL;
- }
-}
-
-var client = new XMLHttpRequest();
-client.onreadystatechange = handler;
-client.setRequestHeader('customHeader', 'value');
-client.setRequestHeader('customHeader2', 'value2');
-client.open("GET", "myvideo.h264");
-client.responseType = "stream";
-client.send();</pre>
-
- <p>
- In addition to the <a>ReadableByteStream</a> interface, this specification introduces an interface called <a>WritableByteStream</a> for data consuming APIs.
- The <a>WritableByteStream</a> interface provides a <code>write()</code> method which allows applications to write data to a <a href="#consumers">data consuming API</a>.
- <code>write()</code> supports writing bytes represented as a <a>Blob</a>, <a>ArrayBuffer</a>, or <a>DOMString</a>.
- </p>
- <p>
- The example below demonstrates how to use <code>write()</code> to load a Stream into the audio tag, whose data could be processed and built dynamically at read time.
- </p>
-
- <pre class="example">var stream = new ByteStream("audio/mp3");
-
-function writeData() {
- // Do work to create more data to place into the stream
- var data = generateMusic();
-
- // If we have no more data to process and place in the stream, we close
- if (moreData == null){
- stream.writeClose();
- } else{
- // Wait until write() completes.
- stream.write(data).then(
- function () {
- writeData();
- },
- function (error) {
- // Handle error
- }
- );
- }
-}
-
-var streamURL = URL.createObjectURL(stream);
-document.getElementById('audioTag').src = streamURL;
-
-writeData();</pre>
-
- <p>
- An producer can also do work only when pulled by using <code>awaitSpaceAvailable()</code>, which will inform the producer when to produce data. This is useful when high-performance is necessary.
- </p>
-
- <pre class="example">function poll() {
- stream.awaitSpaceAvailable().then(
- function (pulledAmount) {
- stream.write(generateRandomBytes(pulledAmount));
- poll();
- }
- );
-}
-
-poll();</pre>
- </section>
-
- <section class="section" id="writableByteStream">
- <h2>WriteableByteStream Interface</h2>
- <p>
- The WritableByteStream interface defines a protocol for APIs which consume byte streams. The protocol includes:
- <ol>
- <li>How to receive the byte stream</li>
- <li>How to notify the writer of completion of writing</li>
- <li>How to notify the writer of how much data can be currently accepted</li>
- </ol>
-
- By returning a <a>Promise</a> and delaying fulfillment of it, the WritableByteStream realizes flow control.
- </p>
-
- <p>
- A WritableByteStream has an associated data sink identified by <dfn>dataSink</dfn>, which notifies the WritableByteStream of the number of bytes the data sink can newly accept.
- </p>
-
- <p>
- A WritableByteStream has a one-to-one mapping with the associated data sink, and has defined semantics for <a href='#interactingWithDataSink'>interacting with the data sink internally</a>.
- </p>
-
- <section class="section">
- <h3>WritableByteStream interface</h3>
-
- <dl class="idl" title="interface WritableByteStream">
- <dt>attribute DOMString writeEncoding</dt>
- <dd>
- <p>
- Specifies a <a>DOMString</a> that represents the label of an encoding [[!EncodingDetermination]].
- If set, it will be used as part of the encoding determination used when processing a <a>DOMString</a> provided in a <code>write()</code> method call.
- It will return the label last set, or the empty DOMString if never set.
- </p>
-
- <section class="note">
- This parameter is not designed to be specified as an argument of write() since it's not likely to be changed frequently.
- </section>
- </dd>
-
- <dt>Promise&lt;unsigned long long> write()</dt>
- <dd>
- <p>
- This method writes the specified <var>data</var> to the WritableByteStream.
- </p>
-
- <p>
- This method must run the steps below:
- <ol>
- <li>Let <var>latchedEncoding</var> be the current value of <a href="#widl-WritableByteStream-writeEncoding">writeEncoding</a></li>
-
- <li><a>Abort wait</a></li>
-
- <li>
- <dl class="switch">
- <dt>If <var>data</var> is a <a>Blob</a> or an <a>ArrayBufferView</a></dt>
- <dd>
- <ol>
- <li>Let <var>bytesToWrite</var> be the bytes represented by <var>data</var></li>
- </ol>
- </dd>
- <dt>Otherwise</dt>
- <dd>
- <ol>
- <li>If <var>data</var> is not a <a>DOMString</a>, let <var>data</var> be a DOMString representing <var>data</var></li>
- <li>Let <var>bytesToWrite</var> be the result of encoding <var>data</var> using <var>latchedEncoding</var></li>
- </ol>
- </dd>
- </dl>
- </li>
- <li>Let <var>numBytesToWrite</var> be the size of <var>bytesToWrite</var></li>
-
- <li>Let <var>writePromise</var> be a new <a>Promise</a></li>
-
- <li>Let <var>tuple</var> be a new <a>pendingWrite</a></li>
- <li>Set <var>writePromise</var> of <var>tuple</var> to <var>writePromise</var></li>
- <li>Set <var>size</var> of <var>tuple</var> to <var>numBytesToWrite</var></li>
- <li>Push <var>tuple</var> to <a>pendingWriteQueue</a></li>
-
- <li><a>Process pendingWriteQueue</a></li>
-
- <li>Return <var>writePromise</var>, and then continue to process the steps in this algorithm</li>
-
- <li>Write <var>bytesToWrite</var> to <a>dataSink</a></li>
- </ol>
- </p>
-
- <p>
- If <var>data</var> argument is an <a>ArrayBufferView</a>, modifications made on the ArrayBufferView's contents between <code>write()</code> method call and fulfill of the returned Promise may affect the data written to <a>dataSink</a>.
- </p>
-
- <dl class="parameters">
- <dt>(DOMString or ArrayBufferView or Blob) data</dt>
- <dd>Data to write.</dd>
- </dl>
- </dd>
-
- <dt>Promise&lt;unsigned long long> awaitSpaceAvailable()</dt>
- <dd>
- <p>
- This method waits until the WritableByteStream becomes able to accept any non-zero amount of data.
- The returned <a>Promise</a> will be fulfilled with the number of bytes the WritableByteStream can accept.
- </p>
-
- <p>
- This method must run the steps below:
- <ol>
- <li><a>Abort wait</a></li>
-
- <li>Set <a>waitPromise</a> to a new <a>Promise</a></li>
- <li>Return <a>waitPromise</a>, and then continue to process the steps in this algorithm</li>
- <li>Wait until <a>pendingWriteQueue</a> is empty and <a>bytesRequested</a> is not 0</li>
- <li>
- Queue a task to run the steps below:
- <ol>
- <li>If <a>waitPromise</a> is <code>null</code>, terminate these steps</li>
- <li>Let <var>detachedWaitPromise</var> be <a>waitPromise</a></li>
- <li>Set <a>waitPromise</a> to <code>null</code></li>
- <li>Fulfill <var>detachedWaitPromise</var> with <a>bytesRequested</a></li>
- </ol>
- </li>
- </ol>
- </p>
- </dd>
-
- <dt>void writeClose()</dt>
- <dd>
- <p>
- This method tells the WritableByteStream that no more data will be written to it.
- Once writeClose() has been called on a WritableByteStream, no further method calls can be made on the WritableByteStream.
- </p>
-
- <p>
- This method must write the EOF to <a>dataSink</a>.
- </p>
- </dd>
- </dl>
- </section>
-
- <section class="section">
- <h2>Data sink model</h2>
-
- <p>
- The data sink is the underlying mechanism in which a <a>WritableByteStream</a> interacts with and stores its data.
- </p>
-
- <p>
- A data sink to which the <a>WritableByteStream</a> interface writes bytes can be anything which:
- <ol>
- <li>Accepts bytes</li>
- <li>
- Can notify <a>WritableByteStream</a> of how much data the data sink can newly accept.
- When and how to generate such notifications is up to data sinks.
- Data sinks must be able to accept data more than it notified <a>WritableByteStream</a> of.
- </li>
- </ol>
- </p>
- </section>
-
- <section class="section" id='interactingWithDataSink'>
- <h2>Interacting with the data sink</h2>
-
- <p>
- This section defines the internal mechanisms for how the WritableByteStream interacts with the data sink. This section specifies both the internal properties as well as the algorithms for interaction with the data sink.
- </p>
-
- <p>
- A WritableByteStream has an associated integer variable <dfn>bytesRequested</dfn> which holds the number of bytes that can be written to the <a>dataSink</a>.
- This variable is initialized to 0 on construction.
- </p>
-
- <p>
- An associated <a>Promise</a> <dfn>waitPromise</dfn> which is used by the <code>awaitSpaceAvailable()</code> method.
- This variable is initialized to null on construction.
- </p>
-
- <p>
- To <dfn>abort wait</dfn>, run the steps below:
- <ol>
- <li>If <a>waitPromise</a> is <code>null</code>, terminate these steps</li>
- <li>Let <var>detachedWaitPromise</var> be <a>waitPromise</a></li>
- <li>Set <a>waitPromise</a> to <code>null</code></li>
- <li>Reject <var>detachedWaitPromise</var> with an "<code><a>AbortError</a></code>"</li>
- </ol>
- </p>
-
- <p>
- A struct type <dfn>pendingWrite</dfn> which has the following members:
- <ul>
- <li>A <a>Promise</a> <var>writePromise</var></li>
- <li>An integer <var>size</var></li>
- <li>An integer <var>bytesAcknowledged</var></li>
- </ul>
- </p>
- <p>
- An associated queue <dfn>pendingWriteQueue</dfn> which holds <a>pendingWrite</a>s.
- This queue is initialized to an empty queue on construction.
- </p>
-
- <p>
- To <dfn>process pendingWriteQueue</dfn>, repeat the steps below:
- <ol>
- <li>If <a>pendingWriteQueue</a> is empty, break from this loop</li>
- <li>Let <var>headTuple</var> be the head element of <a>pendingWriteQueue</a></li>
- <li>Let <var>bytesToAcknowledge</var> be min((<var>size</var> of <var>headTuple</var>) - (<var>bytesAcknowledged<var> of <var>headTuple</var>), <a>bytesRequested</a>)</li>
- <li>Set <a>bytesRequested</a> to <a>bytesRequested</a> - <var>bytesToAcknowledge</var></li>
- <li>Set <var>bytesAcknowledged</var> of <var>headTuple</var> to (<var>bytesAcknowledged</var> of <var>head</var>) + <var>bytesToAcknowledge</var></li>
- <li>
- If <var>bytesAcknowledged</var> of <var>headTuple</var> equals to <var>size</var> of <var>headTuple</var>, run the steps below:
- <ol>
- <li>Pop <var>headTuple</var> form <a>pendingWriteQueue</a></li>
- <li>If <var>writePromise</var> of <var>headTuple</var> is not <code>null</code>, fulfill it with <var>size</var> of <var>headTuple</var></li>
- </ol>
- </ol>
- </p>
-
- <p>
- When <a>dataSink</a> requests <var>bytesNewlyRequested</var> more bytes, queue a task which runs the steps below:
- <ol>
- <li>Set <a>bytesRequested</a> to <a>bytesRequested</a> + <var>bytesNewlyRequested</var></li>
- <li><a>Process pendingWriteQueue</a></li>
- </ol>
- </p>
- </section>
- </section>
-
- <section class="section" id="readableByteStream">
-
- <h2>ReadableByteSteam Interface</h2>
- <p>
- The ReadableByteStream interface defines a protocol for APIs which produce a byte stream. This protocol includes:
- <ol>
- <li>How to receive a read request from the reader and output bytes</li>
- <li>How to transfer data in bulk to another <a>WritableByteStream</a> (by using the <code>pipe()</code> method)</li>
- <li>How to mirror data to multiple destinations (by using the <code>fork()</code>)</li>
- </ol>
-
- By returning a <a>Promise</a> and delaying fulfillment of it, the ReadableByteStream realizes asynchronous data consumption.
- </p>
-
- <p>
- Interfaces introduced in this section provide simple and convenient ways to consume data.
- They connect arbitrary byte stream producer and byte stream consuming JavaScript code using Promises and method invocations.
- </p>
-
- <p>
- A ReadableByteStream has a one-to-one mapping with an associated data source, and has defined semantics for <a href='#interactingWithDataSource'>interacting with the data source internally</a>. A data source, however, can have a one-to-many relationship with ReadableByteStream, in cases where <code>fork()</code> is used.
- </p>
-
- <section class="section" id="readableByteStreamInterface">
- <h3>ReadableByteStream interface</h3>
-
-
- <dl class="idl" title="interface ReadableByteStream">
- <dt>readonly attribute DOMString type</dt>
- <dd>
- Returns the ASCII-encoded string in lower case representing the media type of the <code>Stream</code>,
- expressed as an RFC2046 MIME type [[!RFC2046]].
- Conforming user agents SHOULD return the MIME type of the <code>ReadableByteStream</code>, if it is known.
- If conforming user agents cannot determine the media type of the <code>ReadableByteStream</code>, they MUST return the empty string.
- A string is a valid MIME type if it matches the media-type token defined in section 3.7 "Media Types" of RFC 2616 [[!HTTP11]].
- </dd>
-
- <dt>attribute ByteStreamReadType readType</dt>
- <dd>
- <p>
- Specifies what data type will be returned by a <code>read()</code> and <code>readExact()</code> method call.
- This attribute can be set to any of the supported types in <a>ByteStreamReadType</a>.
- The default value for this attribute is "<code>arraybuffer</code>".
- </p>
- </dd>
-
- <dt>attribute DOMString readEncoding</dt>
- <dd>
- <p>
- Specifies a <a>DOMString</a> that represents the label of an encoding [[!EncodingDetermination]].
- If set, it will be used as part of the encoding determination used when processing a <code>read()</code> method call.
- </p>
-
- <section class="note">
- This parameter is not designed to be specified as an argument of <code>read()</code> since it's not likely to be changed frequently.
- </section>
- </dd>
-
- <dt>attribute unsigned long long pullAmount</dt>
- <dd>
- <p>
- This attribute provides ReadableByteStream with a hint of how many bytes the reader can consume currently.
- Each implementation of ReadableByteStream must initialize the value of pullAmount on construction.
- </p>
-
- <p>
- When this attribute is set, <a>retrieve bytes</a>.
- </p>
-
- <section class="note">
- This flow control functionality is provided as a separated attribute rather than as an argument of the read() method based on the assumption that this value is not changed frequently.
- </section>
- <section class="note">
- It's possible that the number of bytes received by <code>read()</code> is more than the pullAmount value.
- </section>
- </dd>
-
- <dt>Promise&lt;ByteStreamReadResult> readExact()</dt>
- <dd>
- <p>
- This method reads data from the ReadableByteStream.
- The returned Promise is fulfilled only when bytes of the specified size is read or the EOF is reached.
- The size of data read by this method is exactly the same as the specified size unless an EOF was reached, in which case there will be less bytes, which were the remaining bytes until the EOF.
- </p>
-
- <p>
- This method must run the steps below:
- <ol>
- <li>If <a href="#widl-ReadableByteStream-readType">readType</a> is "<code>text</code>" throw a "<code><a>SyntaxError</a></code>"</li>
-
- <li>If <a>readPending</a> is set, throw an "<code><a>InvalidStateError</a></code>"</li>
- <li>Set <a>readPending</a></li>
-
- <li>Let <var>latchedType</var> be the current value of <a href="#widl-ReadableByteStream-readType">readType</a></li>
- <li>Let <var>latchedEncoding</var> be the current value of <a href="#widl-ReadableByteStream-readEncoding">readEncoding</a></li>
-
- <li>Set <a>readExactPullAmount</a> to <var>size</var></li>
- <li>Set <a>numBytesBeingReturned</a> to 0</li>
-
- <li><a>Retrieve bytes</a></li>
-
- <li>Let <var>readPromise</var> be a new <a>Promise</a></li>
- <li>Return <var>readPromise</var>, and then continue to process the steps in this algorithm</li>
-
- <li>Wait until the number of bytes 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>numBytesReadable</var> be the number of bytes in <a>readDataBuffer</a></li>
- <li>Let <var>bytesToOutput</var> be min(<var>size</var>, <var>numBytesReadable</var>)</li>
- <li>Set <a>numBytesBeingReturned</a> to <var>bytesToOutput</var></li>
- <li>Pop <var>bytesToOutput</var> bytes from <a>readDataBuffer</a>, and then let <var>readBytes</var> be the popped bytes</li>
-
- <li>Set <a>readExactPullAmount</a> to 0</li>
-
- <li>Unset <a>readPending</a></li>
-
- <li>Let <var>result</var> be a new <a>ByteStreamReadResult</a></li>
- <li>
- <dl class="switch">
- <dt>If <var>latchedType</var> is "<code>none</code>"</dt>
- <dd>Set <a href="#widl-ByteStreamReadResult-data">data</a> of <var>result</var> to <code>undefined</code></dd>
- <dt>Otherwise</dt>
- <dd>Set <a href="#widl-ByteStreamReadResult-data">data</a> of <var>result</var> to an object of the type specified by <var>latchedType</var> which represents <var>readBytes</var></dd>
- </dl>
- </li>
- <li>Set <a href="#widl-ByteStreamReadResult-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 <a href="#widl-ByteStreamReadResult-size">size</a> of <var>result</var> to <var>bytesToOutput</var></li>
- <li>Fulfill <var>readPromise</var> with <var>result</var></li>
- </ol>
- </li>
- </ol>
- </p>
-
- <dl class="parameters">
- <dt>[Clamp] unsigned long long size</dt>
- <dd>Number of bytes to read.</dd>
- </dl>
-
- <section class="note">
- This method is useful if
- <ol>
- <li>You don't want to get notified of new data unless bytes of the specified number become available.</li>
- <li>You don't want to get your data fragmented into multiple parts, thus avoiding the need to buffer and combine chunks yourself.</li>
- </ol>
- </section>
- </dd>
-
- <dt>Promise&lt;ByteStreamReadResult> read()</dt>
- <dd>
- <p>
- This method reads data from the ReadableByteStream.
- The speed of reading can be roughly adjusted by using <a href="#widl-ByteStreamReadResult-pullAmount">pullAmount</a>.
- pullAmount doesn't necessarily limit the size of data being read by this method.
- </p>
-
- <p>
- This method must run the steps below:
-
- <ol>
- <li>If <a>readPending</a> is set, throw an "<code><a>InvalidStateError</a></code>"</li>
- <li>Set <a>readPending</a></li>
-
- <li>Let <var>latchedType</var> be the current value of <a href="#widl-ReadableByteStream-readType">readType</a> attribute</li>
- <li>Let <var>latchedEncoding</var> be the current value of <a href="#widl-ReadableByteStream-readEncoding">readEncoding</a> attribute</li>
-
- <li>Set <a>numBytesBeingReturned</a> to 0</li>
-
- <li><a>Retrieve bytes</a></li>
-
- <li>Let <var>readPromise</var> be a new <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>
- <ol>
- <li>
- Wait until bytes in <a>readDataBuffer</a> can be converted into a non-empty <a>DOMString</a> when decoded using <var>latchedEncoding</var> or <a>eofReached</a> is set
- </li>
- <li>
- Queue a task which runs the rest of this algorithm
- </li>
- <li>
- Pop non-zero number of bytes from <a>readDataBuffer</a> which can be fully converted into a non-empty <a>DOMString</a> when decoded using <var>latchedEncoding</var>, and then let <var>readBytes</var> be the result of the conversion.
- If <a>eofReached</a> is set and there are no such bytes, reject <var>readPromise</var> and terminate these steps.
- </li>
- <li>
- Let <var>readData</var> be the result of decoding <var>readBytes</var> using <var>latchedEncoding</var>.
- If this throws an <var>exception</var>, reject <var>readPromise</var> with <var>exception</var>.
- </li>
- </ol>
- </dd>
- <dt>Otherwise</dt>
- <dd>
- <ol>
- <li>Wait until <a>readDataBuffer</a> becomes non-empty or <a>eofReached</a> is set</li>
- <li>
- Queue a task which runs the rest of this algorithm
- </li>
- <li>
- Pop non-zero number of 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>
- <dl class="switch">
- <dt>If <var>latchedType</var> is "<code>none</code>"</dt>
- <dd>Let <var>readData</var> be <code>undefined</code></dd>
- <dt>Otherwise</dt>
- <dd>Let <var>readData</var> be an object of the type specified by <var>latchedType</var> which represents <var>readBytes</var></dd>
- </dl>
- </li>
- </ol>
- </dd>
- </dl>
- </li>
- <li>Let <var>bytesConsumed</var> be the size of <var>readBytes</var></li>
-
- <li>Let <var>result</var> be a new <a>ByteStreamReadResult</a>.</li>
- <li>Set <a href="#widl-ByteStreamReadResult-data">data</a> of <var>result</var> to <var>readData</var></li>
- <li>Set <a href="#widl-ByteStreamReadResult-eof">eof</a> of <var>result</var> to <code>true</code> if <a>eofReached</a> is set and <a>readDataBuffer</a> is empty</li>
- <li>Set <a href="#widl-ByteStreamReadResult-size">size</a> of <var>result</var> to <var>bytesConsumed</var>.</li>
-
- <li>Set <a>numBytesBeingReturned</a> to <var>bytesConsumed</var></li>
-
- <li>Unset <a>readPending</a></li>
-
- <li>Fulfill <var>readPromise</var> with <var>result</var></li>
- </ol>
- </p>
-
- <section class="note">
- This method is useful if
- <ol>
- <li>You don't care in what size and as how many fragments the data will be received</li>
- <li>You want to limit the number of bytes read for flow control</li>
- </ol>
- </section>
- </dd>
-
- <dt>Promise&lt;ByteStreamReadResult> pipe()</dt>
- <dd>
- <p>
- This method bulk transfers bytes from the ReadableByteStream to another <a>WritableByteStream</a>.
- </p>
-
- <section class="note">
- Fulfillment of the returned Promise doesn't necessarily mean that the data transferred to <var>destination</var> has been successfully read from it.
- </section>
-
- <section class="note">
- TODO: Rewrite this to update numBytesBeingReturned as bytesAcknowledged of pendingWrites are updated
- </section>
-
- <p>
- This method must run the steps below:
-
- <ol>
- <li>If <a>readPending</a> is set, throw an "<code><a>InvalidStateError</a></code>"</li>
- <li>Set <a>readPending</a></li>
-
- <li><a>Abort wait</a> <var>destination</var></a>
-
- <li>Set <a>numBytesBeingReturned</a> to 0</li>
-
- <li><a>Retrieve bytes</a></li>
-
- <li>Let <var>pipePromise</var> be a new <a>Promise</a></li>
- <li>Return <var>pipePromise</var>, and then continue to process the steps in this algorithm</li>
-
- <li>Let <var>totalBytesTransferred</var> be 0</li>
- <li>
- Repeat the steps below:
- <ul>
- <li>
- Whenever <a>readDataBuffer</a> is not empty or <a>eofReached</a> is set,
- <dl class="switch">
- <dt>If this happened in the event loop</dt>
- <dd>Run the steps below</dd>
- <dt>Otherwise</dt>
- <dd>Queue a task which runs the steps below</dd>
- </dl>
- <ol>
- <li>Let <var>numBytesReadable</var> be the number of bytes in <a>readDataBuffer</a></li>
- <li>
- <dl class="switch">
- <dt>If <var>size</var> is specified</dt>
- <dd>Let <var>bytesToTransfer</var> be min(<var>size</var> - <var>totalBytesTransferred</var>, <var>numBytesReadable</var>)</dd>
- <dt>Otherwise</dt>
- <dd>Let <var>bytesToTransfer</var> be <var>numBytesReadable</var></dd>
- </dl>
- </li>
- <li>Set <a>numBytesBeingReturned</a> to <a>numBytesBeingReturned</a> + <var>bytesToTransfer</var></li>
- <li>Pop <var>bytesToTransfer</var> bytes from <a>readDataBuffer</a>, and then write it to <a>dataSink</a> of <var>destination</var></li>
-
- <li>Let <var>tuple</var> be a new <a>pendingWrite</a></li>
- <li>Set <var>writePromise</var> of <var>tuple</var> to <code>null</code></li>
- <li>Set <var>size</var> of <var>tuple</var> to <var>bytesToTransfer</var></li>
- <li>Push <var>tuple</var> to <a>pendingWriteQueue</a> of <var>destination</var></li>
-
- <li>Set <var>totalBytesTransferred</var> to <var>totalBytesTransferred</var> + <var>bytesToTransfer</var></li>
-
- <li>
- <dl class="switch">
- <dt>If <a>eofReached</a> is set</dt>
- <dd>Break from this loop</dd>
- <dt>If <var>size</var> is specified and <var>totalBytesTransferred</var> equals to <var>size</var></dt>
- <dd>Break from this loop</dd>
- </dl>
- </li>
- </ol>
- </li>
- <li>
- Whenever <a>pendingWriteQueue</a> of <var>destination</var> is empty and <a>bytesRequested</a> of <var>destination</var> is not 0,
- <dl class="switch">
- <dt>If this happened in the event loop</dt>
- <dd>Run the steps below</dd>
- <dt>Otherwise</dt>
- <dd>Queue a task which runs the steps below</dd>
- </dl>
- <ol>
- <li>Let <var>bytesRequested</var> be <a>bytesRequested</a> of <var>destination</var></li>
- <li>
- <dl class="switch">
- <dt>If <var>size</var> is specified</dt>
- <dd>
- Set <a>pipePullAmount</a> to min(<var>size</var> - <var>totalBytesTransferred</var>, <var>bytesRequested</var>)
- <section class="note">
- If <a href="#widl-ReadableByteStream-pullAmount">pullAmount</a> is set to 0, pipe() transfers data in pull style.
- I.e. only bytes of the same number as the number of bytes writable to <var>destination</var> are retrieved from the data source.
- </section>
- <section class="note">
- Setting <a href="#widl-ReadableByteStream-pullAmount">pullAmount</a> to a small value doesn't have an effect of throttling the pace of pipe().
- </section>
- </dd>
- <dt>Otherwise</dt>
- <dd>Set <a>pipePullAmount</a> to <var>bytesRequested</var></dd>
- </dl>
- </li>
- <li>Set <a>numBytesBeingReturned</a> to 0</li>
- <li><a>Retrieve bytes</a></li>
- </ol>
- </li>
- </ul>
- </li>
-
- <li>Set <a>pipePullAmount</a> to 0</li>
-
- <li>Unset <a>readPending</a></li>
-
- <li>Let <var>result</var> be a new <a>ByteStreamReadResult</a></li>
- <li>Set <a href="#widl-ByteStreamReadResult-data">data</a> of <var>result</var> to <var>readData</var> to <code>undefined</code>.
- <li>Set <a href="#widl-ByteStreamReadResult-eof">eof</a> of <var>result</var> to <code>true</code> if <a>the EOF is reached</a></li>
- <li>Set <a href="#widl-ByteStreamReadResult-size">size</a> of <var>result</var> to <var>totalBytesTransferred</var></li>
- <li>
- Fulfill <var>readPromise</var> with <var>result</var>
- <section class="note">
- At this point, <a>numBytesBeingReturned</a> is not yet reset
- </section>
- </li>
- </ol>
- </p>
-
- <dl class="parameters">
- <dt>WritableByteStream destination</dt>
- <dd>Destination <a>WritableByteStream</a>.</dd>
- <dt>optional [Clamp] unsigned long long size</dt>
- <dd>Number of bytes to transfer.</dd>
- </dl>
- </dd>
-
- <dt>ReadableByteStream fork()</dt>
- <dd>
- <p>
- This method creates a new ReadableByteStream which refers to the same <a>dataSource</a> as the current ReadableByteStream.
- Data sources are range reference counted so that a range in a data source is freed only when all the ReadableByteStreams sharing the data source finish consuming it.
- </p>
-
- <p>
- This method must run the steps below:
- <ol>
- <li>Let <var>branch</var> be a new ReadableByteStream which refers to <a>dataSource</a> and has the same <a>numBytesRequested</a> value, <a>readDataBuffer</a> contents and <a>eofReached</a> value as the current ReadableByteStream.</li>
- <li>If <a>numBytesRequested</a> is not 0, up to <a>numBytesRequested</a> bytes arriving in the future must be forwarded to <var>branch</var>.</li>
- <li>Return <var>branch</var>.</li>
- </ol>
- </p>
- </dd>
-
- <dt>void readClose()</dt>
- <dd>
- <p>
- This method tells the ReadableByteStream that no more data will be read from it.
- </p>
- </dd>
- </dl>
- </section>
-
- <section class="section" id='readableByteStreamDataSource'>
- <h3>Data source model</h3>
-
- <p>
- A data source produces the bytes to be consumed via the <a>ReadableByteStream</a> interface instances. The data source model is not directly surfaced in the API, and is described here to provide details on how internal operations such as <a href="#widl-ReadableByteStream-fork-ReadableByteStream">fork()</a> can be handled.
- </p>
-
- <p>
- A <dfn>data source</dfn> from which <a>ReadableByteStream</a> retrieves bytes can be anything that:
- <ol>
- <li>Produces bytes</li>
- <li>
- Receives retrieval requests for generation of bytes from a <a>ReadableByteStream</a> and replies to it with the newly produced bytes.
- Interpretation of the request is up to data sources.
- Data sources may respond to retrieval requests with data larger than requested.
- Data sources may produce bytes and send to <a>ReadableByteStream</a> unsolicitedly without receiving any retrieval request.
- </li>
- </ol>
- </p>
-
- <p>
- To allow multiple consumers, we use a wrapper <dfn>data source wrapper</dfn> for range reference counting on produced bytes.
- A <a>data source wrapper</a> has the following functionalities:
- <ul>
- <li>has a <var>queue</var> to which newly produced bytes are pushed</li>
- <li>has a sorted map <dfn>cursorMap</dfn> whose key is reader ID and value is integer called cursor</li>
- <li>can issue reader IDs which are unique to the <a>data source wrapper</a> instance when requested</li>
- <li>pops bytes from <var>queue</var> when the smallest cursor in <a>cursorMap</a> by the difference of the new smallest cursor and the old smallest cursor</li>
- <li>when there's not sufficient bytes in <var>queue</var> to respond to coming retrieval request, retrieves bytes from the wrapped data source</li>
- </ul>
- </p>
-
- <p>
- When <a href="#widl-ReadableByteStream-fork-ReadableByteStream">fork()</a> is called, a new reader is registered to the original <a>ReadableByteStream</a>'s data source and the new <a>ReadableByteStream</a> uses read() method to fetch data from it.
- </p>
- </section>
-
- <section class="section" id="interactingWithDataSource">
- <h2>Interacting with the data source</h2>
-
- <section class="note">
- This interface is designed to work even if operations on <a>dataSource</a> are asynchronous.
- If <a>dataSource</a> is synchronously accessible, some of the algorithms can be simplified.
- </section>
-
- <p>
- A ReadableByteStream has an associated <a>data source</a> referred by <dfn>dataSource</dfn> from which the ReadableByteStream retrieves bytes.
- The data source model is explained in <a href="#h2_data_source">this section</a>.
- A data source can be shared by multiple ReadableByteStream instances when <code>fork()</code> is used.
- A ReadableByteStream is registered with a data source on construction and given a reader ID.
- The <a>dataSource</a> of a ReadableByteStream refers to its data source, and <dfn>readerId</dfn> of a ReadableByteStream refers to its reader ID.
- </p>
-
- <p>
- A ReadableByteStream has the following internal mechanisms:
- </p>
-
- <p>
- An associated flag <dfn>readPending</dfn> which prevents multiple read operations from being run.
- This flag is set to false on construction.
- </p>
-
- <p>
- An associated integer variable <dfn>readExactPullAmount</dfn> which temporarily overrides <a href="#widl-ReadableByteStream-pullAmount">pullAmount</a> if necessary for a <code>readExact()</code> method call.
- This variable is initialized to 0 on construction.
- </p>
- <p>
- An associated integer variable <dfn>pipePullAmount</dfn> which temporarily overrides <a href="#widl-ReadableByteStream-pullAmount">pullAmount</a> if necessary for a <code>pipe()</code> method call.
- This variable is initialized to 0 on construction.
- </p>
-
- <p>
- An associated integer variable <dfn>numBytesRequested</dfn> which holds the number of bytes being retrieved from the <a>dataSource</a>.
- This variable is initialized to 0 on construction.
- </p>
- <p>
- An associated integer variable <dfn>numBytesBeingReturned</dfn> which holds the number of bytes consumed on the last read operation.
- This variable is initialized to 0 on construction.
-
- <section class="note">
- numBytesBeingReturned delays replenishment of pullAmount until the next read()/pipe() operation is made.
- </section>
- </p>
-
- <p>
- An associated queue <dfn>readDataBuffer</dfn> which holds the bytes retrieved from <a>dataSource</a>.
- This queue is initialized to an empty queue on construction.
- <section class="note">
- Retrieved bytes can be queued in <a>readDataBuffer</a> in any form.
- For example, if bytes were retrieved as <a>ArrayBufferView</a> fragments, it's ok to store them as-is to avoid unnecessary copy.
- If the object representing retrieved bytes is a DOMString, that should be accompanied with the encoding to use to decode it.
- </section>
- </p>
-
- <p>
- An associated flag <dfn>eofReached</dfn> which indicates that the EOF was received from the <a>dataSource</a>.
- </p>
-
- <p>
- To <dfn>retrieve bytes</dfn>, run the steps below:
- <ol>
- <li>Let <var>numBytesReadable</var> be the number of bytes in the <a>readDataBuffer</a></li>
- <li>Let <var>numBytesToRetrieve</var> be max(max(<a href="#widl-ReadableByteStream-pullAmount">pullAmount</a>, <a>readExactPullAmount</a>, <a>pipePullAmount</a>) - (<a>numBytesRequested</a> + <var>numBytesReadable</var> + <a>numBytesBeingReturned</a>), 0)</li>
- <li>Set <a>numBytesRequested</a> to <a>numBytesRequested</a> + <var>numBytesToRetrieve</var></li>
- <li>Send a request to the <a>dataSource</a> to return <var>numBytesToRetrieve</var> bytes to the ReadableByteStream</li>
- </ol>
- </p>
-
- <p>
- When bytes are received from <a>dataSource</a>, queue a task which runs the steps below:
- <ol>
- <li>Let <var>bytesReceived</var> be the received bytes</li>
- <li>Let <var>numBytesReceived</var> be the size of <var>bytesReceived</var></li>
- <li>Set <a>numBytesRequested</a> to <a>numBytesRequested</a> - <var>numBytesReceived</var></li>
- <li>Push <var>bytesReceived</var> to <a>readDataBuffer</a></li>
- </ol>
- </p>
-
- <p>
- When the EOF is received from <a>dataSource</a>, queue a task which sets <a>eofReached</a>.
- </p>
-
- </section>
- </section>
-
- <section class="section">
- <h2>ByteStreamReadResult Interface</h2>
-
- <p>
- This interface represents the result of methods on <a>ReadableByteStream</a>.
- </p>
-
- <dl class="idl" title="interface ByteStreamReadResult">
- <dt>readonly attribute boolean eof</dt>
- <dd>Set if the operation resulted in an EOF</dd>
- <dt>readonly attribute any data</dt>
- <dd>The contents read converted into an object of the specified type</dd>
- <dt>readonly attribute unsigned long long size</dt>
- <dd>The size, in bytes, of the data read</dd>
- </dl>
- </section>
-
- <section class="section">
- <h2>ByteStreamReadType enum</h2>
-
- <p>
- Data can be read as various data types from <a>ReadableByteStream</a>.
- This enum defines <a>DOMString</a> values to specify the data types.
- </p>
-
- <dl class="idl" title="enum ByteStreamReadType">
- <dt>blob</dt>
- <dd>Read operations should return data as a <a>Blob</a></dd>
- <dt>arraybuffer</dt>
- <dd>Read operations should return data as an <a>ArrayBuffer</a></dd>
- <dt>text</dt>
- <dd>Read operations should return data as a <a>DOMString</a></dd>
- <dt>none</dt>
- <dd>
- Read operations should return nothing.
- Useful for seeking data by skipping some amount of data.
- User agents may implement some optimization for "<code>none</code>" type read for example omitting internal data transfer.
- </dd>
- </dl>
- </section>
-
- <section class="section" id="streams">
- <h2>ByteStream</h2>
-
- <p>
- This section introduces a simple implementation of the <a>WritableByteStream</a> and <a>ReadableByteStream</a> named <code>ByteStream</code>, as well as accompanying interfaces required as part of the <a>ByteStream</a> implementation.
- This includes a constructor to build a <a>ByteStream</a> object and the type attribute.
- </p>
-
- <section class="section" id="stream-interface">
- <h2>ByteStream Interface</h2>
-
- <p>
- This interface represents a sequence of bytes which can be read only once over time and to which we can push data.
- </p>
-
- <p>
- A ByteStream has an associated <dfn>bufferedDataQueue</dfn>.
- The buffer can be stored in memory or backed by slower devices such as a disk.
- </p>
-
- <p>
- The ByteStream inherits the <a>WritableByteStream</a> interface.
- Its <a>dataSink</a> is <a>bufferedDataQueue</a> wrapped with a <a>data source wrapper</a>.
- </p>
-
- <p>
- The ByteStream inherits the <a>ReadableByteStream</a> interface.
- Its <a>dataSource</a> is also <a>bufferedDataQueue</a>.
- </p>
-
- <p>
- <a>bufferedDataQueue</a> just forwards retrieval requests coming from the <a>data source wrapper</a> to the <a>WritableByteStream</a> as a notification of the number of newly acceptable bytes with the same amount.
- </p>
-
- <dl class="idl" title="interface ByteStream : ReadableByteStream, WritableByteStream">
- <dt>Constructor()</dt>
- <dd>
- Constructs a <a>ByteStream</a> and sets the <a href="#widl-ByteStream-type">type</a> to the specified value.
-
- <dl class="parameters">
- <dt>in unsigned long long pullAmount</dt>
- <dd>
- Specifies the initial value of <a href="#widl-ReadableByteStream-pullAmount">pullAmount</a>.
- </dd>
- <dt>in optional DOMString type</dt>
- <dd>
- Specifies the MIME type [[!RFC2046]] of the <a>ByteStream</a>.
- </dd>
- </dl>
- </dd>
- </dl>
- </section>
-
- <section class="section" id="error-uris_for_streams">
- <h3>URIs for Stream</h3>
- <p>
- To reference a <a>ByteStream</a>, <a href="http://dev.w3.org/2006/webapi/FileAPI/#url">the same URI used</a> for <code>Blobs</code> and <code>Files</code> in
- <a href="http://dev.w3.org/2006/webapi/FileAPI/#url">6.7. A URI for Blob and File reference</a> of
- the File API specification should be used. [[!FILE-API]]
- The definitions of <strong>Origin</strong>, <strong>Lifetime</strong>, <strong>Referencing</strong>, and <strong>Dereferencing</strong> of a <code>Blob</code> should be applied to a <a>ByteStream</a>.
- </p>
-
- <section class="section" id="creating-revoking-streamuri">
- <h4>Creating and Revoking a Stream URI</h4>
- <p>
- A <dfn id="stream-uri">Stream URI</dfn> is a <code>Blob URI</code> that is referencing a <a>ReadableByteStream</a>.
- These URIs are created and revoked using methods exposed on the URL object,
- as defined in <a href="http://dev.w3.org/2006/webapi/FileAPI/#creating-revoking">6.7.5. Creating and Revoking a Blob URI</a>
- of the File API specification. [[!FILE-API]]
- </p>
- <p>
- <a href="http://dev.w3.org/2006/webapi/FileAPI/#dfn-createObjectURL">URL.createObjectURL</a>
- and <a href="http://dev.w3.org/2006/webapi/FileAPI/#dfn-revokeObjectURL">URL.revokeObjectURL</a>
- should both be extended as follows:
- </p>
- <dl class="idl" title="interface URL">
- <dt>static DOMString? createObjectURL(in (Blob or ReadableByteStream) object)</dt>
- <dd>
- <p>
- The extension onto <code>createObjectURL</code> should have the following steps added.
- </p>
- <p>
- Returns a unique Blob URL each time it is called on a valid <code>object</code> argument, which is a non-null <a>ReadableByteStream</a> in scope of the global object's URL property from which this static method is called. This method must act as follows:
- <ol>
- <li>
- If called with a <a>ReadableByteStream</a> argument that is NOT valid, then user agents must return null.
- </li>
- <li>
- If called with a valid <a>ReadableByteStream</a> argument,
- user agents must run the following sub-steps:
- <ol>
- <li>
- If <a>readPending</a> of the <a>ReadableByteStream</a> is set, return null.
- </li>
- <li>
- Set <a>readPending</a> of the <a>ReadableByteStream</a>.
- </li>
- <li>
- Return a unique <code>Blob URI</code> that can be used to dereference the <code>stream</code> argument.
- </li>
- <li>
- Add an entry to the Blob URL Store for this Blob URL.
- </li>
- </ol>
- </li>
- </ol>
- </p>
- </dd>
-
- <dt>static DOMString? createFor(in (Blob or ReadableByteStream) object)</dt>
- <dd>
- <p>
- The extension onto <code>createFor</code> should have the following steps added.
- </p>
- <p>
- Returns a unique Blob URL each time it is called on a valid <code>object</code> argument, which is a non-null <a>ReadableByteStream</a> in scope of the global object's URL property from which this static method is called. Blob URLs created with this method are said to be auto-revoking since user-agents are responsible for the revocation of Blob URLs created with this method, subject to the lifetime stipulation for Blob URLs. This method must act as follows:
- <ol>
- <li>
- If called with a <a>ReadableByteStream</a> argument that is NOT valid, then user agents must return null.
- </li>
- <li>
- If called with a valid <a>ReadableByteStream</a> argument,
- user agents must run the following sub-steps:
- <ol>
- <li>
- If <a>readPending</a> of the <a>ReadableByteStream</a> is set, return null.
- </li>
- <li>
- Set <a>readPending</a> of the <a>ReadableByteStream</a>.
- </li>
- <li>
- Return a unique <code>Blob URI</code> that can be used to dereference the <code>stream</code> argument.
- </li>
- <li>
- Add an entry to the Blob URL Store for this Blob URL.
- </li>
- <li>
- Add an entry in the Revocation List for this Blob URL.
- </li>
- </ol>
- </li>
- </ol>
- </p>
- </dd>
-
- <dt>static void revokeObjectURL(in DOMString url)</dt>
- <dd>
- <p>
- The extension onto <code>revokeObjectURL</code> should have the following steps added.
- </p>
- <ol>
- <li>
- If the URL refers to a <a>Blob</a> or <a>ReadableByteStream</a> that is both
- valid and in the same origin of the global object’s <code>URL</code> property on which this static method was called,
- user agents MUST return a 404 response code when the URL is dereferenced.
- </li>
- <li>
- If the URL refers to a <a>Blob</a> or <a>ReadableByteStream</a> that is <strong>not</strong> valid
- or if the value provided for the URL argument is not a <code>Blob URI</code>
- or if the URL argument refers to a <a>Blob</a> or <a>ReadableByteStream</a> that is <strong>not</strong> in the same origin
- as the global object’s<code>URL</code> property, this method call does nothing.
- User agents MAY display a message on their error console.
- </li>
- </ol>
- </dd>
- </dl>
- </section>
- </section>
- </section>
-
- <section class="section" id="producers-consumers">
- <h2>Stream Consumers and Producers</h2>
- <p>
- Streams can be both produced and consumed by various APIs. APIs which create streams are identified as producers, and ones which read and act on a stream are known as consumers. This section identifies some of the APIs where Streams may be produced and consumed.
- <section class="note">The list of producers and consumers below is not an exhaustive list. It is placed here as informative for the time being.</section>
- </p>
- <section class="section" id="consumers">
- <h2>Stream Consumers</h2>
- <p>This section outlines APIs which can consume a Stream object</p>
- <ul>
- <li>Web Audio</li>
- <li>Media Source Extensions</li>
- <li>Web Cryptography API</li>
- <li>TextEncoder</li>
- <li>TextDecoder</li>
- <li>WebSockets</li>
- <li>RTCPeerConnection</li>
- </ul>
- </section>
-
- <section class="section" id="producers">
- <h2>Stream Producers</h2>
- <p>This section outlines APIs which can produce a Stream object</p>
- <ul>
- <li>XMLHttpRequest</li>
- <li>FileReader</li>
- <li>Media Capture</li>
- <li>MediaStream Recording API</li>
- <li>Indexed Database</li>
- <li>Web Cryptography API</li>
- <li>TextEncoder</li>
- <li>TextDecoder</li>
- <li>WebSockets</li>
- <li>EventSource</li>
- <li>RTCPeerConnection</li>
- </ul>
- </section>
- </section>
-
- <section class="section" id="security">
- <h2>Security Considerations</h2>
- <p>
- A <a>ReadableByteStream</a> should have the same security considerations as a <code>Blob</code>.
- This is outlined in <a href="http://dev.w3.org/2006/webapi/FileAPI/#security-discussion">6.8. Security Considerations</a>
- of the File API specification. [[!FILE-API]]
- Because a <a>ReadableByteStream</a> uses a <code>Blob URI</code>, cross origin requests on a <a>ReadableByteStream</a> will not be supported.
- </p>
- </section>
-
- <section class="section" id="XMLHttpRequest">
- <h2>Extension of XMLHttpRequest</h2>
- <p>
- This specification proposes an extension to <code>XMLHttpRequest</code> [[!XMLHTTPREQUEST2]] to add support for <a>ByteStream</a>. This section is temporary and is meant to provide a recommendation for how <a>ByteStream</a> should be incorporated into <code>XMLHttpRequest</code>.
- This will extend <code>XMLHttpRequest</code> to allow for receiving and uploading of a <a>ByteStream</a>.
- One such scenario is providing access to data during <a href="http://dev.w3.org/2006/webapi/XMLHttpRequest-2/#dom-xmlhttprequest-readystate"><code>readyState</code></a> 3 (LOADING).
- The sections below document in detail what extensions must be done to <code>XMLHttpRequest</code> to support <a>ByteStream</a>.
- </p>
-
- <section class="section" title="addition-of-stream-response-entity">
- <h3>Addition of stream response entity body</h3>
- <p>
- <a href="https://dvcs.w3.org/hg/xhr/raw-file/tip/Overview.html#response-entity-body-0">The section named "Response Entity Body"</a>
- in XMLHttpRequest specification [[!XMLHTTPREQUEST2]] should have the following additions:
- </p>
- <p>
- The <dfn id="stream-response-entity">stream response entity body</dfn> is either a <a>ByteStream</a> representing the <a href="https://dvcs.w3.org/hg/xhr/raw-file/tip/Overview.html#response-entity-body">response entity body</a> or null.
- If the <a href="#stream-response-entity">stream response entity body</a> is null, let it be the return value of the following algorithm:
- </p>
- <ol>
- <li>
- If the <a href="https://dvcs.w3.org/hg/xhr/raw-file/tip/Overview.html#response-entity-body">response entity body</a> is null,
- return an empty <a>ByteStream</a> object.
- </li>
- <li>
- Return a <a>ByteStream</a> object representing the <a href="https://dvcs.w3.org/hg/xhr/raw-file/tip/Overview.html#response-entity-body">response entity body</a>.
- </li>
- </ol>
- </section>
-
- <section class="section" title="addition-of-stream">
- <h3>Addition of "<code>stream</code>" responseType</h3>
- <p>
- A new value for the <code>responseType</code> attribute "<code>stream</code>" should be introduced.
- </p>
- <p>
- In the IDL list in <a href="https://dvcs.w3.org/hg/xhr/raw-file/tip/Overview.html#interface-xmlhttprequest">the section named "Interface XMLHttpRequest"</a> in XMLHttpRequest specification [[!XMLHTTPREQUEST2]], the definition of <code>XMLHttpRequestResponseType</code> enum should now read:
- <pre>
-enum XMLHttpRequestResponseType {
- "",
- "arraybuffer",
- "blob",
- "stream",
- "document",
- "json",
- "text"
-}</pre>
- </p>
- </section>
-
- <section class="section" title="modification-on-response-algorithm">
- <h3>Modification on the <code>response</code> attribute</h3>
- <p>
- The algorithm of the <code>response</code> attribute should be modified to handle the new <code>responseType</code> value "<code>stream</code>".
- A Stream is binary data obtained sequentially over time.
- Given this, a <a>ByteStream</a> should be accessible in <a href="https://dvcs.w3.org/hg/xhr/raw-file/tip/Overview.html#dom-xmlhttprequest-readystate"><code>readyState</code></a> 3 (LOADING).
- </p>
- <p>
- <a href="http://dev.w3.org/2006/webapi/XMLHttpRequest-2/#the-response-attribute">The section named "The response attribute"</a> in XMLHttpRequest specification [[!XMLHTTPREQUEST2]] should now read:
- </p>
- <p>
- The <code>response</code> attribute must return the result of running these steps:
- </p>
- <dl class="switch">
- <dt>If <a href="http://dev.w3.org/2006/webapi/XMLHttpRequest-2/#dom-xmlhttprequest-responsetype"><code>responseType</code></a> is the empty string or "<code>text</code>"</dt>
- <dd>
- The same as the original XMLHttpRequest specification.
- </dd>
- <dt>If <a href="https://dvcs.w3.org/hg/xhr/raw-file/tip/Overview.html#dom-xmlhttprequest-responsetype"><code>responseType</code></a> is "<code>stream</code>"</dt>
- <dd>
- <ol>
- <li>
- If the state is not <a href="https://dvcs.w3.org/hg/xhr/raw-file/tip/Overview.html#dom-xmlhttprequest-loading">LOADING</a> or
- <a href="https://dvcs.w3.org/hg/xhr/raw-file/tip/Overview.html#dom-xmlhttprequest-done">DONE</a>, return null.
- </li>
- <li>
- If the <a href="https://dvcs.w3.org/hg/xhr/raw-file/tip/Overview.html#error-flag">error flag</a> is set, return null.
- </li>
- <li>
- Return the <a href="#stream-response-entity">stream response entity body</a>.
- </li>
- </ol>
- </dd>
- <dt>Otherwise</dt>
- <dd>
- The same as the original XMLHttpRequest specification.
- </dd>
- </dl>
- </section>
-
- <section class="section" id="modification-on-send-algorithm">
- <h3>send()</h3>
- <p>
- The switch in otherwise case of step 4 of
- <a href="https://dvcs.w3.org/hg/xhr/raw-file/tip/Overview.html#the-send()-method">The section named "The <code>send()</code> method"</a>
- in XMLHttpRequest specification [[!XMLHTTPREQUEST2]] should have the following additions:
- </p>
- <dl class="switch">
- <dt><a>ReadableByteStream</a></dt>
- <dd>
- <p>
- If the object's <a href="#widl-ByteStream-type">type</a> attribute is not the empty string let <var>mime type</var> be its value.
- </p>
- <p>
- Set <a>readPending</a> of the <a>ReadableByteStream</a>.
- </p>
- <p>
- Let the <a href="https://dvcs.w3.org/hg/xhr/raw-file/tip/Overview.html#request-entity-body">request entity body</a> be the raw data represented by <var>data</var>.
- </p>
- </dd>
- </dl>
- </section>
- </section>
-
- <section class="section" id="terminology">
- <h2>Terminology</h2>
-
- <p>
- <dfn>ArrayBuffer</dfn> and <dfn>ArrayBufferView</dfn> are defined in <a href="http://www.khronos.org/registry/typedarray/specs/latest/">Typed Array specification</a>.
- </p>
-
- <p>
- <dfn>Blob</dfn> is defined in <a href="http://dev.w3.org/2006/webapi/FileAPI/">File API specification</a>.
- </p>
-
- <p>
- <dfn>Promise</dfn> is defined in <a href="https://github.com/domenic/promises-unwrapping/blob/master/README.md">Promise Objects specification</a>.
- </p>
-
- <p>
- <dfn>DOMString</dfn> is defined in <a href="http://www.w3.org/TR/DOM-Level-3-Core/core.html">DOM Level 3 Core specification</a>.
- </p>
-
- <p>
- <dfn>XMLHttpRequest</dfn> is defined in [[!XMLHTTPREQUEST2]].
- </p>
-
- <p>
- <dfn>AbortError</dfn> is defined in <a href="https://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#aborterror">DOM4 specification</a>.
- <dfn>InvalidStateError</dfn> is defined in <a href="https://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#invalidstateerror">DOM4 specification</a>.
- <dfn>SyntaxError</dfn> is defined in <a href="https://dvcs.w3.org/hg/domcore/raw-file/tip/Overview.html#syntaxerror">DOM4 specification</a>.
- </p>
- </section>
-
- <section class="section" id="requirements">
- <h2>Requirements and Use Cases</h2>
- <p>
- The <a>ByteStream</a> type allows for completion of several end-to-end experiences. This section covers what the requirements are for this API, and
- illustrates some use cases.
- </p>
- <ul>
- <li>
- Begin loading a video through <code>XMLHttpRequest</code> in <code>readyState</code> LOADING
- <p>
- Videos can typically be large files that may take a long time to download, and require authentication or certain headers to access.
- For certain video formats, an application can begin playing the video once the first chunks of data are available, and would not need to wait for the entire video to download.
- </p>
- </li>
- <li>
- Begin processing the data of a <a>ByteStream</a> as it is being read via <code>XMLHttpRequest</code>
- <p>
- If a file format is understood, then an application can make sense of the data as it being made available. For example, a given
- file may be very large and the application wants to begin processing the data immediately, rather than having to wait for full download of the file.
- </p>
- </li>
- <li>
- Upload of dynamic runtime data using <a>ByteStream</a> and <code>XMLHttpRequest</code>
- <p>
- There are situations where an application may have data to upload once the application is processing. This could involve processing
- of data an application wants to upload as it is being created. One such case is the upload of GPS coordinates within an application. The
- coordiantes may constantly change, and the application wants to upload the data as it being collected.
- </p>
- </li>
- <li>
- Media streaming scenarios using <a>ByteStream</a> and <code>XMLHttpRequest</code>
- <p>
- Media streaming scenarios require the ability to quickly receive data over the network and connect it to a media element. An application can successfully accomplish this by receiving a Stream in <code>readyState</code> LOADING and assign it to a media element. This helps avoid the application from having to buffer the data prior to assigning it to a media element.
- </p>
- </li>
- </ul>
- </section>
-
- <section class=appendix>
- <h2>Acknowledgements</h2>
- <p>
- Thanks to Eliot Graff for editorial assistance.
- Special thanks to the W3C.
- The editor would like to thank
- Anne van Kesteren,
- Austin William Wright,
- Aymeric Vitte,
- Domenic Denicola,
- Elliott Sprehn,
- Isaac Schlueter,
- Jonas Sicking,
- Kenneth Russell,
- Kinuko Yasuda,
- Michael Davidson,
- Taiju Tsuiki,
- Yusuke Suzuki,
- Yutaka Hirano,
- Adrian Bateman,
- Harris Syed,
- Lindsay Verola
- for their contributions to this specification.
- </p>
- </section>
-
-</body>
-</html>
+<!DOCTYPE html>
+<html lang="en" dir="ltr">
+<head>
+ <title>Streams API (Preview version)</title>
+ <meta content="text/html;charset=utf-8" http-equiv="Content-Type">
+
+<style>/*****************************************************************
+ * ReSpec 3 CSS
+ * Robin Berjon - http://berjon.com/
+ *****************************************************************/
+
+/* --- INLINES --- */
+em.rfc2119 {
+ text-transform: lowercase;
+ font-variant: small-caps;
+ font-style: normal;
+ color: #900;
+}
+
+h1 acronym, h2 acronym, h3 acronym, h4 acronym, h5 acronym, h6 acronym, a acronym,
+h1 abbr, h2 abbr, h3 abbr, h4 abbr, h5 abbr, h6 abbr, a abbr {
+ border: none;
+}
+
+dfn {
+ font-weight: bold;
+}
+
+a.internalDFN {
+ color: inherit;
+ border-bottom: 1px solid #99c;
+ text-decoration: none;
+}
+
+a.externalDFN {
+ color: inherit;
+ border-bottom: 1px dotted #ccc;
+ text-decoration: none;
+}
+
+a.bibref {
+ text-decoration: none;
+}
+
+cite .bibref {
+ font-style: normal;
+}
+
+code {
+ color: #ff4500;
+}
+
+/* --- TOC --- */
+.toc a, .tof a {
+ text-decoration: none;
+}
+
+a .secno, a .figno {
+ color: #000;
+}
+
+ul.tof, ol.tof {
+ list-style: none outside none;
+}
+
+.caption {
+ margin-top: 0.5em;
+ font-style: italic;
+}
+
+/* --- TABLE --- */
+table.simple {
+ border-spacing: 0;
+ border-collapse: collapse;
+ border-bottom: 3px solid #005a9c;
+}
+
+.simple th {
+ background: #005a9c;
+ color: #fff;
+ padding: 3px 5px;
+ text-align: left;
+}
+
+.simple th[scope="row"] {
+ background: inherit;
+ color: inherit;
+ border-top: 1px solid #ddd;
+}
+
+.simple td {
+ padding: 3px 10px;
+ border-top: 1px solid #ddd;
+}
+
+.simple tr:nth-child(even) {
+ background: #f0f6ff;
+}
+
+/* --- DL --- */
+.section dd > p:first-child {
+ margin-top: 0;
+}
+
+.section dd > p:last-child {
+ margin-bottom: 0;
+}
+
+.section dd {
+ margin-bottom: 1em;
+}
+
+.section dl.attrs dd, .section dl.eldef dd {
+ margin-bottom: 0;
+}
+</style><style>/* --- ISSUES/NOTES --- */
+div.issue-title, div.note-title {
+ padding-right: 1em;
+ min-width: 7.5em;
+ color: #b9ab2d;
+}
+div.issue-title { color: #e05252; }
+div.note-title { color: #2b2; }
+div.issue-title span, div.note-title span {
+ text-transform: uppercase;
+}
+div.note, div.issue {
+ margin-top: 1em;
+ margin-bottom: 1em;
+}
+.note > p:first-child, .issue > p:first-child { margin-top: 0 }
+.issue, .note {
+ padding: .5em;
+ border-left-width: .5em;
+ border-left-style: solid;
+}
+div.issue, div.note {
+ padding: 1em 1.2em 0.5em;
+ margin: 1em 0;
+ position: relative;
+ clear: both;
+}
+span.note, span.issue { padding: .1em .5em .15em; }
+
+.issue {
+ border-color: #e05252;
+ background: #fbe9e9;
+}
+.note {
+ border-color: #52e052;
+ background: #e9fbe9;
+}
+
+
+</style><link rel="stylesheet" href="https://www.w3.org/StyleSheets/TR/W3C-ED"><!--[if lt IE 9]><script src='https://www.w3.org/2008/site/js/html5shiv.js'></script><![endif]--></head>
+<body style="" role="document" id="respecDocument">
+
+ <section id="abstract" class="introductory" property="dcterms:abstract" datatype="" typeof="bibo:Chapter" resource="#ref" rel="bibo:Chapter"><h2 aria-level="1" role="heading" id="h2_abstract">Streams API (Preview version)</h2><p>
+ <div class="note"><div class="note-title" aria-level="2" role="heading" id="h_note_1"><span>Note</span></div><section class="">
+ This spec has now been moved out of preview and to the editor draft located <a href="http://dvcs.w3.org/hg/streams-api/raw-file/tip/Overview.htm">here</a>. This document has been left here temporarily, and will be removed at some point in the future.
+ </section></div>
+ </p></section>
+
+
+
+</body></html>