Overview.htm
author Takeshi Yoshino <tyoshino@google.com>
Fri, 10 Jan 2014 21:43:59 +0900
changeset 126 be34c357de7f
parent 125 98448480356b
child 127 bf65397910b7
permissions -rw-r--r--
Rewording
<!DOCTYPE html>

<html>

<head>
	<title>Streams API</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">
		<p>
			This specification provides an API for representing a stream of data in web applications, as well as programmatically reading and writing it.
			This includes:
		</p>
		<ul>
			<li>
				An interface named <a>WritableStream</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>ReadableStream</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 WritableStream and ReadableStream and represents a sequence of data.
			</li>
			<li>
				A struct type named <a>StreamReadResult</a> which represents the result of consuming operations such as <code>read()</code> and <code>pipe()</code>.
				It holds:
				<ul>
					<li>Chunk of content read from a <a>ReadableStream</a></li>
					<li>The total cost of the chunk</li>
					<li>EOF signal</li>
					<li>Error info</li>
				</ul>
			</li>
			<li>
				An enum <a>StreamReadType</a> which represents data types as which data can be read from a <a>ReadableStream</a>.
			</li>
			<li>
				A list of notable data <a href="#producers">producers</a> and <a href="#consumers">consumers</a> for which we can apply either or both of <a>ReadableStream</a> and <a>WritableStream</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>WritableStream</a> and downloading a response as a <a>ReadableStream</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>ReadableStream</a>.
			</li>
		</ul>

		<p>
			This API is designed to be used in conjunction with other APIs and elements on the web platform, notably:
			<ul>
				<li><a href="http://dev.w3.org/2006/webapi/FileAPI">FileAPI</a> [[!FILE-API]]</li>
				<li>
					<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>ReadableStream</a> objects) [[!XMLHTTPREQUEST2]].
				</li>
				<li><a href="http://dev.w3.org/html5/postmsg/#dom-window-postmessage"><code>postMessage</code></a></li>
				<li>Web Workers [[!WEBWORKERS]]</li>
			</ul>
		</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 streams of data, and programmatic ways to read and write streams of data and errors raised on those operations.
		</p>

		<p>
			The <a>WritableStream</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>WritableStream</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 inside the data consuming API using:
			<ul>
				<li>
					The <code>write()</code> method which writes the given data to the data sink
				</li>
				<li>
					The <code>awaitSpaceAvailable()</code> method which allows a data producing code to write data to the data consuming API only when its data sink is available to consume more data.
					This is useful for cases where an app may want to avoid filling the internal buffer.
				</li>
			</ul>
			Actual transfer of data to the data sink may happen either synchronously or asynchronously.
			<a>WritableStream</a> hides the details of actual communication with the data sink while allowing for an efficient transfer of data.
		</p>

		<p>
			The <a>ReadableStream</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 data which are obtained over time and read once.
			Data consuming code reads data from the internal data source inside the data producing API using:
			<ul>
				<li>
					The <code>read()</code> and <code>readUpTo()</code> methods which reads data from the data source
				</li>
				<li>
					The <code>pullAmount</code> attribute which paces data retrieval from the data source
				</li>
				<li>
					The <code>pipe()</code> method which transfers data in bulk from the data source into the data sink of another API which implements <a>WritableStream</a>
				</li>
			</ul>
			Actual transfer of data from the data source may happen either synchronously or asynchronously.
			The <a>ReadableStream</a> hides the details of actual communication with the data source while allowing for an efficient transfer of data.
		</p>

		<p>
			With the combination of the following features, this interface suite responds to various simple and complex needs of data stream handling.
			<ul>
				<li>Delayed notification of completion by using <a>Promise</a>s. See below for more details.</li>
				<li>Explicit back pressure management by propagating room for consumption back to producers</li>
				<li><a>WritableStream</a> always accepts incoming data synchronously to bridge with legacy APIs that don't understand backpressure</li>
			</ul>
		</p>

		<p>
			The <a>ByteStream</a> is a simple implementation of both the <a>WritableStream</a> and <a>ReadableStream</a> interface.
			A ByteStream has a single queue of bytes which works as a data sink for the WritableStream interface and as a data source for the ReadableStream 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.
		</p>

		<p>
			Examples below will be illustrative.
		</p>

		<p>
			The example below demonstrates how to read a chunk of data from a <a>ReadableStream</a> using <code>read()</code>.
			The <a>ReadableStream</a> may of come from a <a href="#producers">producer</a> such as <code>XMLHttpRequest</code>.
		</p>

		<pre class="example">
// Tell stream that we're ready to consume 1024 bytes.
stream.pullAmount = 1024;
stream.readEncoding = "UTF-8";
stream.readBinaryAs = "arraybuffer";
stream.read().then(
  function (result) {
    // Process data
  },
  function (error) {
    // Handle error
  });</pre>

		<p>
			The example below demonstrates how to read bytes from a <a>ReadableStream</a> until an EOF is encountered.
		</p>

		<pre class="example">// Read data from the ReadableStream repeatedly
function readUntilEof() {
  stream.read().then(
    function (result) {
      processData(result.data);

      if (!result.eof) {
        readUntilEof();
      }
    },
    function (error) {
      // Handle error
    });
}

readUntilEof();</pre>

		<p>
			The example below demonstrates how to obtain a <a>ReadableStream</a> from <a>XMLHttpRequest</a> to begin playing a large video in <code>readystate</code> LOADING.
			The example takes the <a>ReadableStream</a> from a <a href="#producers">producer</a>, <a>XMLHttpRequest</a>, and gives it to a <a href="#consumers">consumer</a>, the video tag.
			If the consumer implements the <a>WritableStream</a> interface, we could use <code>pipe()</code> to transfer data to it instead of URL.
		</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>
			The example below demonstrates how to use <code>write()</code> to load a <a>ReadableStream</a> into the audio tag, whose data could be processed and built dynamically at read time.
			ByteStream in the example is a class which implements both <a>WritableStream</a> and <a>ReadableStream</a>.
			It accepts bytes generated by the code via <a>WritableStream</a> methods, and the written data will be consumed by the audio element via the object URL which is a part of <a>ReadableStream</a>'s functionality.
		</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>
			A producer can also do work only when pulled by using <code>awaitSpaceAvailable()</code>.
			This method informs the data producing code of that the data consuming API is ready to consume 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>

		<p>
			The example below demonstrates how the timing to pull new data is determined.
			When data of cost X is loaded and passed to the Promise, the <a>ReadableStream</a> marks X bytes of pullAmount as used.
			The next <code>read()</code> call automatically clears the mask to request the data source to produce X more data.
			If precise flow control is needed, you update pullAmount before the next <code>read()</code>.
			In the example, the producer API is requested to produce 16 bytes, and then in the fulfill callback, pullAmount is set to the remaining number of bytes not to let the API produce more data.
		</p>

		<pre class="example">stream.pullAmount = 16;
function read() {
  stream.read().then(
    function (result) {
      process(result);
      stream.pullAmount -= result.size;
      if (stream.pullAmount == 0) {
        // Done
      } else if (stream.eof) {
        // Done
      } else {
        read();
      }
    }
  );
}</pre>
	</section>

	<section class="section" id="writableByteStream">
		<h2>WritableStream Interface</h2>
		<p>
			The WritableStream 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 accepted currently</li>
			</ol>

			By returning a <a>Promise</a> and delaying fulfillment of it, the WritableStream realizes flow control.
		</p>

		<p>
			The actual data consumer behind the WritableStream is called a data sink and is identified by <dfn>dataSink</dfn>.
			A data sink consumes byte streams and notifies the WritableStream of the number of bytes the data sink can newly accept.
			For each data sink, it's defined how to calculate <a>cost</a> of each object which the data sink can consume.
		</p>

		<p>
			A WritableStream 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>WritableStream interface</h3>

			<dl class="idl" title="interface WritableStream">
				<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&amp;lt;unsigned long long&gt; write()</dt>
				<dd>
					<p>
						This method writes the specified <var>data</var> to the WritableStream.
					</p>

					<section class="note">
						<p>
							write() returns a Promise to make it easy for byte stream producing code to react to backpressure.
						</p>
					</section>

					<p>
						This method must run the steps below:
						<ol>
							<li>Let <var>latchedEncoding</var> be the current value of <a href="#widl-WritableStream-writeEncoding">writeEncoding</a></li>

							<li><a>Abort wait</a></li>

							<li>If <var>cost</var> argument is specified, let <var>amountToWrite</var> be <var>cost</var> argument. Otherwise, let <var>amountToWrite</var> be the <a>cost</a> of <var>data</var></li>

							<li>Let <var>writePromise</var> be a new <a>Promise</a></li>

							<li>Let <var>pendingWrite</var> be a new <a>PendingWriteDescriptor</a></li>
							<li>Set <var>pendingWrite.promise</var> to <var>writePromise</var></li>
							<li>Set <var>pendingWrite.amount</var> to <var>amountToWrite</var></li>
							<li>Push <var>pendingWrite</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>
								<dl class="switch">
									<dt>If <var>data</var> is a <a>DOMString</a></dt>
									<dd>
										Write <var>data</var> to <a>dataSink</a> together with <var>latchedEncoding</var> as <var>encoding</var> parameter.
										Interpretation of <var>latchedEncoding</var> is up to <a>dataSink</a>.
									</dd>
									<dt>Otherwise</dt>
									<dd>
										Write <var>data</var> to <a>dataSink</a>.
									</dd>
								</dl>
							</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>any data</dt>
						<dd>Data to write.</dd>
						<dt>optional [Clamp] unsigned long long cost</dt>
						<dd>Overrides <a>cost</a> of data.</dd>
					</dl>
				</dd>

				<dt>Promise&amp;lt;unsigned long long&gt; awaitSpaceAvailable()</dt>
				<dd>
					<p>
						This method waits until the WritableStream becomes able to accept any non-zero amount of data.
						The returned <a>Promise</a> will be fulfilled with the number of bytes the WritableStream can accept.
					</p>

					<p>
						This method must run the steps below:
						<ol>
							<li><a>Abort waiting</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>spaceAvailable</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>spaceAvailable</a></li>
								</ol>
							</li>
						</ol>
					</p>
				</dd>

				<dt>Promise&amp;lt;undefined&gt; writeClose()</dt>
				<dd>
					<p>
						This method tells the WritableStream that no more data will be written to it.
						Once writeClose() has been called on a WritableStream, no further method calls can be made on the WritableStream.
					</p>

					<p>
						This method must run the steps below:
						<ol>
							<li>Let <var>closePromise</var> be a new <a>Promise</a></li>
							<li>Return <var>closePromise</var>, and then continue the process the steps in this algorithm</li>
							<li>Write the EOF to <a>dataSink</a></li>
							<li>Wait until <a>dataSink</a> acknowledges the EOF</li>
							<li>Fulfill <var>closePromise</var> with <code>undefined</code></li>
						</ol>
					</p>
				</dd>

				<dt>Promise&amp;lt;undefined&gt; writeAbort(optional any reason)</dt>
				<dd>
					<p>
						This method tells the WritableStream that no more data will be written to it with indication of error.
						The details of the error will be given by <var>reason</var> argument.
						The interpretation of <var>reason</var> is up to <a>dataSink</a>.
						Once writeAbort() has been called on a WritableStream, no further method calls can be made on the WritableStream.
					</p>

					<p>
						This method must run the steps below:
						<ol>
							<li>Let <var>abortPromise</var> be a new <a>Promise</a></li>
							<li>Return <var>abortPromise</var>, and then continue the process the steps in this algorithm</li>
							<li><a>Write-abort</a> <a>dataSink</a> with <var>reason</var></li>
							<li>Wait until <a>dataSink</a> acknowledges the write-abort</li>
							<li>Fulfill <var>abortPromise</var> with <code>undefined</code></li>
						</ol>
					</p>
				</dd>
			</dl>
		</section>

		<section class="section">
			<h2>Data sink model</h2>

			<p>
				The data sink is the underlying mechanism which a <a>WritableStream</a> interacts with and stores its data in.
			</p>

			<p>
				A data sink to which the <a>WritableStream</a> interface writes bytes can be anything which:
				<ol>
					<li>
						Accepts data possibly together with a <a>DOMString</a> parameter named <var>encoding</var> indicating in what encoding the data must be interpreted.
					</li>
					<li>
						Accepts the EOF signal
					</li>
					<li>
						Accepts the write-abort signal with an object parameter named reason.
					</li>
					<li>
						Notifies <a>WritableStream</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>WritableStream</a> of.
					</li>
					<li>
						Notifies <a>WritableStream</a> of that the data sink is gone.
						This signal may mean an error.
						If it means an error, an object indicating the details of the error is attached.
					</li>
					<li>
						Notifies <a>WritableStream</a> of acknowledgement of the write-abort signal with error detail object.
					</li>
					<li>
						How to calculate an integer value <dfn>cost</dfn> of each object which the data sink can consume.
					</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 WritableStream interacts with <a>dataSink</a>.
				This section specifies both the internal properties as well as the algorithms.
			</p>

			<p>
				A WritableStream has an associated integer variable <dfn>spaceAvailable</dfn> which holds the number of bytes that <a>dataSink</a> requested but not yet written to it.
				This variable is initialized to 0 on construction.
			</p>

			<p>
				A WritableStream has an associated <a>Promise</a> <dfn>waitPromise</dfn> which is used by the <code>awaitSpaceAvailable()</code> method.
				This variable is initialized to <code>null</code> on construction.
			</p>

			<p>
				To <dfn>abort waiting</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>PendingWriteDescriptor</dfn> has the following members:
				<ul>
					<li>A <a>Promise</a> <var>promise</var></li>
					<li>An integer <var>amount</var></li>
					<li>An integer <var>ackedAmount</var></li>
				</ul>
			</p>

			<p>
				A WritableStream has an associated queue <dfn>pendingWriteQueue</dfn> which holds <a>PendingWriteDescriptor</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>pendingWrite</var> be the head element of <a>pendingWriteQueue</a></li>
					<li>
						<dl class="switch">
							<dt>If <a>sinkGone</a> is set</dt>
							<dd>Run the steps below:
								<ol>
									<li>Pop <var>pendingWrite</var> from <a>pendingWriteQueue</a>, and then</li>
									<li>If <var>pendingWrite.promise</var> is not <code>null</code>, reject it with <a>sinkErrorDetail</a></li>
								</ol>
							</dd>
							<dt>Otherwise</dt>
							<dd>Run the steps below:
								<ol>
									<li>Let <var>amountToAcknowledge</var> be min(<var>pendingWrite.amount</var> - <var>pendingWrite.ackedAmount</var>, <a>spaceAvailable</a>)</li>
									<li>Set <a>spaceAvailable</a> to <a>spaceAvailable</a> - <var>amountToAcknowledge</var></li>
									<li>Set <var>pendingWrite.ackedAmount</var> to <var>pendingWrite.ackedAmount</var> + <var>amountToAcknowledge</var></li>
									<li>
										If <var>pendingWrite.ackedAmount</var> equals to <var>pendingWrite.amount</var>, run the steps below:
										<ol>
											<li>Pop <var>pendingWrite</var> from <a>pendingWriteQueue</a></li>
											<li>If <var>pendingWrite.promise</var> is not <code>null</code>, fulfill it with <var>pendingWrite.amount</var></li>
										</ol>
									</li>
								</ol>
							</dd>
						</dl>
					</li>
				</ol>
			</p>

			<p>
				When <a>dataSink</a> requests <var>amountNewlyRequested</var> more data, queue a task which runs the steps below:
				<ol>
					<li>Set <a>spaceAvailable</a> to <a>spaceAvailable</a> + <var>amountNewlyRequested</var></li>
					<li><a>Process pendingWriteQueue</a></li>
				</ol>
			</p>

			<p>
				A WritableStream has an associated flag <dfn>sinkGone</dfn> which is set when the data sink is gone.
			</p>

			<p>
				A WritableStream has an associated object <dfn>sinkErrorDetail</dfn> which is initialized to null, and when the data sink is gone, set to the error detail object.
			</p>

			<p>
				When <a>dataSink</a> notifies the WritableStream of that the data sink is gone, queue a task which runs the steps below:
				<ol>
					<li>Set <a>sinkGone</a></li>
					<li>Set <a>sinkErrorDetail</a> to the error detail object</li>
					<li><a>Process pendingWriteQueue</a></li>
				</ol>
			</p>
		</section>
	</section>

	<section class="section" id="readableByteStream">
		<h2>ReadableStream Interface</h2>
		<p>
			The ReadableStream 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>WritableStream</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 ReadableStream 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 ReadableStream 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 ReadableStream, in cases where <code>fork()</code> is used.
		</p>

		<section class="section" id="readableByteStreamInterface">
			<h3>ReadableStream interface</h3>

			<dl class="idl" title="interface ReadableStream">
				<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>ReadableStream</code>, if it is known.
					If conforming user agents cannot determine the media type of the <code>ReadableStream</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 StreamReadType readBinaryAs</dt>
				<dd>
					<p>
						Specifies what data type will be returned by a <code>read()</code> and <code>readUpTo()</code> method call.
						This attribute can be set to any of the supported types in <a>StreamReadType</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 ReadableStream with a hint of how much data the reader can consume currently.
						Each implementation of ReadableStream must initialize the value of pullAmount on construction.
					</p>

					<p>
						When this attribute is set, <a>retrieve data</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&amp;lt;StreamReadResult&gt; 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.
					</p>

					<p>
						This method must run the steps below:
						<ol>
							<li>If <a href="#widl-ReadableStream-readBinaryAs">readBinaryAs</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-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>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 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 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 new <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>
						</ol>
					</p>

					<dl class="parameters">
						<dt>[Clamp] unsigned long long size</dt>
						<dd>Max 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&amp;lt;StreamReadResult&gt; read()</dt>
				<dd>
					<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.
					</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-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>amountBeingReturned</a> to 0</li>

							<li><a>Retrieve data</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>
										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 new <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>
						</ol>
					</p>

					<p>
						<img src="images/fulfilling.png" alt="How new data is automatically fetched">
					</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&amp;lt;StreamReadResult&gt; pipe()</dt>
				<dd>
					<p>
						This method bulk transfers bytes from the ReadableStream to another <a>WritableStream</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 <a>amountBeingReturned</a> as numBytesAcknowledged of <a>PendingWriteDescriptor</a>s 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>Run <a>abort waiting</a> algorithm on <var>destination</var></a>

							<li>Set <a>amountBeingReturned</a> to 0</li>

							<li><a>Retrieve data</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>totalAmountTransferred</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>readableAmount</var> be the number of bytes in <a>readDataBuffer</a>
												<section class="note">
													It's fine to process only part of the bytes, and process the rest in the next task.
												</section>
											</li>
											<li>
												<dl class="switch">
													<dt>If <var>size</var> is specified</dt>
													<dd>Let <var>amountToTransfer</var> be min(<var>size</var> - <var>totalAmountTransferred</var>, <var>readableAmount</var>)</dd>
													<dt>Otherwise</dt>
													<dd>Let <var>amountToTransfer</var> be <var>readableAmount</var></dd>
												</dl>
											</li>
											<li>Set <a>amountBeingReturned</a> to <a>amountBeingReturned</a> + <var>amountToTransfer</var></li>
											<li>Pop <var>amountToTransfer</var> bytes from <a>readDataBuffer</a>, and then write it to <a>dataSink</a> of <var>destination</var></li>

											<li>Let <var>pendingWrite</var> be a new <a>PendingWriteDescriptor</a></li>
											<li>Set <var>pendingWrite.promise</var> to <code>null</code></li>
											<li>Set <var>pendingWrite.amount</var> to <var>amountToTransfer</var></li>
											<li>Push <var>pendingWrite</var> to <a>pendingWriteQueue</a> of <var>destination</var></li>

											<li>Set <var>totalAmountTransferred</var> to <var>totalAmountTransferred</var> + <var>amountToTransfer</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>totalAmountTransferred</var> equals to <var>size</var></dt>
													<dd>Break from this loop</dd>
												</dl>
												<section class="note">
													Need to revisit. Finish when write to the destination completes?
												</section>
											</li>
										</ol>
									</li>
									<li>
										Whenever <a>pendingWriteQueue</a> of <var>destination</var> is empty and <a>spaceAvailable</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>destSpaceAvailable</var> be <a>spaceAvailable</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>totalAmountTransferred</var>, <var>destSpaceAvailable</var>)
														<section class="note">
															If <a href="#widl-ReadableStream-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-ReadableStream-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>destSpaceAvailable</var></dd>
												</dl>
											</li>
											<li>Set <a>amountBeingReturned</a> to 0</li>
											<li><a>Retrieve data</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>StreamReadResult</a></li>
							<li>Set <var>result</var>.<a href="#widl-StreamReadResult-data">data</a> to <code>undefined</code>.
							<li>Set <var>result</var>.<a href="#widl-StreamReadResult-eof">eof</a> to <code>true</code> if <a>eofReached</a></li>
							<li>Set <var>result</var>.<a href="#widl-StreamReadResult-amountConsumed">amountConsumed</a> to <var>totalAmountTransferred</var></li>
							<li>
								Fulfill <var>pipePromise</var> with <var>result</var>
								<section class="note">
									At this point, <a>amountBeingReturned</a> is not yet reset
								</section>
							</li>
						</ol>
					</p>

					<dl class="parameters">
						<dt>WritableStream destination</dt>
						<dd>Destination <a>WritableStream</a>.</dd>
						<dt>optional [Clamp] unsigned long long size</dt>
						<dd>Number of bytes to transfer.</dd>
					</dl>
				</dd>

				<dt>ReadableStream fork()</dt>
				<dd>
					<p>
						This method creates a new ReadableStream which refers to the same <a>dataSource</a> as the current ReadableStream.
						Data sources are range reference counted so that a range in a data source is freed only when all the ReadableStreams 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 ReadableStream which refers to <a>dataSource</a> and has the same <a>amountRequested</a> value, <a>readDataBuffer</a> contents and <a>eofReached</a> value as the current ReadableStream.</li>
							<li>If <a>amountRequested</a> is not 0, up to <a>amountRequested</a> bytes arriving in the future must be forwarded to <var>branch</var>.</li>
							<li>Return <var>branch</var>.</li>
						</ol>
					</p>
				</dd>

				<dt>Promise&amp;lt;undefined&gt; readAbort(optional any reason)</dt>
				<dd>
					<p>
						This method tells the ReadableStream that no more data will be read from it optionally with indication of error.
						The details of the error will be given by <var>reason</var> argument.
						The interpretation of <var>reason</var> is up to <a>dataSource</a>.
						Once readAbort() has been called on a ReadableStream, no further method calls can be made on the ReadableStream.
					</p>

					<p>
						This method must run the steps below:
						<ol>
							<li>Let <var>abortPromise</var> be a new <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>
						</ol>
					</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>ReadableStream</a> interface instances.
				A <a>ReadableStream</a> retrieves bytes from an associated data source.
				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-ReadableStream-fork-ReadableStream">fork()</a> can be handled.
			</p>

			<p>
				A <dfn>data source</dfn> can be anything that:
				<ul>
					<li>
						Produces bytes.
						Newly produced bytes will be delivered to the associated <a>ReadableStream</a>.
					</li>
					<li>
						Notifies <a>ReadableStream</a> of the EOF signal.
						This signal may mean an error.
						If it means an error, an object indicating the details of the error is attached.
					</li>
					<li>
						Accepts requests for production of bytes from a <a>ReadableStream</a>.
						A byte production request consists of an integer indicating the number of bytes to produce in addition to already requested ones.
						Interpretation of the request is up to data sources.
						Data sources may respond to retrieval requests with data larger than requested.
						Requests and delivery of bytes don't need to 1-to-1 correspond.
						Data sources may produce bytes and send to <a>ReadableStream</a> unsolicitedly without receiving any retrieval request.
					</li>
					<li>
						Accepts and acknowledges read-abort signal which means the associated <a>ReadableStream</a> has completed consuming bytes from this data source optionally with indication of any error.
					</li>
				</ul>
			</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-ReadableStream-fork-ReadableStream">fork()</a> is called, a new reader is registered to the original <a>ReadableStream</a>'s data source and the new <a>ReadableStream</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 ReadableStream has an associated <a>data source</a> referred by <dfn>dataSource</dfn> from which the ReadableStream 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 ReadableStream instances when <code>fork()</code> is used.
				A ReadableStream is registered with a data source on construction and given a reader ID.
				The <a>dataSource</a> of a ReadableStream refers to its data source, and <dfn>readerId</dfn> of a ReadableStream refers to its reader ID.
			</p>

			<p>
				A ReadableStream 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>readUpToPullAmount</dfn> which temporarily overrides <a href="#widl-ReadableStream-pullAmount">pullAmount</a> if necessary for a <code>readUpTo()</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-ReadableStream-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>amountRequested</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>amountBeingReturned</dfn> which holds the number of bytes consumed on the last read operation.
				This variable is initialized to 0 on construction.

				<section class="note">
					amountBeingReturned 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>
				<img src="images/readdatabuffer.png" alt="Read data buffer related variables">
			</p>

			<p>
				An associated flag <dfn>eofReached</dfn> which indicates that the EOF was received from the <a>dataSource</a>.
			</p>

			<p>
				An associated object <dfn>sourceErrorDetail</dfn> which is initialized to <code>null</code>, and once the EOF meaning an error is received from the <a>dataSource</a>, set to the error detail object.
			</p>

			<p>
				To <dfn>retrieve data</dfn>, run the steps below:
				<ol>
					<li>Let <var>readableAmount</var> be the number of bytes in the <a>readDataBuffer</a></li>
					<li>Let <var>amountToRetrieve</var> be max(max(<a href="#widl-ReadableStream-pullAmount">pullAmount</a>, <a>readUpToPullAmount</a>, <a>pipePullAmount</a>) - (<a>amountRequested</a> + <var>readableAmount</var> + <a>amountBeingReturned</a>), 0)</li>
					<li>Set <a>amountRequested</a> to <a>amountRequested</a> + <var>amountToRetrieve</var></li>
					<li>Send a request to the <a>dataSource</a> to return <var>amountToRetrieve</var> bytes to the ReadableStream</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>
				</ol>
			</p>

			<p>
				<img src="images/increasing_pullamount.png" alt="When pullAmount is increased, new data will be fetched">
			</p>

			<p>
				When the EOF is received from <a>dataSource</a>, queue a task which sets <a>eofReached</a> and <a>sourceErrorDetail</a>
			</p>
	  </section>
	</section>

	<section class="section">
		<h2>StreamReadResult Interface</h2>

		<p>
			This interface represents the result of methods on <a>ReadableStream</a>.
		</p>

		<dl class="idl" title="interface StreamReadResult">
			<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 amountConsumed</dt>
			<dd>The size, in bytes, of the data read</dd>
			<dt>readonly attribute any error</dt>
			<dd>Once any error occurred, set to the error detail object on all StreamReadResults returned after the error</dd>
		</dl>
	</section>

	<section class="section">
		<h2>StreamReadType enum</h2>

		<p>
			Data can be read as various data types from <a>ReadableStream</a>.
			This enum defines <a>DOMString</a> values to specify the data types.
		</p>

		<dl class="idl" title="enum StreamReadType">
			<dt>as-is</dt>
			<dd>Default. <code>read()</code> and <code>readUpTo()</code> return produced data as-is</dd>
			<dt>blob</dt>
			<dd><code>read()</code> and <code>readUpTo()</code> attempt to convert produced data into a <a>Blob</a>, and then return it</dd>
			<dt>arraybuffer</dt>
			<dd><code>read()</code> and <code>readUpTo()</code> attempt to convert produced data into an <a>ArrayBuffer</a>, and then return it</dd>
			<dt>text</dt>
			<dd><code>read()</code> and <code>readUpTo()</code> attempt to convert produced data into a <a>DOMString</a>, and then return it</dd>
			<dt>none</dt>
			<dd>
				<code>read()</code> and <code>readUpTo()</code> 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>WritableStream</a> and <a>ReadableStream</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>WritableStream</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>ReadableStream</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>WritableStream</a> as a notification of the number of newly acceptable bytes with the same amount.
			</p>

			<dl class="idl" title="interface ByteStream : ReadableStream, WritableStream">
				<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-ReadableStream-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>ReadableStream</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 ReadableStream) 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>ReadableStream</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>ReadableStream</a> argument that is NOT valid, then user agents must return null.
								</li>
								<li>
									If called with a valid <a>ReadableStream</a> argument,
									user agents must run the following sub-steps:
									<ol>
										<li>
											If <a>readPending</a> of the <a>ReadableStream</a> is set, return null.
										</li>
										<li>
											Set <a>readPending</a> of the <a>ReadableStream</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 ReadableStream) 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>ReadableStream</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>ReadableStream</a> argument that is NOT valid, then user agents must return null.
								</li>
								<li>
									If called with a valid <a>ReadableStream</a> argument,
									user agents must run the following sub-steps:
									<ol>
										<li>
											If <a>readPending</a> of the <a>ReadableStream</a> is set, return null.
										</li>
										<li>
											Set <a>readPending</a> of the <a>ReadableStream</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>ReadableStream</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>ReadableStream</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>ReadableStream</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>
			Byte 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 byte 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 byte stream</p>
			<ul>
				<li>XMLHttpRequest</li>
				<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>
				<li>FileWriter</li>
			</ul>
		</section>

		<section class="section" id="producers">
			<h2>Stream Producers</h2>
			<p>This section outlines APIs which can produce a byte stream</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>ReadableStream</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>ReadableStream</a> uses a <code>Blob URI</code>, cross origin requests on a <a>ReadableStream</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>ReadableStream</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>ReadableStream</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
			Adrian Bateman,
			Anne van Kesteren,
			Austin William Wright,
			Aymeric Vitte,
			Domenic Denicola,
			Elliott Sprehn,
			Francois-Xavier Kowalski,
			Harris Syed,
			Isaac Schlueter,
			Jonas Sicking,
			Kenneth Russell,
			Kinuko Yasuda,
			Lindsay Verola,
			Michael Davidson,
			Rob Manson,
			Taiju Tsuiki,
			Yusuke Suzuki,
			Yutaka Hirano,
			for their contributions to this specification.
		</p>
	</section>

</body>
</html>