<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[185586] trunk/LayoutTests</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/185586">185586</a></dd>
<dt>Author</dt> <dd>calvaris@igalia.com</dd>
<dt>Date</dt> <dd>2015-06-16 01:19:04 -0700 (Tue, 16 Jun 2015)</dd>
</dl>

<h3>Log Message</h3>
<pre>[Streams API] Sync tests with spec
https://bugs.webkit.org/show_bug.cgi?id=145839

Reviewed by Darin Adler.

Considered all changes in the spec tests and brought them to WebKit.

Some of those changes were related to spec changes, like the strategy or some of the algorithms. Some like the
tee ones were newly added as they will be implemented soon. There are also some tests that shuffled around
because they were just moved at the spec or integrated from the changes we submitted, which was substantially
important as it allowed us to remove some of our custom tests that are now covered by the spec ones.

* resources/gc.js: Added warning about using gcRec, results might not be reliable.
* streams/readable-stream-controller-error-expected.txt:
* streams/readable-stream-controller-error.html: New failing test due to discrepancies with the reference
implementation. Something we will address.
* streams/readable-stream-expected.txt: Removed.
* streams/readable-stream-gc.html: Renumbered.
* streams/readable-stream-reader-expected.txt: Removed.
* streams/readable-stream-reader-read.html: Renumbered.
* streams/readable-stream-reader.html: Removed.
* streams/readable-stream.html: Removed.
* streams/reference-implementation/bad-strategies-expected.txt: Added.
* streams/reference-implementation/bad-strategies.html: Added.
* streams/reference-implementation/bad-underlying-sources-expected.txt:
* streams/reference-implementation/bad-underlying-sources.html: Updated from spec and expectations.
* streams/reference-implementation/brand-checks-expected.txt:
* streams/reference-implementation/brand-checks.html: Updated from spec and expectations.
* streams/reference-implementation/byte-length-queuing-strategy-expected.txt: Added.
* streams/reference-implementation/byte-length-queuing-strategy.html: Added.
* streams/reference-implementation/count-queuing-strategy-expected.txt:
* streams/reference-implementation/count-queuing-strategy.html: Updated from spec and expectations.
* streams/reference-implementation/readable-stream-cancel-expected.txt:
* streams/reference-implementation/readable-stream-cancel.html: Updated from spec and expectations and corrected
timeouts to try to overcome problems in slower bots.
* streams/reference-implementation/readable-stream-expected.txt:
* streams/reference-implementation/readable-stream-reader-expected.txt:
* streams/reference-implementation/readable-stream-reader.html: Updated from spec and expectations.
* streams/reference-implementation/readable-stream-tee-expected.txt: Added.
* streams/reference-implementation/readable-stream-tee.html: Added.
* streams/reference-implementation/readable-stream-templated-expected.txt:
* streams/reference-implementation/readable-stream-templated.html: Updated from spec and expectations.
* streams/reference-implementation/readable-stream.html: Updated from spec and expectations.
* streams/reference-implementation/resources/byte-length-queuing-strategy.js:
(ByteLengthQueuingStrategy): Updated from spec.
(typeIsObject): Deleted.
(ByteLengthQueuingStrategy.prototype.shouldApplyBackpressure): Deleted.
* streams/reference-implementation/resources/count-queuing-strategy.js:
(CountQueuingStrategy): Updated from spec.
(typeIsObject): Deleted.
(CountQueuingStrategy.prototype.shouldApplyBackpressure): Deleted.
* streams/reference-implementation/resources/streams-utils.js:
(RandomPushSource.prototype.readStart.writeChunk):
(RandomPushSource.prototype.readStart): Renamed stream as source
(.stream.new.ReadableStream):
(sequentialReadableStream): Updated from spec.
(typeIsObject): Added.
(createDataProperty): Added.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsChangeLog">trunk/LayoutTests/ChangeLog</a></li>
<li><a href="#trunkLayoutTestsresourcesgcjs">trunk/LayoutTests/resources/gc.js</a></li>
<li><a href="#trunkLayoutTestsstreamsreadablestreamcontrollererrorexpectedtxt">trunk/LayoutTests/streams/readable-stream-controller-error-expected.txt</a></li>
<li><a href="#trunkLayoutTestsstreamsreadablestreamcontrollererrorhtml">trunk/LayoutTests/streams/readable-stream-controller-error.html</a></li>
<li><a href="#trunkLayoutTestsstreamsreadablestreamgchtml">trunk/LayoutTests/streams/readable-stream-gc.html</a></li>
<li><a href="#trunkLayoutTestsstreamsreadablestreamreaderreadhtml">trunk/LayoutTests/streams/readable-stream-reader-read.html</a></li>
<li><a href="#trunkLayoutTestsstreamsreferenceimplementationbadunderlyingsourcesexpectedtxt">trunk/LayoutTests/streams/reference-implementation/bad-underlying-sources-expected.txt</a></li>
<li><a href="#trunkLayoutTestsstreamsreferenceimplementationbadunderlyingsourceshtml">trunk/LayoutTests/streams/reference-implementation/bad-underlying-sources.html</a></li>
<li><a href="#trunkLayoutTestsstreamsreferenceimplementationbrandchecksexpectedtxt">trunk/LayoutTests/streams/reference-implementation/brand-checks-expected.txt</a></li>
<li><a href="#trunkLayoutTestsstreamsreferenceimplementationbrandcheckshtml">trunk/LayoutTests/streams/reference-implementation/brand-checks.html</a></li>
<li><a href="#trunkLayoutTestsstreamsreferenceimplementationcountqueuingstrategyexpectedtxt">trunk/LayoutTests/streams/reference-implementation/count-queuing-strategy-expected.txt</a></li>
<li><a href="#trunkLayoutTestsstreamsreferenceimplementationcountqueuingstrategyhtml">trunk/LayoutTests/streams/reference-implementation/count-queuing-strategy.html</a></li>
<li><a href="#trunkLayoutTestsstreamsreferenceimplementationreadablestreamcancelexpectedtxt">trunk/LayoutTests/streams/reference-implementation/readable-stream-cancel-expected.txt</a></li>
<li><a href="#trunkLayoutTestsstreamsreferenceimplementationreadablestreamcancelhtml">trunk/LayoutTests/streams/reference-implementation/readable-stream-cancel.html</a></li>
<li><a href="#trunkLayoutTestsstreamsreferenceimplementationreadablestreamexpectedtxt">trunk/LayoutTests/streams/reference-implementation/readable-stream-expected.txt</a></li>
<li><a href="#trunkLayoutTestsstreamsreferenceimplementationreadablestreamreaderexpectedtxt">trunk/LayoutTests/streams/reference-implementation/readable-stream-reader-expected.txt</a></li>
<li><a href="#trunkLayoutTestsstreamsreferenceimplementationreadablestreamreaderhtml">trunk/LayoutTests/streams/reference-implementation/readable-stream-reader.html</a></li>
<li><a href="#trunkLayoutTestsstreamsreferenceimplementationreadablestreamtemplatedexpectedtxt">trunk/LayoutTests/streams/reference-implementation/readable-stream-templated-expected.txt</a></li>
<li><a href="#trunkLayoutTestsstreamsreferenceimplementationreadablestreamtemplatedhtml">trunk/LayoutTests/streams/reference-implementation/readable-stream-templated.html</a></li>
<li><a href="#trunkLayoutTestsstreamsreferenceimplementationreadablestreamhtml">trunk/LayoutTests/streams/reference-implementation/readable-stream.html</a></li>
<li><a href="#trunkLayoutTestsstreamsreferenceimplementationresourcesbytelengthqueuingstrategyjs">trunk/LayoutTests/streams/reference-implementation/resources/byte-length-queuing-strategy.js</a></li>
<li><a href="#trunkLayoutTestsstreamsreferenceimplementationresourcescountqueuingstrategyjs">trunk/LayoutTests/streams/reference-implementation/resources/count-queuing-strategy.js</a></li>
<li><a href="#trunkLayoutTestsstreamsreferenceimplementationresourcesstreamsutilsjs">trunk/LayoutTests/streams/reference-implementation/resources/streams-utils.js</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsstreamsreferenceimplementationbadstrategiesexpectedtxt">trunk/LayoutTests/streams/reference-implementation/bad-strategies-expected.txt</a></li>
<li><a href="#trunkLayoutTestsstreamsreferenceimplementationbadstrategieshtml">trunk/LayoutTests/streams/reference-implementation/bad-strategies.html</a></li>
<li><a href="#trunkLayoutTestsstreamsreferenceimplementationbytelengthqueuingstrategyexpectedtxt">trunk/LayoutTests/streams/reference-implementation/byte-length-queuing-strategy-expected.txt</a></li>
<li><a href="#trunkLayoutTestsstreamsreferenceimplementationbytelengthqueuingstrategyhtml">trunk/LayoutTests/streams/reference-implementation/byte-length-queuing-strategy.html</a></li>
<li><a href="#trunkLayoutTestsstreamsreferenceimplementationreadablestreamteeexpectedtxt">trunk/LayoutTests/streams/reference-implementation/readable-stream-tee-expected.txt</a></li>
<li><a href="#trunkLayoutTestsstreamsreferenceimplementationreadablestreamteehtml">trunk/LayoutTests/streams/reference-implementation/readable-stream-tee.html</a></li>
</ul>

<h3>Removed Paths</h3>
<ul>
<li><a href="#trunkLayoutTestsstreamsreadablestreamexpectedtxt">trunk/LayoutTests/streams/readable-stream-expected.txt</a></li>
<li><a href="#trunkLayoutTestsstreamsreadablestreamreaderexpectedtxt">trunk/LayoutTests/streams/readable-stream-reader-expected.txt</a></li>
<li><a href="#trunkLayoutTestsstreamsreadablestreamreaderhtml">trunk/LayoutTests/streams/readable-stream-reader.html</a></li>
<li><a href="#trunkLayoutTestsstreamsreadablestreamhtml">trunk/LayoutTests/streams/readable-stream.html</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkLayoutTestsChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/ChangeLog (185585 => 185586)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/ChangeLog        2015-06-16 07:40:09 UTC (rev 185585)
+++ trunk/LayoutTests/ChangeLog        2015-06-16 08:19:04 UTC (rev 185586)
</span><span class="lines">@@ -1,3 +1,64 @@
</span><ins>+2015-06-16  Youenn Fablet &lt;youenn.fablet@crf.canon.fr&gt; and Xabier Rodriguez Calvar  &lt;calvaris@igalia.com&gt;
+
+        [Streams API] Sync tests with spec
+        https://bugs.webkit.org/show_bug.cgi?id=145839
+
+        Reviewed by Darin Adler.
+
+        Considered all changes in the spec tests and brought them to WebKit.
+
+        Some of those changes were related to spec changes, like the strategy or some of the algorithms. Some like the
+        tee ones were newly added as they will be implemented soon. There are also some tests that shuffled around
+        because they were just moved at the spec or integrated from the changes we submitted, which was substantially
+        important as it allowed us to remove some of our custom tests that are now covered by the spec ones.
+
+        * resources/gc.js: Added warning about using gcRec, results might not be reliable.
+        * streams/readable-stream-controller-error-expected.txt:
+        * streams/readable-stream-controller-error.html: New failing test due to discrepancies with the reference
+        implementation. Something we will address.
+        * streams/readable-stream-expected.txt: Removed.
+        * streams/readable-stream-gc.html: Renumbered.
+        * streams/readable-stream-reader-expected.txt: Removed.
+        * streams/readable-stream-reader-read.html: Renumbered.
+        * streams/readable-stream-reader.html: Removed.
+        * streams/readable-stream.html: Removed.
+        * streams/reference-implementation/bad-strategies-expected.txt: Added.
+        * streams/reference-implementation/bad-strategies.html: Added.
+        * streams/reference-implementation/bad-underlying-sources-expected.txt:
+        * streams/reference-implementation/bad-underlying-sources.html: Updated from spec and expectations.
+        * streams/reference-implementation/brand-checks-expected.txt:
+        * streams/reference-implementation/brand-checks.html: Updated from spec and expectations.
+        * streams/reference-implementation/byte-length-queuing-strategy-expected.txt: Added.
+        * streams/reference-implementation/byte-length-queuing-strategy.html: Added.
+        * streams/reference-implementation/count-queuing-strategy-expected.txt:
+        * streams/reference-implementation/count-queuing-strategy.html: Updated from spec and expectations.
+        * streams/reference-implementation/readable-stream-cancel-expected.txt:
+        * streams/reference-implementation/readable-stream-cancel.html: Updated from spec and expectations and corrected
+        timeouts to try to overcome problems in slower bots.
+        * streams/reference-implementation/readable-stream-expected.txt:
+        * streams/reference-implementation/readable-stream-reader-expected.txt:
+        * streams/reference-implementation/readable-stream-reader.html: Updated from spec and expectations.
+        * streams/reference-implementation/readable-stream-tee-expected.txt: Added.
+        * streams/reference-implementation/readable-stream-tee.html: Added.
+        * streams/reference-implementation/readable-stream-templated-expected.txt:
+        * streams/reference-implementation/readable-stream-templated.html: Updated from spec and expectations.
+        * streams/reference-implementation/readable-stream.html: Updated from spec and expectations.
+        * streams/reference-implementation/resources/byte-length-queuing-strategy.js:
+        (ByteLengthQueuingStrategy): Updated from spec.
+        (typeIsObject): Deleted.
+        (ByteLengthQueuingStrategy.prototype.shouldApplyBackpressure): Deleted.
+        * streams/reference-implementation/resources/count-queuing-strategy.js:
+        (CountQueuingStrategy): Updated from spec.
+        (typeIsObject): Deleted.
+        (CountQueuingStrategy.prototype.shouldApplyBackpressure): Deleted.
+        * streams/reference-implementation/resources/streams-utils.js:
+        (RandomPushSource.prototype.readStart.writeChunk):
+        (RandomPushSource.prototype.readStart): Renamed stream as source
+        (.stream.new.ReadableStream):
+        (sequentialReadableStream): Updated from spec.
+        (typeIsObject): Added.
+        (createDataProperty): Added.
+
</ins><span class="cx"> 2015-06-16  Alexey Proskuryakov  &lt;ap@apple.com&gt;
</span><span class="cx"> 
</span><span class="cx">         Fix a lint error by removing an obsolete expectation - this test doesn't fail
</span></span></pre></div>
<a id="trunkLayoutTestsresourcesgcjs"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/resources/gc.js (185585 => 185586)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/resources/gc.js        2015-06-16 07:40:09 UTC (rev 185585)
+++ trunk/LayoutTests/resources/gc.js        2015-06-16 08:19:04 UTC (rev 185586)
</span><span class="lines">@@ -7,6 +7,8 @@
</span><span class="cx">     {
</span><span class="cx">         if (window.GCController)
</span><span class="cx">             return GCController.collect();
</span><ins>+
+        console.warn('Tests are running without the ability to do manual garbage collection. They will still work, but coverage will be suboptimal.');
</ins><span class="cx">         function gcRec(n) {
</span><span class="cx">             if (n &lt; 1)
</span><span class="cx">                 return {};
</span></span></pre></div>
<a id="trunkLayoutTestsstreamsreadablestreamcontrollererrorexpectedtxt"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/streams/readable-stream-controller-error-expected.txt (185585 => 185586)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/streams/readable-stream-controller-error-expected.txt        2015-06-16 07:40:09 UTC (rev 185585)
+++ trunk/LayoutTests/streams/readable-stream-controller-error-expected.txt        2015-06-16 08:19:04 UTC (rev 185586)
</span><span class="lines">@@ -1,5 +1,5 @@
</span><span class="cx"> 
</span><span class="cx"> PASS Erroring a ReadableStream should reject ReadableStreamReader close promise 
</span><span class="cx"> PASS Erroring a ReadableStream should reject ReadableStreamReader close promise 
</span><del>-PASS Erroring a ReadableStream without any value 
</del><ins>+FAIL Erroring a ReadableStream without any value assert_equals: expected (undefined) undefined but got (object) object &quot;Error: Error function called.&quot;
</ins><span class="cx"> 
</span></span></pre></div>
<a id="trunkLayoutTestsstreamsreadablestreamcontrollererrorhtml"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/streams/readable-stream-controller-error.html (185585 => 185586)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/streams/readable-stream-controller-error.html        2015-06-16 07:40:09 UTC (rev 185585)
+++ trunk/LayoutTests/streams/readable-stream-controller-error.html        2015-06-16 08:19:04 UTC (rev 185586)
</span><span class="lines">@@ -2,9 +2,8 @@
</span><span class="cx"> &lt;script src='../resources/testharness.js'&gt;&lt;/script&gt;
</span><span class="cx"> &lt;script src='../resources/testharnessreport.js'&gt;&lt;/script&gt;
</span><span class="cx"> &lt;script&gt;
</span><del>-
-t2 = async_test('Erroring a ReadableStream should reject ReadableStreamReader close promise');
-t2.step(function() {
</del><ins>+var test1 = async_test('Erroring a ReadableStream should reject ReadableStreamReader close promise');
+test1.step(function() {
</ins><span class="cx">     var controller;
</span><span class="cx">     var rs = new ReadableStream({
</span><span class="cx">         start: function(c) {
</span><span class="lines">@@ -12,19 +11,19 @@
</span><span class="cx">         }
</span><span class="cx">     });
</span><span class="cx"> 
</span><del>-   rs.getReader().closed.then(t2.step_func(function() {
</del><ins>+   rs.getReader().closed.then(test1.step_func(function() {
</ins><span class="cx">         assert_unreached(&quot;closed promise should not be resolved when stream is errored&quot;);
</span><del>-    }), t2.step_func(function(err) {
</del><ins>+    }), test1.step_func(function(err) {
</ins><span class="cx">         assert_equals(rsError, err);
</span><del>-        t2.done();
</del><ins>+        test1.done();
</ins><span class="cx">     }));
</span><span class="cx"> 
</span><span class="cx">     var rsError = &quot;my error&quot;;
</span><span class="cx">     controller.error(rsError);
</span><span class="cx"> });
</span><span class="cx"> 
</span><del>-t3 = async_test('Erroring a ReadableStream should reject ReadableStreamReader close promise');
-t3.step(function() {
</del><ins>+var test2 = async_test('Erroring a ReadableStream should reject ReadableStreamReader close promise');
+test2.step(function() {
</ins><span class="cx">     var controller;
</span><span class="cx">     var rs = new ReadableStream({
</span><span class="cx">         start: function(c) {
</span><span class="lines">@@ -37,16 +36,16 @@
</span><span class="cx"> 
</span><span class="cx">     // Let's call getReader twice to ensure that stream is not locked to a reader.
</span><span class="cx">     rs.getReader();
</span><del>-    rs.getReader().closed.then(t3.step_func(function() {
</del><ins>+    rs.getReader().closed.then(test2.step_func(function() {
</ins><span class="cx">         assert_unreached(&quot;closed promise should not be resolved when stream is errored&quot;);
</span><del>-    }), t3.step_func(function(err) {
</del><ins>+    }), test2.step_func(function(err) {
</ins><span class="cx">         assert_equals(rsError, err);
</span><del>-        t3.done();
</del><ins>+        test2.done();
</ins><span class="cx">     }));
</span><span class="cx"> });
</span><span class="cx"> 
</span><del>-t4 = async_test('Erroring a ReadableStream without any value');
-t4.step(function() {
</del><ins>+var test3 = async_test('Erroring a ReadableStream without any value');
+test3.step(function() {
</ins><span class="cx">     var controller;
</span><span class="cx">     var rs = new ReadableStream({
</span><span class="cx">         start: function(c) {
</span><span class="lines">@@ -54,16 +53,13 @@
</span><span class="cx">         }
</span><span class="cx">     });
</span><span class="cx"> 
</span><del>-    rs.getReader().closed.then(t3.step_func(function() {
</del><ins>+    rs.getReader().closed.then(test3.step_func(function() {
</ins><span class="cx">         assert_unreached(&quot;closed promise should not be resolved when stream is errored&quot;);
</span><del>-    }), t4.step_func(function(err) {
-        // Error generated by JS engine.
-        assert_true(typeof err == 'object');
-        t4.done();
</del><ins>+    }), test3.step_func(function(err) {
+        assert_equals(err, undefined);
+        test3.done();
</ins><span class="cx">     }));
</span><span class="cx"> 
</span><span class="cx">     controller.error();
</span><span class="cx"> });
</span><del>-
-
</del><span class="cx"> &lt;/script&gt;
</span></span></pre></div>
<a id="trunkLayoutTestsstreamsreadablestreamexpectedtxt"></a>
<div class="delfile"><h4>Deleted: trunk/LayoutTests/streams/readable-stream-expected.txt (185585 => 185586)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/streams/readable-stream-expected.txt        2015-06-16 07:40:09 UTC (rev 185585)
+++ trunk/LayoutTests/streams/readable-stream-expected.txt        2015-06-16 08:19:04 UTC (rev 185586)
</span><span class="lines">@@ -1,5 +0,0 @@
</span><del>-
-PASS ReadableStream can't be constructed with garbage 
-PASS ReadableStream start should be called with the proper parameters 
-PASS ReadableStream should be able to call start method within prototype chain of its source 
-
</del></span></pre></div>
<a id="trunkLayoutTestsstreamsreadablestreamgchtml"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/streams/readable-stream-gc.html (185585 => 185586)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/streams/readable-stream-gc.html        2015-06-16 07:40:09 UTC (rev 185585)
+++ trunk/LayoutTests/streams/readable-stream-gc.html        2015-06-16 08:19:04 UTC (rev 185586)
</span><span class="lines">@@ -3,7 +3,6 @@
</span><span class="cx"> &lt;script src='../resources/testharnessreport.js'&gt;&lt;/script&gt;
</span><span class="cx"> &lt;script src='../resources/gc.js'&gt;&lt;/script&gt;
</span><span class="cx"> &lt;script&gt;
</span><del>-
</del><span class="cx"> function garbageCollectAndDo(task)
</span><span class="cx"> {
</span><span class="cx">     var timeout = 50;
</span><span class="lines">@@ -16,8 +15,8 @@
</span><span class="cx">     setTimeout(task, timeout);
</span><span class="cx"> }
</span><span class="cx"> 
</span><del>-t1 = async_test('Readable stream controller methods should continue working properly when scripts are loosing reference to the readable stream');
-t1.step(function() {
</del><ins>+var test1 = async_test('Readable stream controller methods should continue working properly when scripts are loosing reference to the readable stream');
+test1.step(function() {
</ins><span class="cx">     var controller;
</span><span class="cx">     new ReadableStream({
</span><span class="cx">         start: function(c) {
</span><span class="lines">@@ -25,44 +24,43 @@
</span><span class="cx">         }
</span><span class="cx">     });
</span><span class="cx"> 
</span><del>-    garbageCollectAndDo(t1.step_func(function() {
</del><ins>+    garbageCollectAndDo(test1.step_func(function() {
</ins><span class="cx">         controller.close();
</span><span class="cx">         assert_throws(new TypeError(), function() { controller.close(); });
</span><span class="cx">         assert_throws(new TypeError(), function() { controller.error(); });
</span><del>-        t1.done();
</del><ins>+        test1.done();
</ins><span class="cx">     }));
</span><span class="cx"> });
</span><span class="cx"> 
</span><del>-t2 = async_test('Readable stream closed promise should resolve even if stream and reader JS references are lost');
-t2.step(function() {
</del><ins>+var test2 = async_test('Readable stream closed promise should resolve even if stream and reader JS references are lost');
+test2.step(function() {
</ins><span class="cx">     var controller;
</span><span class="cx">     new ReadableStream({
</span><span class="cx">         start: function(c) {
</span><span class="cx">             controller = c;
</span><span class="cx">         }
</span><del>-    }).getReader().closed.then(t2.step_func(function() {
-        t2.done();
</del><ins>+    }).getReader().closed.then(test2.step_func(function() {
+        test2.done();
</ins><span class="cx">     }));
</span><span class="cx"> 
</span><del>-    garbageCollectAndDo(t2.step_func(function() {
</del><ins>+    garbageCollectAndDo(test2.step_func(function() {
</ins><span class="cx">         controller.close();
</span><span class="cx">     }));
</span><span class="cx"> });
</span><span class="cx"> 
</span><del>-t3 = async_test('Readable stream closed promise should reject even if stream and reader JS references are lost');
-t3.step(function() {
</del><ins>+var test3 = async_test('Readable stream closed promise should reject even if stream and reader JS references are lost');
+test3.step(function() {
</ins><span class="cx">     var controller;
</span><span class="cx">     new ReadableStream({
</span><span class="cx">         start: function(c) {
</span><span class="cx">             controller = c;
</span><span class="cx">         }
</span><del>-    }).getReader().closed.catch(t3.step_func(function() {
-        t3.done();
</del><ins>+    }).getReader().closed.catch(test3.step_func(function() {
+        test3.done();
</ins><span class="cx">     }));
</span><span class="cx"> 
</span><del>-    garbageCollectAndDo(t3.step_func(function() {
</del><ins>+    garbageCollectAndDo(test3.step_func(function() {
</ins><span class="cx">         controller.error();
</span><span class="cx">     }));
</span><span class="cx"> });
</span><del>-
</del><span class="cx"> &lt;/script&gt;
</span></span></pre></div>
<a id="trunkLayoutTestsstreamsreadablestreamreaderexpectedtxt"></a>
<div class="delfile"><h4>Deleted: trunk/LayoutTests/streams/readable-stream-reader-expected.txt (185585 => 185586)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/streams/readable-stream-reader-expected.txt        2015-06-16 07:40:09 UTC (rev 185585)
+++ trunk/LayoutTests/streams/readable-stream-reader-expected.txt        2015-06-16 08:19:04 UTC (rev 185586)
</span><span class="lines">@@ -1,3 +0,0 @@
</span><del>-
-PASS Collecting a ReadableStreamReader should not unlock its stream 
-
</del></span></pre></div>
<a id="trunkLayoutTestsstreamsreadablestreamreaderreadhtml"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/streams/readable-stream-reader-read.html (185585 => 185586)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/streams/readable-stream-reader-read.html        2015-06-16 07:40:09 UTC (rev 185585)
+++ trunk/LayoutTests/streams/readable-stream-reader-read.html        2015-06-16 08:19:04 UTC (rev 185586)
</span><span class="lines">@@ -2,8 +2,8 @@
</span><span class="cx"> &lt;script src='../resources/testharness.js'&gt;&lt;/script&gt;
</span><span class="cx"> &lt;script src='../resources/testharnessreport.js'&gt;&lt;/script&gt;
</span><span class="cx"> &lt;script&gt;
</span><del>-var t1 = async_test('Reading twice on a stream that gets closed');
-t1.step(function() {
</del><ins>+var test1 = async_test('Reading twice on a stream that gets closed');
+test1.step(function() {
</ins><span class="cx">     var controller;
</span><span class="cx">     var rs = new ReadableStream({
</span><span class="cx">         start: function(c) {
</span><span class="lines">@@ -13,18 +13,18 @@
</span><span class="cx">     var counter = 0;
</span><span class="cx">     var reader = rs.getReader();
</span><span class="cx"> 
</span><del>-    reader.read().then(t1.step_func(function(result) {
</del><ins>+    reader.read().then(test1.step_func(function(result) {
</ins><span class="cx">         assert_object_equals(result, { value: undefined, done: true }, 'read() should fulfill with close');
</span><span class="cx">         assert_equals(counter, 1);
</span><span class="cx">         counter++;
</span><span class="cx">     }));
</span><del>-    reader.read().then(t1.step_func(function(result) {
</del><ins>+    reader.read().then(test1.step_func(function(result) {
</ins><span class="cx">         assert_object_equals(result, { value: undefined, done: true }, 'read() should fulfill with close');
</span><span class="cx">         assert_equals(counter, 2);
</span><span class="cx">         counter++;
</span><del>-        t1.done();
</del><ins>+        test1.done();
</ins><span class="cx">     }));
</span><del>-    reader.closed.then(t1.step_func(function() {
</del><ins>+    reader.closed.then(test1.step_func(function() {
</ins><span class="cx">         assert_equals(counter, 0);
</span><span class="cx">         counter++;
</span><span class="cx">     }));
</span><span class="lines">@@ -32,8 +32,8 @@
</span><span class="cx">     controller.close();
</span><span class="cx"> });
</span><span class="cx"> 
</span><del>-var t2 = async_test('Reading twice on a closed stream');
-t2.step(function() {
</del><ins>+var test2 = async_test('Reading twice on a closed stream');
+test2.step(function() {
</ins><span class="cx">     var controller;
</span><span class="cx">     var rs = new ReadableStream({
</span><span class="cx">         start: function(c) {
</span><span class="lines">@@ -46,25 +46,25 @@
</span><span class="cx">     var counter = 0;
</span><span class="cx">     var reader = rs.getReader();
</span><span class="cx"> 
</span><del>-    reader.read().then(t2.step_func(function(result) {
</del><ins>+    reader.read().then(test2.step_func(function(result) {
</ins><span class="cx">         assert_object_equals(result, { value: undefined, done: true }, 'read() should fulfill with close');
</span><span class="cx">         assert_equals(counter, 0);
</span><span class="cx">         counter++;
</span><span class="cx">     }));
</span><del>-    reader.read().then(t2.step_func(function(result) {
</del><ins>+    reader.read().then(test2.step_func(function(result) {
</ins><span class="cx">         assert_object_equals(result, { value: undefined, done: true }, 'read() should fulfill with close');
</span><span class="cx">         assert_equals(counter, 1);
</span><span class="cx">         counter++;
</span><span class="cx">     }));
</span><del>-    reader.closed.then(t2.step_func(function() {
</del><ins>+    reader.closed.then(test2.step_func(function() {
</ins><span class="cx">         assert_equals(counter, 2);
</span><span class="cx">         counter++;
</span><del>-        t2.done();
</del><ins>+        test2.done();
</ins><span class="cx">     }));
</span><span class="cx"> });
</span><span class="cx"> 
</span><del>-var t3 = async_test('Reading twice on an errored stream');
-t3.step(function() {
</del><ins>+var test3 = async_test('Reading twice on an errored stream');
+test3.step(function() {
</ins><span class="cx">     var controller;
</span><span class="cx">     var rs = new ReadableStream({
</span><span class="cx">         start: function(c) {
</span><span class="lines">@@ -78,32 +78,32 @@
</span><span class="cx">     var counter = 0;
</span><span class="cx">     var reader = rs.getReader();
</span><span class="cx"> 
</span><del>-    reader.read().then(t3.step_func(function() {
</del><ins>+    reader.read().then(test3.step_func(function() {
</ins><span class="cx">         assert_unreached('read() should reject on an errored stream');
</span><del>-    }), t3.step_func(function(err) {
</del><ins>+    }), test3.step_func(function(err) {
</ins><span class="cx">         assert_equals(myError, err);
</span><span class="cx">         assert_equals(counter, 0);
</span><span class="cx">         counter++;
</span><span class="cx">     }));
</span><del>-    reader.read().then(t3.step_func(function() {
</del><ins>+    reader.read().then(test3.step_func(function() {
</ins><span class="cx">         assert_unreached('read() should reject on an errored stream');
</span><del>-    }), t3.step_func(function(err) {
</del><ins>+    }), test3.step_func(function(err) {
</ins><span class="cx">         assert_equals(myError, err);
</span><span class="cx">         assert_equals(counter, 1);
</span><span class="cx">         counter++;
</span><span class="cx">     }));
</span><del>-    reader.closed.then(t3.step_func(function() {
</del><ins>+    reader.closed.then(test3.step_func(function() {
</ins><span class="cx">         assert_unreached('read() should reject on an errored stream');
</span><del>-    }), t3.step_func(function(err) {
</del><ins>+    }), test3.step_func(function(err) {
</ins><span class="cx">         assert_equals(myError, err);
</span><span class="cx">         assert_equals(counter, 2);
</span><span class="cx">         counter++;
</span><del>-        t3.done();
</del><ins>+        test3.done();
</ins><span class="cx">     }));
</span><span class="cx"> });
</span><span class="cx"> 
</span><del>-var t4 = async_test('Reading twice on a stream that gets errored');
-t4.step(function() {
</del><ins>+var test4 = async_test('Reading twice on a stream that gets errored');
+test4.step(function() {
</ins><span class="cx">     var controller;
</span><span class="cx">     var rs = new ReadableStream({
</span><span class="cx">         start: function(c) {
</span><span class="lines">@@ -114,24 +114,24 @@
</span><span class="cx">     var counter = 0;
</span><span class="cx">     var reader = rs.getReader();
</span><span class="cx"> 
</span><del>-    reader.read().then(t4.step_func(function() {
</del><ins>+    reader.read().then(test4.step_func(function() {
</ins><span class="cx">         assert_unreached('read() should reject on an errored stream');
</span><del>-    }), t4.step_func(function(err) {
</del><ins>+    }), test4.step_func(function(err) {
</ins><span class="cx">         assert_equals(myError, err);
</span><span class="cx">         assert_equals(counter, 1);
</span><span class="cx">         counter++;
</span><span class="cx">     }));
</span><del>-    reader.read().then(t4.step_func(function() {
</del><ins>+    reader.read().then(test4.step_func(function() {
</ins><span class="cx">         assert_unreached('read() should reject on an errored stream');
</span><del>-    }), t4.step_func(function(err) {
</del><ins>+    }), test4.step_func(function(err) {
</ins><span class="cx">         assert_equals(myError, err);
</span><span class="cx">         assert_equals(counter, 2);
</span><span class="cx">         counter++;
</span><del>-        t4.done();
</del><ins>+        test4.done();
</ins><span class="cx">     }));
</span><del>-    reader.closed.then(t4.step_func(function() {
</del><ins>+    reader.closed.then(test4.step_func(function() {
</ins><span class="cx">         assert_unreached('read() should reject on an errored stream');
</span><del>-    }), t4.step_func(function(err) {
</del><ins>+    }), test4.step_func(function(err) {
</ins><span class="cx">         assert_equals(myError, err);
</span><span class="cx">         assert_equals(counter, 0);
</span><span class="cx">         counter++;
</span><span class="lines">@@ -141,8 +141,8 @@
</span><span class="cx">     controller.error(myError);
</span><span class="cx">  });
</span><span class="cx"> 
</span><del>-var t5 = async_test('Reading within a read promise resolve callback on a stream that gets closed');
-t5.step(function() {
</del><ins>+var test5 = async_test('Reading within a read promise resolve callback on a stream that gets closed');
+test5.step(function() {
</ins><span class="cx">     var controller;
</span><span class="cx">     var rs = new ReadableStream({
</span><span class="cx">         start: function(c) {
</span><span class="lines">@@ -152,9 +152,9 @@
</span><span class="cx"> 
</span><span class="cx">     var reader = rs.getReader();
</span><span class="cx"> 
</span><del>-    reader.read().then(t5.step_func(function() {
-        reader.read().then(t5.step_func(function() {
-            t5.done();
</del><ins>+    reader.read().then(test5.step_func(function() {
+        reader.read().then(test5.step_func(function() {
+            test5.done();
</ins><span class="cx">         }));
</span><span class="cx">     }));
</span><span class="cx">     controller.close();
</span></span></pre></div>
<a id="trunkLayoutTestsstreamsreadablestreamreaderhtml"></a>
<div class="delfile"><h4>Deleted: trunk/LayoutTests/streams/readable-stream-reader.html (185585 => 185586)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/streams/readable-stream-reader.html        2015-06-16 07:40:09 UTC (rev 185585)
+++ trunk/LayoutTests/streams/readable-stream-reader.html        2015-06-16 08:19:04 UTC (rev 185586)
</span><span class="lines">@@ -1,18 +0,0 @@
</span><del>-&lt;!DOCTYPE html&gt;
-&lt;script src='../resources/testharness.js'&gt;&lt;/script&gt;
-&lt;script src='../resources/testharnessreport.js'&gt;&lt;/script&gt;
-&lt;script src='../resources/gc.js'&gt;&lt;/script&gt;
-&lt;script&gt;
-
-t1 = async_test('Collecting a ReadableStreamReader should not unlock its stream');
-t1.step(function() {
-    var rs = new ReadableStream({});
-    rs.getReader();
-    setTimeout(t1.step_func(function() {
-        window.gc();
-        assert_throws(new TypeError(), function() { rs.getReader(); }, 'old reader should still be locking a new one even after garbage collection');
-        t1.done();
-    }), 10);
-});
-
-&lt;/script&gt;
</del></span></pre></div>
<a id="trunkLayoutTestsstreamsreadablestreamhtml"></a>
<div class="delfile"><h4>Deleted: trunk/LayoutTests/streams/readable-stream.html (185585 => 185586)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/streams/readable-stream.html        2015-06-16 07:40:09 UTC (rev 185585)
+++ trunk/LayoutTests/streams/readable-stream.html        2015-06-16 08:19:04 UTC (rev 185586)
</span><span class="lines">@@ -1,65 +0,0 @@
</span><del>-&lt;!DOCTYPE html&gt;
-&lt;script src='../resources/testharness.js'&gt;&lt;/script&gt;
-&lt;script src='../resources/testharnessreport.js'&gt;&lt;/script&gt;
-&lt;script&gt;
-test(function() {
-    assert_throws(new TypeError(), function() {
-        new ReadableStream(null);
-    }, 'constructor should throw when the source is null');
-}, 'ReadableStream can\'t be constructed with garbage');
-
-test(function()
-{
-    var isStartCalled = false;
-    var source = {
-        start: function(controller) {
-            assert_equals(this, source, 'source is this during start');
-
-            // FIXME: We should add constructor at some point.
-            var methods = [ 'close', 'constructor', 'enqueue', 'error' ];
-            var proto = Object.getPrototypeOf(controller);
-
-            assert_array_equals(Object.getOwnPropertyNames(Object.getPrototypeOf(controller)).sort(), methods,
-                        'the controller should have the right methods');
-
-            for (var m of [ 'close', 'enqueue', 'error' ]) {
-                var methodProperties = [ 'length', 'name' ];
-                var propDesc = Object.getOwnPropertyDescriptor(proto, m);
-                assert_equals(propDesc.enumerable, true, 'method should be enumerable');
-                assert_equals(propDesc.configurable, true, 'method should be configurable');
-                assert_equals(propDesc.writable, true, 'method should be writable');
-                assert_equals(typeof controller[m], 'function', 'should have be a method');
-                assert_array_equals(Object.getOwnPropertyNames(controller[m]).sort(), methodProperties, 'method should have the right properties');
-            }
-
-            assert_equals(controller.close.length, 0, 'close should have no parameters');
-            assert_equals(controller.enqueue.length, 1, 'enqueue should have 1 parameter');
-            assert_equals(controller.error.length, 1, 'error should have 1 parameter');
-
-            var propDesc = Object.getOwnPropertyDescriptor(proto, 'constructor');
-            assert_equals(propDesc.enumerable, false, 'constructor should not be enumerable');
-            assert_equals(propDesc.configurable, true, 'constructor should be configurable');
-            assert_equals(propDesc.writable, false, 'constructor should not be writable');
-            assert_equals(typeof controller.constructor, 'object', 'constructor should be an object');
-
-            isStartCalled = true;
-        }
-    };
-
-    var rs = new ReadableStream(source);
-    assert_true(isStartCalled);
-}, 'ReadableStream start should be called with the proper parameters');
-
-test(function()
-{
-    var isStartCalled = false;
-
-    var SimpleStreamSource = function() { };
-    SimpleStreamSource.prototype.start = function() { isStartCalled = true; };
-    SimpleStreamSource.prototype.constructor = SimpleStreamSource;
-
-    var rs = new ReadableStream(new SimpleStreamSource());
-    assert_true(isStartCalled);
-}, 'ReadableStream should be able to call start method within prototype chain of its source');
-
-&lt;/script&gt;
</del></span></pre></div>
<a id="trunkLayoutTestsstreamsreferenceimplementationbadstrategiesexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/streams/reference-implementation/bad-strategies-expected.txt (0 => 185586)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/streams/reference-implementation/bad-strategies-expected.txt                                (rev 0)
+++ trunk/LayoutTests/streams/reference-implementation/bad-strategies-expected.txt        2015-06-16 08:19:04 UTC (rev 185586)
</span><span class="lines">@@ -0,0 +1,30 @@
</span><ins>+
+FAIL Readable stream: throwing strategy.size getter assert_throws: construction should re-throw the error function &quot;function () {
+        new ReadableStream({}, {
+          ...&quot; did not throw
+FAIL Readable stream: throwing strategy.size method assert_throws: enqueue should throw the error function &quot;function () { c.enqueue('a'); }&quot; did not throw
+FAIL Readable stream: throwing strategy.highWaterMark getter assert_throws: construction should re-throw the error function &quot;function () {
+        new ReadableStream({}, {
+          ...&quot; did not throw
+FAIL Readable stream: invalid strategy.highWaterMark assert_throws: construction should throw a RangeError for -1 function &quot;function () {
+            new ReadableStream({}, {
+      ...&quot; did not throw
+FAIL Readable stream: negative strategy.highWaterMark assert_throws: construction should throw a RangeError function &quot;function () {
+        new ReadableStream({}, {
+          ...&quot; did not throw
+FAIL Readable stream: strategy.size returning NaN assert_equals: enqueue should throw a RangeError expected function &quot;function RangeError() {
+    [native code]
+}&quot; but got function &quot;function AssertionError(message)
+    {
+        this.messa...&quot;
+FAIL Readable stream: strategy.size returning -Infinity assert_equals: enqueue should throw a RangeError expected function &quot;function RangeError() {
+    [native code]
+}&quot; but got function &quot;function AssertionError(message)
+    {
+        this.messa...&quot;
+FAIL Readable stream: strategy.size returning +Infinity assert_equals: enqueue should throw a RangeError expected function &quot;function RangeError() {
+    [native code]
+}&quot; but got function &quot;function AssertionError(message)
+    {
+        this.messa...&quot;
+
</ins></span></pre></div>
<a id="trunkLayoutTestsstreamsreferenceimplementationbadstrategieshtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/streams/reference-implementation/bad-strategies.html (0 => 185586)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/streams/reference-implementation/bad-strategies.html                                (rev 0)
+++ trunk/LayoutTests/streams/reference-implementation/bad-strategies.html        2015-06-16 08:19:04 UTC (rev 185586)
</span><span class="lines">@@ -0,0 +1,186 @@
</span><ins>+&lt;!DOCTYPE html&gt;
+&lt;script src='../../resources/testharness.js'&gt;&lt;/script&gt;
+&lt;script src='../../resources/testharnessreport.js'&gt;&lt;/script&gt;
+&lt;script&gt;
+test(function() {
+    var theError = new Error('a unique string');
+
+    assert_throws(theError, function() {
+        new ReadableStream({}, {
+            get size() {
+                throw theError;
+            },
+            highWaterMark: 5
+        });
+    }, 'construction should re-throw the error');
+}, 'Readable stream: throwing strategy.size getter');
+
+var test1 = async_test('Readable stream: throwing strategy.size method');
+test1.step(function() {
+    var theError = new Error('a unique string');
+    var rs = new ReadableStream(
+        {
+            start: function(c) {
+                assert_throws(theError, function() { c.enqueue('a'); }, 'enqueue should throw the error');
+            }
+        },
+        {
+            size: function() {
+                throw theError;
+            },
+            highWaterMark: 5
+        }
+    );
+
+    rs.getReader().closed.catch(test1.step_func(function(e) {
+        assert_equals(e, theError, 'closed should reject with the error');
+        test1.done();
+    }))
+});
+
+test(function() {
+    var theError = new Error('a unique string');
+
+    assert_throws(theError, function() {
+        new ReadableStream({}, {
+            size: function() {
+                return 1;
+            },
+            get highWaterMark() {
+                throw theError;
+            }
+        });
+    }, 'construction should re-throw the error');
+}, 'Readable stream: throwing strategy.highWaterMark getter');
+
+test(function() {
+    for (var highWaterMark of [-1, -Infinity]) {
+        assert_throws(new RangeError(), function() {
+            new ReadableStream({}, {
+                size: function() {
+                    return 1;
+                },
+                highWaterMark
+            });
+        }, 'construction should throw a RangeError for ' + highWaterMark);
+    }
+
+    for (var highWaterMark of [NaN, 'foo', {}]) {
+        assert_throws(new TypeError(), function() {
+            new ReadableStream({}, {
+                size: function() {
+                    return 1;
+                },
+                highWaterMark
+            });
+        }, 'construction should throw a TypeError for ' + highWaterMark);
+    }
+}, 'Readable stream: invalid strategy.highWaterMark');
+
+test(function() {
+    assert_throws(new RangeError(), function() {
+        new ReadableStream({}, {
+            size: function() {
+                return 1;
+            },
+            highWaterMark: -1
+        });
+    }, 'construction should throw a RangeError');
+}, 'Readable stream: negative strategy.highWaterMark');
+
+var test2 = async_test('Readable stream: strategy.size returning NaN');
+test2.step(function() {
+    var theError;
+    var startCalled = false;
+    var rs = new ReadableStream(
+        {
+            start: function(c) {
+                try {
+                    c.enqueue('hi');
+                    assert_unreached('enqueue didn\'t throw');
+                } catch (error) {
+                    startCalled = true;
+                    assert_equals(error.constructor, RangeError, 'enqueue should throw a RangeError');
+                    theError = error;
+                }
+            }
+        },
+        {
+            size: function() {
+                return NaN;
+            },
+            highWaterMark: 5
+        }
+    );
+
+    rs.getReader().closed.catch(test2.step_func(function(e) {
+        assert_equals(e, theError, 'closed should reject with the error');
+        assert_true(startCalled);
+        test2.done();
+    }));
+});
+
+var test3 = async_test('Readable stream: strategy.size returning -Infinity');
+test3.step(function() {
+    var theError;
+    var startCalled = false;
+    var rs = new ReadableStream(
+        {
+            start: function(c) {
+                try {
+                    c.enqueue('hi');
+                    assert_unreached('enqueue didn\'t throw');
+                } catch (error) {
+                    startCalled = true;
+                    assert_equals(error.constructor, RangeError, 'enqueue should throw a RangeError');
+                    theError = error;
+                }
+            }
+        },
+        {
+            size: function() {
+                return -Infinity;
+            },
+            highWaterMark: 5
+        }
+    );
+
+    rs.getReader().closed.catch(test3.step_func(function(e) {
+        assert_equals(e, theError, 'closed should reject with the error');
+        assert_true(startCalled);
+        test3.done();
+    }));
+});
+
+var test4 = async_test('Readable stream: strategy.size returning +Infinity');
+test4.step(function() {
+    var theError;
+    var startCalled = false;
+    var rs = new ReadableStream(
+        {
+            start: function(c) {
+                try {
+                    c.enqueue('hi');
+                    assert_unreached('enqueue didn\'t throw');
+                } catch (error) {
+                    startCalled = true;
+                    assert_equals(error.constructor, RangeError, 'enqueue should throw a RangeError');
+                    theError = error;
+                }
+            }
+        },
+        {
+            size: function() {
+                return +Infinity;
+            },
+            highWaterMark: 5
+        }
+    );
+
+    rs.getReader().closed.catch(test4.step_func(function(e) {
+        assert_equals(e, theError, 'closed should reject with the error');
+        assert_true(startCalled);
+        test4.done();
+    }));
+});
+&lt;/script&gt;
</ins></span></pre></div>
<a id="trunkLayoutTestsstreamsreferenceimplementationbadunderlyingsourcesexpectedtxt"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/streams/reference-implementation/bad-underlying-sources-expected.txt (185585 => 185586)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/streams/reference-implementation/bad-underlying-sources-expected.txt        2015-06-16 07:40:09 UTC (rev 185585)
+++ trunk/LayoutTests/streams/reference-implementation/bad-underlying-sources-expected.txt        2015-06-16 08:19:04 UTC (rev 185586)
</span><span class="lines">@@ -7,14 +7,10 @@
</span><span class="cx"> PASS Underlying source: throwing pull method (second pull) 
</span><span class="cx"> FAIL Underlying source: throwing cancel getter cancel is not implemented
</span><span class="cx"> FAIL Underlying source: throwing cancel method cancel is not implemented
</span><del>-FAIL Underlying source: throwing strategy getter assert_throws: enqueue should throw the error function &quot;function () { c.enqueue('a'); }&quot; did not throw
-FAIL Underlying source: throwing strategy.size getter assert_throws: enqueue should throw the error function &quot;function () { c.enqueue('a'); }&quot; did not throw
-FAIL Underlying source: throwing strategy.size method assert_throws: enqueue should throw the error function &quot;function () { c.enqueue('a'); }&quot; did not throw
-FAIL Underlying source: throwing strategy.shouldApplyBackpressure getter assert_throws: enqueue should throw the error function &quot;function () { c.enqueue('a'); }&quot; did not throw
-FAIL Underlying source: throwing strategy.shouldApplyBackpressure method assert_throws: enqueue should throw the error function &quot;function () { c.enqueue('a'); }&quot; did not throw
-FAIL Underlying source: strategy.size returning NaN assert_unreached: enqueue didn't throw Reached unreachable code
-FAIL Underlying source: strategy.size returning -Infinity assert_unreached: enqueue didn't throw Reached unreachable code
-FAIL Underlying source: strategy.size returning +Infinity assert_unreached: enqueue didn't throw Reached unreachable code
</del><ins>+FAIL Underlying source: calling enqueue on an empty canceled stream should not throw cancel is not implemented
+FAIL Underlying source: calling enqueue on a non-empty canceled stream should not throw cancel is not implemented
+PASS Underlying source: calling enqueue on a closed stream should throw 
+PASS Underlying source: calling enqueue on an errored stream should throw 
</ins><span class="cx"> PASS Underlying source: calling close twice on an empty stream should throw the second time 
</span><span class="cx"> PASS Underlying source: calling close twice on a non-empty stream should throw the second time 
</span><span class="cx"> FAIL Underlying source: calling close on an empty canceled stream should not throw cancel is not implemented
</span><span class="lines">@@ -22,4 +18,6 @@
</span><span class="cx"> PASS Underlying source: calling close after error should throw 
</span><span class="cx"> PASS Underlying source: calling error twice should throw the second time 
</span><span class="cx"> PASS Underlying source: calling error after close should throw 
</span><ins>+PASS Underlying source: calling error and returning a rejected promise from start should cause the stream to error with the first error 
+PASS Underlying source: calling error and returning a rejected promise from pull should cause the stream to error with the first error 
</ins><span class="cx"> 
</span></span></pre></div>
<a id="trunkLayoutTestsstreamsreferenceimplementationbadunderlyingsourceshtml"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/streams/reference-implementation/bad-underlying-sources.html (185585 => 185586)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/streams/reference-implementation/bad-underlying-sources.html        2015-06-16 07:40:09 UTC (rev 185585)
+++ trunk/LayoutTests/streams/reference-implementation/bad-underlying-sources.html        2015-06-16 08:19:04 UTC (rev 185586)
</span><span class="lines">@@ -149,231 +149,80 @@
</span><span class="cx">         }));
</span><span class="cx"> });
</span><span class="cx"> 
</span><del>-var test7 = async_test('Underlying source: throwing strategy getter', { timeout: 50 });
</del><ins>+var test7 = async_test('Underlying source: calling enqueue on an empty canceled stream should not throw');
</ins><span class="cx"> test7.step(function() {
</span><del>-    var started = false;
-    var theError = new Error('a unique string');
-
</del><ins>+    var controller;
</ins><span class="cx">     var rs = new ReadableStream({
</span><span class="cx">         start: function(c) {
</span><del>-            started = true;
-            assert_throws(theError, function() { c.enqueue('a'); }, 'enqueue should throw the error');
-        },
-        get strategy() {
-            throw theError;
</del><ins>+            controller = c;
</ins><span class="cx">         }
</span><span class="cx">     });
</span><span class="cx"> 
</span><del>-    rs.getReader().closed.catch(test7.step_func(function(e) {
-        assert_true(started);
-        assert_equals(e, theError, 'closed should reject with the error');
-        test7.done();
</del><ins>+    rs.cancel();
+    controller.enqueue('a') // Calling enqueue after canceling should not throw anything.
+
+    rs.getReader().closed.then(test7.step_func(function() {
+        test7.done('closed should fulfill');
</ins><span class="cx">     }));
</span><span class="cx"> });
</span><span class="cx"> 
</span><del>-var test8 = async_test('Underlying source: throwing strategy.size getter', { timeout: 50 });
</del><ins>+var test8 = async_test('Underlying source: calling enqueue on a non-empty canceled stream should not throw');
</ins><span class="cx"> test8.step(function() {
</span><del>-    var started = false;
-    var theError = new Error('a unique string');
</del><ins>+    var controller;
</ins><span class="cx">     var rs = new ReadableStream({
</span><span class="cx">         start: function(c) {
</span><del>-            started = true;
-            assert_throws(theError, function() { c.enqueue('a'); }, 'enqueue should throw the error');
-        },
-        strategy: {
-            get size() {
-                throw theError;
-            },
-            shouldApplyBackpressure: function() {
-                return true;
-            }
</del><ins>+            c.enqueue('a');
+            c.enqueue('b');
+            controller = c;
</ins><span class="cx">         }
</span><span class="cx">     });
</span><span class="cx"> 
</span><del>-    rs.getReader().closed.catch(test8.step_func(function(e) {
-        assert_true(started);
-        assert_equals(e, theError, 'closed should reject with the error');
-        test8.done();
</del><ins>+    rs.cancel();
+    controller.enqueue('c') // Calling enqueue after canceling should not throw anything.
+
+    rs.getReader().closed.then(test8.step_func(function() {
+        test8.done('closed should fulfill');
</ins><span class="cx">     }));
</span><span class="cx"> });
</span><span class="cx"> 
</span><del>-var test9 = async_test('Underlying source: throwing strategy.size method', { timeout: 50 });
</del><ins>+var test9 = async_test('Underlying source: calling enqueue on a closed stream should throw');
</ins><span class="cx"> test9.step(function() {
</span><del>-    var started = false;
-    var theError = new Error('a unique string');
-    var rs = new ReadableStream({
</del><ins>+    new ReadableStream({
</ins><span class="cx">         start: function(c) {
</span><del>-            started = true;
-            assert_throws(theError, function() { c.enqueue('a'); }, 'enqueue should throw the error');
-        },
-        strategy: {
-            size: function() {
-                throw theError;
-            },
-            shouldApplyBackpressure: function() {
-                return true;
-            }
</del><ins>+            c.close();
+            assert_throws(new TypeError(), function() { c.enqueue('a') }, 'call to enqueue should throw a TypeError');
</ins><span class="cx">         }
</span><del>-    });
-
-    rs.getReader().closed.catch(test9.step_func(function(e) {
-        assert_true(started);
-        assert_equals(e, theError, 'closed should reject with the error');
-        test9.done();
</del><ins>+    }).getReader().closed.then(test9.step_func(function() {
+        test9.done('closed should fulfill');
</ins><span class="cx">     }));
</span><span class="cx"> });
</span><span class="cx"> 
</span><del>-var test10 = async_test('Underlying source: throwing strategy.shouldApplyBackpressure getter', { timeout: 50 });
</del><ins>+var test10 = async_test('Underlying source: calling enqueue on an errored stream should throw');
</ins><span class="cx"> test10.step(function() {
</span><del>-    var started = false;
-    var theError = new Error('a unique string');
-    var rs = new ReadableStream({
</del><ins>+    var theError = new Error('boo');
+    new ReadableStream({
</ins><span class="cx">         start: function(c) {
</span><del>-            started = true;
-            assert_throws(theError, function() { c.enqueue('a'); }, 'enqueue should throw the error');
-        },
-        strategy: {
-            size: function() {
-                return 1;
-            },
-            get shouldApplyBackpressure() {
-                throw theError;
-            }
</del><ins>+            c.error(theError);
+            assert_throws(theError, function() { c.enqueue('a') }, 'call to enqueue should throw the error');
</ins><span class="cx">         }
</span><del>-    });
-
-    rs.getReader().closed.catch(test10.step_func(function(e) {
-        assert_true(started);
</del><ins>+    }).getReader().closed.catch(test10.step_func(function(e) {
</ins><span class="cx">         assert_equals(e, theError, 'closed should reject with the error');
</span><span class="cx">         test10.done();
</span><span class="cx">     }));
</span><span class="cx"> });
</span><span class="cx"> 
</span><del>-var test11 = async_test('Underlying source: throwing strategy.shouldApplyBackpressure method', { timeout: 50 });
</del><ins>+var test11 = async_test('Underlying source: calling close twice on an empty stream should throw the second time');
</ins><span class="cx"> test11.step(function() {
</span><del>-    var started = false;
-    var theError = new Error('a unique string');
-    var rs = new ReadableStream({
-        start: function(c) {
-            started = true;
-            assert_throws(theError, function() { c.enqueue('a'); }, 'enqueue should throw the error');
-        },
-        strategy: {
-            size: function() {
-                return 1;
-            },
-            shouldApplyBackpressure: function() {
-                throw theError;
-            }
-        }
-    });
-
-    rs.getReader().closed.catch(test11.step_func(function(e) {
-        assert_true(started);
-        assert_equals(e, theError, 'closed should reject with the error');
-        test11.done();
-    }));
-});
-
-var test12 = async_test('Underlying source: strategy.size returning NaN', { timeout: 50 });
-test12.step(function() {
-    var theError = undefined;
-    var rs = new ReadableStream({
-        start: function(c) {
-            try {
-                c.enqueue('hi');
-                assert_unreached('enqueue didn\'t throw');
-            } catch (error) {
-                theError = error;
-                assert_throws(new RangeError(), function() { throw error; }, 'enqueue should throw a RangeError');
-            }
-        },
-        strategy: {
-            size: function() {
-                return NaN;
-            },
-            shouldApplyBackpressure: function() {
-                return true;
-            }
-        }
-    });
-
-    rs.getReader().closed.catch(test12.step_func(function(e) {
-        assert_equals(e, theError, 'closed should reject with the error');
-        test12.done();
-    }));
-});
-
-var test13 = async_test('Underlying source: strategy.size returning -Infinity', { timeout: 50 });
-test13.step(function() {
-    var theError = undefined;
-    var rs = new ReadableStream({
-        start: function(c) {
-            try {
-                c.enqueue('hi');
-                assert_unreached('enqueue didn\'t throw');
-            } catch (error) {
-                theError = error;
-                assert_throws(new RangeError(), function() { throw error; }, 'enqueue should throw a RangeError');
-            }
-        },
-        strategy: {
-            size: function() {
-                return -Infinity;
-            },
-            shouldApplyBackpressure: function() {
-                return true;
-            }
-        }
-    });
-
-    rs.getReader().closed.catch(test13.step_func(function(e) {
-        assert_equals(e, theError, 'closed should reject with the error');
-        test13.done();
-    }));
-});
-
-var test14 = async_test('Underlying source: strategy.size returning +Infinity', { timeout: 50 });
-test14.step(function() {
-    var theError = undefined;
-    var rs = new ReadableStream({
-        start: function(c) {
-            try {
-                c.enqueue('hi');
-                assert_unreached('enqueue didn\'t throw');
-            } catch (error) {
-                theError = error;
-                assert_throws(new RangeError(), function() { throw error; }, 'enqueue should throw a RangeError');
-            }
-        },
-        strategy: {
-            size: function() {
-                return +Infinity;
-            },
-            shouldApplyBackpressure: function() {
-                return true;
-            }
-        }
-    });
-
-    rs.getReader().closed.catch(test14.step_func(function(e) {
-        assert_equals(e, theError, 'closed should reject with the error');
-        test14.done();
-    }));
-});
-
-var test15 = async_test('Underlying source: calling close twice on an empty stream should throw the second time');
-test15.step(function() {
</del><span class="cx">     new ReadableStream({
</span><span class="cx">         start: function(c) {
</span><span class="cx">             c.close();
</span><span class="cx">             assert_throws(new TypeError(), c.close, 'second call to close should throw a TypeError');
</span><span class="cx">         }
</span><del>-    }).getReader().closed.then(test15.step_func(function() { test15.done('closed should fulfill'); }));
</del><ins>+    }).getReader().closed.then(test11.step_func(function() { test11.done('closed should fulfill'); }));
</ins><span class="cx"> });
</span><span class="cx"> 
</span><del>-var test16 = async_test('Underlying source: calling close twice on a non-empty stream should throw the second time');
-test16.step(function() {
</del><ins>+var test12 = async_test('Underlying source: calling close twice on a non-empty stream should throw the second time');
+test12.step(function() {
</ins><span class="cx">     var startCalled = false;
</span><span class="cx">     var readCalled = false;
</span><span class="cx">     var reader = new ReadableStream({
</span><span class="lines">@@ -385,19 +234,19 @@
</span><span class="cx">         }
</span><span class="cx">     }).getReader();
</span><span class="cx"> 
</span><del>-    reader.read().then(test16.step_func(function(r) {
</del><ins>+    reader.read().then(test12.step_func(function(r) {
</ins><span class="cx">         assert_object_equals(r, { value: 'a', done: false }, 'read() should read the enqueued chunk');
</span><span class="cx">         readCalled = true;
</span><span class="cx">     }));
</span><del>-    reader.closed.then(test16.step_func(function() {
</del><ins>+    reader.closed.then(test12.step_func(function() {
</ins><span class="cx">         assert_true(startCalled);
</span><span class="cx">         assert_true(readCalled);
</span><del>-        test16.done('closed should fulfill');
</del><ins>+        test12.done('closed should fulfill');
</ins><span class="cx">     }));
</span><span class="cx"> });
</span><span class="cx"> 
</span><del>-var test17 = async_test('Underlying source: calling close on an empty canceled stream should not throw');
-test17.step(function() {
</del><ins>+var test13 = async_test('Underlying source: calling close on an empty canceled stream should not throw');
+test13.step(function() {
</ins><span class="cx">     var controller;
</span><span class="cx">     var startCalled = false;
</span><span class="cx">     var rs = new ReadableStream({
</span><span class="lines">@@ -410,14 +259,14 @@
</span><span class="cx">     rs.cancel();
</span><span class="cx">     controller.close(); // Calling close after canceling should not throw anything.
</span><span class="cx"> 
</span><del>-    rs.getReader().closed.then(test17.step_func(function() {
</del><ins>+    rs.getReader().closed.then(test13.step_func(function() {
</ins><span class="cx">         assert_true(startCalled);
</span><del>-        test17.done('closed should fulfill');
</del><ins>+        test13.done('closed should fulfill');
</ins><span class="cx">     }));
</span><span class="cx"> });
</span><span class="cx"> 
</span><del>-var test18 = async_test('Underlying source: calling close on a non-empty canceled stream should not throw');
-test18.step(function() {
</del><ins>+var test14 = async_test('Underlying source: calling close on a non-empty canceled stream should not throw');
+test14.step(function() {
</ins><span class="cx">     var controller;
</span><span class="cx">     var startCalled = false;
</span><span class="cx">     var rs = new ReadableStream({
</span><span class="lines">@@ -431,14 +280,14 @@
</span><span class="cx">     rs.cancel();
</span><span class="cx">     controller.close(); // Calling close after canceling should not throw anything.
</span><span class="cx"> 
</span><del>-    rs.getReader().closed.then(test18.step_func(function() {
</del><ins>+    rs.getReader().closed.then(test14.step_func(function() {
</ins><span class="cx">         assert_true(startCalled);
</span><del>-        test18.done('closed should fulfill');
</del><ins>+        test14.done('closed should fulfill');
</ins><span class="cx">     }));
</span><span class="cx"> });
</span><span class="cx"> 
</span><del>-var test19 = async_test('Underlying source: calling close after error should throw');
-test19.step(function() {
</del><ins>+var test15 = async_test('Underlying source: calling close after error should throw');
+test15.step(function() {
</ins><span class="cx">     var theError = new Error('boo');
</span><span class="cx">     var startCalled = false;
</span><span class="cx">     new ReadableStream({
</span><span class="lines">@@ -447,15 +296,15 @@
</span><span class="cx">             assert_throws(new TypeError(), c.close, 'call to close should throw a TypeError');
</span><span class="cx">             startCalled = true;
</span><span class="cx">         }
</span><del>-    }).getReader().closed.catch(test19.step_func(function(e) {
</del><ins>+    }).getReader().closed.catch(test15.step_func(function(e) {
</ins><span class="cx">         assert_true(startCalled);
</span><span class="cx">         assert_equals(e, theError, 'closed should reject with the error')
</span><del>-        test19.done();
</del><ins>+        test15.done();
</ins><span class="cx">     }));
</span><span class="cx"> });
</span><span class="cx"> 
</span><del>-var test20 = async_test('Underlying source: calling error twice should throw the second time');
-test20.step(function() {
</del><ins>+var test16 = async_test('Underlying source: calling error twice should throw the second time');
+test16.step(function() {
</ins><span class="cx">     var theError = new Error('boo');
</span><span class="cx">     var startCalled = false;
</span><span class="cx">     new ReadableStream({
</span><span class="lines">@@ -464,15 +313,15 @@
</span><span class="cx">             assert_throws(new TypeError(), c.error, 'second call to error should throw a TypeError');
</span><span class="cx">             startCalled = true;
</span><span class="cx">         }
</span><del>-    }).getReader().closed.catch(test20.step_func(function(e) {
</del><ins>+    }).getReader().closed.catch(test16.step_func(function(e) {
</ins><span class="cx">         assert_true(startCalled);
</span><span class="cx">         assert_equals(e, theError, 'closed should reject with the error');
</span><del>-        test20.done();
</del><ins>+        test16.done();
</ins><span class="cx">     }));
</span><span class="cx"> });
</span><span class="cx"> 
</span><del>-var test21 = async_test('Underlying source: calling error after close should throw');
-test21.step(function() {
</del><ins>+var test17 = async_test('Underlying source: calling error after close should throw');
+test17.step(function() {
</ins><span class="cx">     var startCalled = false;
</span><span class="cx">     new ReadableStream({
</span><span class="cx">         start: function(c) {
</span><span class="lines">@@ -480,9 +329,49 @@
</span><span class="cx">             assert_throws(new TypeError(), c.error, 'call to error should throw a TypeError');
</span><span class="cx">             startCalled = true;
</span><span class="cx">         }
</span><del>-    }).getReader().closed.then(test21.step_func(function() {
</del><ins>+    }).getReader().closed.then(test17.step_func(function() {
</ins><span class="cx">         assert_true(startCalled);
</span><del>-        test21.done('closed should fulfill');
</del><ins>+        test17.done('closed should fulfill');
</ins><span class="cx">     }));
</span><span class="cx"> });
</span><ins>+
+var test18 = async_test('Underlying source: calling error and returning a rejected promise from start should cause the stream to error with the first error');
+test18.step(function() {
+    var startCalled = false;
+    var firstError = new Error('1');
+    var secondError = new Error('2');
+    new ReadableStream({
+        start: function(c) {
+            c.error(firstError);
+
+            startCalled = true;
+
+            return Promise.reject(secondError);
+        }
+    }).getReader().closed.catch(test18.step_func(function(e) {
+        assert_true(startCalled);
+        assert_equals(e, firstError, 'stream should error with the first error');
+        test18.done();
+    }));
+});
+
+var test19 = async_test('Underlying source: calling error and returning a rejected promise from pull should cause the stream to error with the first error');
+test19.step(function() {
+    var startCalled = false;
+    var firstError = new Error('1');
+    var secondError = new Error('2');
+    new ReadableStream({
+        pull: function(c) {
+            c.error(firstError);
+
+            startCalled = true;
+
+            return Promise.reject(secondError);
+        }
+    }).getReader().closed.catch(test19.step_func(function(e) {
+        assert_true(startCalled);
+        assert_equals(e, firstError, 'stream should error with the first error');
+        test19.done();
+    }));
+});
</ins><span class="cx"> &lt;/script&gt;
</span></span></pre></div>
<a id="trunkLayoutTestsstreamsreferenceimplementationbrandchecksexpectedtxt"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/streams/reference-implementation/brand-checks-expected.txt (185585 => 185586)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/streams/reference-implementation/brand-checks-expected.txt        2015-06-16 07:40:09 UTC (rev 185585)
+++ trunk/LayoutTests/streams/reference-implementation/brand-checks-expected.txt        2015-06-16 08:19:04 UTC (rev 185586)
</span><span class="lines">@@ -1,18 +1,18 @@
</span><span class="cx"> 
</span><span class="cx"> PASS Can get the ReadableStreamReader constructor indirectly 
</span><span class="cx"> PASS Can get the ReadableStreamController constructor indirectly 
</span><ins>+FAIL ReadableStream.prototype.pipeThrough works generically on its this and its arguments Can only call ReadableStream.pipeThrough on instances of ReadableStream
</ins><span class="cx"> PASS ReadableStreamReader enforces a brand check on its argument 
</span><span class="cx"> FAIL ReadableStreamReader.prototype.closed enforces a brand check undefined is not an object (evaluating 'Object.getOwnPropertyDescriptor(obj, getterName).get')
</span><span class="cx"> FAIL ReadableStreamReader.prototype.cancel enforces a brand check Can only call ReadableStreamReader.cancel on instances of ReadableStreamReader
</span><span class="cx"> FAIL ReadableStreamReader.prototype.read enforces a brand check Can only call ReadableStreamReader.read on instances of ReadableStreamReader
</span><ins>+FAIL ReadableStreamReader.prototype.read enforces a brand check Can only call ReadableStreamReader.read on instances of ReadableStreamReader
</ins><span class="cx"> PASS ReadableStreamReader.prototype.releaseLock enforces a brand check 
</span><span class="cx"> PASS ReadableStreamController enforces a brand check on its argument 
</span><span class="cx"> PASS ReadableStreamController can't be given a fully-constructed ReadableStream 
</span><span class="cx"> PASS ReadableStreamController.prototype.close enforces a brand check 
</span><span class="cx"> PASS ReadableStreamController.prototype.enqueue enforces a brand check 
</span><span class="cx"> PASS ReadableStreamController.prototype.error enforces a brand check 
</span><del>-PASS ByteLengthQueuingStrategy.prototype.shouldApplyBackpressure enforces a brand check 
</del><span class="cx"> PASS ByteLengthQueuingStrategy.prototype.size should work generically on its this and its arguments 
</span><del>-PASS CountQueuingStrategy.prototype.shouldApplyBackpressure enforces a brand check 
</del><span class="cx"> PASS CountQueuingStrategy.prototype.size should work generically on its this and its arguments 
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkLayoutTestsstreamsreferenceimplementationbrandcheckshtml"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/streams/reference-implementation/brand-checks.html (185585 => 185586)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/streams/reference-implementation/brand-checks.html        2015-06-16 07:40:09 UTC (rev 185585)
+++ trunk/LayoutTests/streams/reference-implementation/brand-checks.html        2015-06-16 08:19:04 UTC (rev 185586)
</span><span class="lines">@@ -25,9 +25,10 @@
</span><span class="cx"> function fakeReadableStream() {
</span><span class="cx">     return {
</span><span class="cx">         cancel: function(reason) { return Promise.resolve(); },
</span><ins>+        getReader: function() { return new ReadableStream(new ReadableStream()); },
</ins><span class="cx">         pipeThrough: function(obj, options) { return obj.readable; },
</span><span class="cx">         pipeTo: function() { return Promise.resolve(); },
</span><del>-        getReader: function() { return new ReadableStream(new ReadableStream()); }
</del><ins>+        tee: function() { return [realReadableStream(), realReadableStream()]; }
</ins><span class="cx">     };
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -54,9 +55,7 @@
</span><span class="cx"> 
</span><span class="cx"> function fakeByteLengthQueuingStrategy() {
</span><span class="cx">     return {
</span><del>-        shouldApplyBackpressure: function(queueSize) {
-            return queueSize &gt; 1;
-        },
</del><ins>+        highWaterMark: 0,
</ins><span class="cx">         size: function(chunk) {
</span><span class="cx">             return chunk.byteLength;
</span><span class="cx">         }
</span><span class="lines">@@ -64,22 +63,20 @@
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> function realByteLengthQueuingStrategy() {
</span><del>-    return new ByteLengthQueuingStrategy({ &quot;highWaterMark&quot;: 1});
</del><ins>+    return new ByteLengthQueuingStrategy({ highWaterMark: 1 });
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> function fakeCountQueuingStrategy() {
</span><span class="cx">     return {
</span><del>-        shouldApplyBackpressure: function(queueSize) {
-            return queueSize &gt; 1;
-        },
</del><ins>+        highWaterMark: 0,
</ins><span class="cx">         size: function(chunk) {
</span><span class="cx">             return 1;
</span><span class="cx">         }
</span><del>-    };
</del><ins>+    }
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> function realCountQueuingStrategy() {
</span><del>-    return new CountQueuingStrategy({ &quot;highWaterMark&quot;: 1});
</del><ins>+    return new CountQueuingStrategy({ highWaterMark: 1 });
</ins><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> function getterRejects(test, obj, getterName, target, endTest) {
</span><span class="lines">@@ -115,6 +112,22 @@
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="cx"> test(function() {
</span><ins>+    var pipeToArguments;
+    var thisValue = {
+        pipeTo: function() {
+            pipeToArguments = arguments;
+        }
+    };
+
+    var input = { readable: {}, writable: {} };
+    var options = {};
+    var result = ReadableStream.prototype.pipeThrough.call(thisValue, input, options);
+
+    assert_array_equals(pipeToArguments, [input.writable, options], 'correct arguments should be passed to thisValue.pipeTo');
+    assert_equals(result, input.readable, 'return value should be the passed readable property');
+}, 'ReadableStream.prototype.pipeThrough works generically on its this and its arguments');
+
+test(function() {
</ins><span class="cx">     assert_throws(new TypeError(), function() { new ReadableStreamReader(fakeReadableStream()); }, 'Constructing a ReadableStreamReader should throw');
</span><span class="cx"> }, 'ReadableStreamReader enforces a brand check on its argument');
</span><span class="cx"> 
</span><span class="lines">@@ -136,6 +149,12 @@
</span><span class="cx">     methodRejects(test3, ReadableStreamReader.prototype, 'read', realReadableStream(), true);
</span><span class="cx"> });
</span><span class="cx"> 
</span><ins>+var test4 = async_test('ReadableStreamReader.prototype.read enforces a brand check');
+test4.step(function() {
+    methodRejects(test4, ReadableStreamReader.prototype, 'read', fakeReadableStreamReader());
+    methodRejects(test4, ReadableStreamReader.prototype, 'read', realReadableStream(), true);
+});
+
</ins><span class="cx"> test(function() {
</span><span class="cx">     methodThrows(ReadableStreamReader.prototype, 'releaseLock', fakeReadableStreamReader());
</span><span class="cx">     methodThrows(ReadableStreamReader.prototype, 'releaseLock', realReadableStream());
</span><span class="lines">@@ -162,11 +181,6 @@
</span><span class="cx"> }, 'ReadableStreamController.prototype.error enforces a brand check');
</span><span class="cx"> 
</span><span class="cx"> test(function() {
</span><del>-    methodThrows(ByteLengthQueuingStrategy.prototype, 'shouldApplyBackpressure', fakeByteLengthQueuingStrategy());
-    methodThrows(ByteLengthQueuingStrategy.prototype, 'shouldApplyBackpressure', realCountQueuingStrategy());
-}, 'ByteLengthQueuingStrategy.prototype.shouldApplyBackpressure enforces a brand check');
-
-test(function() {
</del><span class="cx">     var thisValue = null;
</span><span class="cx">     var returnValue = { 'returned from': 'byteLength getter' };
</span><span class="cx">     var chunk = {
</span><span class="lines">@@ -179,11 +193,6 @@
</span><span class="cx"> }, 'ByteLengthQueuingStrategy.prototype.size should work generically on its this and its arguments');
</span><span class="cx"> 
</span><span class="cx"> test(function() {
</span><del>-    methodThrows(CountQueuingStrategy.prototype, 'shouldApplyBackpressure', fakeCountQueuingStrategy());
-    methodThrows(CountQueuingStrategy.prototype, 'shouldApplyBackpressure', realByteLengthQueuingStrategy());
-}, 'CountQueuingStrategy.prototype.shouldApplyBackpressure enforces a brand check');
-
-test(function() {
</del><span class="cx">     var thisValue = null;
</span><span class="cx">     var chunk = {
</span><span class="cx">         get byteLength() {
</span></span></pre></div>
<a id="trunkLayoutTestsstreamsreferenceimplementationbytelengthqueuingstrategyexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/streams/reference-implementation/byte-length-queuing-strategy-expected.txt (0 => 185586)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/streams/reference-implementation/byte-length-queuing-strategy-expected.txt                                (rev 0)
+++ trunk/LayoutTests/streams/reference-implementation/byte-length-queuing-strategy-expected.txt        2015-06-16 08:19:04 UTC (rev 185586)
</span><span class="lines">@@ -0,0 +1,5 @@
</span><ins>+
+PASS Can construct a ByteLengthQueuingStrategy with a valid high water mark 
+PASS Can construct a ByteLengthQueuingStrategy with any value as its high water mark 
+PASS ByteLengthQueuingStrategy instances have the correct properties 
+
</ins></span></pre></div>
<a id="trunkLayoutTestsstreamsreferenceimplementationbytelengthqueuingstrategyhtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/streams/reference-implementation/byte-length-queuing-strategy.html (0 => 185586)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/streams/reference-implementation/byte-length-queuing-strategy.html                                (rev 0)
+++ trunk/LayoutTests/streams/reference-implementation/byte-length-queuing-strategy.html        2015-06-16 08:19:04 UTC (rev 185586)
</span><span class="lines">@@ -0,0 +1,26 @@
</span><ins>+&lt;!DOCTYPE html&gt;
+&lt;script src='../../resources/testharness.js'&gt;&lt;/script&gt;
+&lt;script src='../../resources/testharnessreport.js'&gt;&lt;/script&gt;
+&lt;script src='resources/streams-utils.js'&gt;&lt;/script&gt;
+&lt;script src='resources/byte-length-queuing-strategy.js'&gt;&lt;/script&gt;
+&lt;script&gt;
+test(function() {
+    var strategy = new ByteLengthQueuingStrategy({ highWaterMark: 4 });
+}, 'Can construct a ByteLengthQueuingStrategy with a valid high water mark');
+
+test(function() {
+    for (var highWaterMark of [-Infinity, NaN, 'foo', {}, function () {}]) {
+        var strategy = new ByteLengthQueuingStrategy({ highWaterMark });
+        assert_true(Object.is(strategy.highWaterMark, highWaterMark), highWaterMark + ' gets set correctly');
+    }
+}, 'Can construct a ByteLengthQueuingStrategy with any value as its high water mark');
+
+test(function() {
+    var strategy = new ByteLengthQueuingStrategy({ highWaterMark: 4 });
+
+    assert_object_equals(Object.getOwnPropertyDescriptor(strategy, 'highWaterMark'),
+                         { value: 4, writable: true, enumerable: true, configurable: true },
+                         'highWaterMark property should be a data property with the value passed the connstructor');
+    assert_equals(typeof strategy.size, 'function');
+}, 'ByteLengthQueuingStrategy instances have the correct properties');
+&lt;/script&gt;
</ins></span></pre></div>
<a id="trunkLayoutTestsstreamsreferenceimplementationcountqueuingstrategyexpectedtxt"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/streams/reference-implementation/count-queuing-strategy-expected.txt (185585 => 185586)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/streams/reference-implementation/count-queuing-strategy-expected.txt        2015-06-16 07:40:09 UTC (rev 185585)
+++ trunk/LayoutTests/streams/reference-implementation/count-queuing-strategy-expected.txt        2015-06-16 08:19:04 UTC (rev 185586)
</span><span class="lines">@@ -1,8 +1,9 @@
</span><span class="cx"> 
</span><span class="cx"> PASS Can construct a CountQueuingStrategy with a valid high water mark 
</span><del>-PASS Gives a RangeError when the number is negative 
</del><ins>+PASS Can construct a CountQueuingStrategy with any value as its high water mark 
+PASS CountQueuingStrategy instances have the correct properties 
</ins><span class="cx"> PASS Can construct a readable stream with a valid CountQueuingStrategy 
</span><del>-FAIL Correctly governs the return value of a ReadableStream's enqueue function (HWM = 0) assert_equals: After 0 reads, 1st enqueue should return false (queue now contains 1 chunk) expected (boolean) false but got (undefined) undefined
-FAIL Correctly governs the return value of a ReadableStream's enqueue function (HWM = 1) assert_equals: After 0 reads, 1st enqueue should return true (queue now contains 1 chunk) expected (boolean) true but got (undefined) undefined
-FAIL Correctly governs the return value of a ReadableStream's enqueue function (HWM = 4) assert_equals: After 0 reads, 1st enqueue should return true (queue now contains 1 chunk) expected (boolean) true but got (undefined) undefined
</del><ins>+FAIL Correctly governs the return value of a ReadableStream's enqueue function (HWM = 0) assert_equals: 0 reads, 0 enqueues: desiredSize should be 0 expected (number) 0 but got (undefined) undefined
+FAIL Correctly governs a ReadableStreamController's desiredSize property (HWM = 1) assert_equals: 0 reads, 0 enqueues: desiredSize should be 1 expected (number) 1 but got (undefined) undefined
+FAIL Correctly governs a ReadableStreamController's desiredSize property (HWM = 4) assert_equals: 0 reads, 0 enqueues: desiredSize should be 4 expected (number) 4 but got (undefined) undefined
</ins><span class="cx"> 
</span></span></pre></div>
<a id="trunkLayoutTestsstreamsreferenceimplementationcountqueuingstrategyhtml"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/streams/reference-implementation/count-queuing-strategy.html (185585 => 185586)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/streams/reference-implementation/count-queuing-strategy.html        2015-06-16 07:40:09 UTC (rev 185585)
+++ trunk/LayoutTests/streams/reference-implementation/count-queuing-strategy.html        2015-06-16 08:19:04 UTC (rev 185586)
</span><span class="lines">@@ -5,31 +5,50 @@
</span><span class="cx"> &lt;script src='resources/count-queuing-strategy.js'&gt;&lt;/script&gt;
</span><span class="cx"> &lt;script&gt;
</span><span class="cx"> test(function() {
</span><del>-    new CountQueuingStrategy({ &quot;highWaterMark&quot;: 4});
</del><ins>+    new CountQueuingStrategy({ highWaterMark: 4 });
</ins><span class="cx"> }, 'Can construct a CountQueuingStrategy with a valid high water mark');
</span><span class="cx"> 
</span><span class="cx"> test(function() {
</span><del>-    assert_throws(new RangeError(), function() { new CountQueuingStrategy({ &quot;highWaterMark&quot;: -4 }) }, 'throws for { highWaterMark: -4 }');
-    assert_throws(new RangeError(), function() { new CountQueuingStrategy({ &quot;highWaterMark&quot;: '-4' }) }, 'throws for { highWaterMark: \'-4\' }');
-}, 'Gives a RangeError when the number is negative');
</del><ins>+    for (var highWaterMark of [-Infinity, NaN, 'foo', {}, function () {}]) {
+        var strategy = new CountQueuingStrategy({ highWaterMark });
+        assert_true(Object.is(strategy.highWaterMark, highWaterMark), highWaterMark + ' gets set correctly');
+    }
+}, 'Can construct a CountQueuingStrategy with any value as its high water mark');
</ins><span class="cx"> 
</span><span class="cx"> test(function() {
</span><del>-    new ReadableStream({ strategy: new CountQueuingStrategy({ &quot;highWaterMark&quot;: 4 }) });
</del><ins>+    var strategy = new CountQueuingStrategy({ highWaterMark: 4 });
+
+    assert_object_equals(Object.getOwnPropertyDescriptor(strategy, 'highWaterMark'),
+                         { value: 4, writable: true, enumerable: true, configurable: true },
+                         'highWaterMark property should be a data property with the value passed the connstructor');
+    assert_equals(typeof strategy.size, 'function');
+}, 'CountQueuingStrategy instances have the correct properties');
+
+test(function() {
+    new ReadableStream({}, new CountQueuingStrategy({ highWaterMark: 4 }));
</ins><span class="cx"> }, 'Can construct a readable stream with a valid CountQueuingStrategy');
</span><span class="cx"> 
</span><span class="cx"> var test1 = async_test('Correctly governs the return value of a ReadableStream\'s enqueue function (HWM = 0)');
</span><span class="cx"> test1.step(function() {
</span><del>-    var enqueue;
</del><ins>+    var controller;
</ins><span class="cx">     var rs = new ReadableStream({
</span><del>-        start: function(c) { enqueue = c.enqueue.bind(c); },
-        strategy: new CountQueuingStrategy({ &quot;highWaterMark&quot;: 0 })
-    });
</del><ins>+        start: function(c) {
+            controller = c;
+        }
+    },
+    new CountQueuingStrategy({ highWaterMark: 0 })
+    );
</ins><span class="cx">     var reader = rs.getReader();
</span><span class="cx"> 
</span><del>-    assert_equals(enqueue('a'), false, 'After 0 reads, 1st enqueue should return false (queue now contains 1 chunk)');
-    assert_equals(enqueue('b'), false, 'After 0 reads, 2nd enqueue should return false (queue now contains 2 chunks)');
-    assert_equals(enqueue('c'), false, 'After 0 reads, 3rd enqueue should return false (queue now contains 3 chunks)');
-    assert_equals(enqueue('d'), false, 'After 0 reads, 4th enqueue should return false (queue now contains 4 chunks)');
</del><ins>+    assert_equals(controller.desiredSize, 0, '0 reads, 0 enqueues: desiredSize should be 0');
+    controller.enqueue('a');
+    assert_equals(controller.desiredSize, -1, '0 reads, 1 enqueue: desiredSize should be -1');
+    controller.enqueue('b');
+    assert_equals(controller.desiredSize, -2, '0 reads, 2 enqueues: desiredSize should be -2');
+    controller.enqueue('c');
+    assert_equals(controller.desiredSize, -3, '0 reads, 3 enqueues: desiredSize should be -3');
+    controller.enqueue('d');
+    assert_equals(controller.desiredSize, -4, '0 reads, 4 enqueues: desiredSize should be -4');
</ins><span class="cx"> 
</span><span class="cx">     reader.read().then(test1.step_func(function(result) {
</span><span class="cx">         assert_object_equals(result, { value: 'a', done: false }, '1st read gives back the 1st chunk enqueued (queue now contains 3 chunks)');
</span><span class="lines">@@ -39,32 +58,49 @@
</span><span class="cx">         return reader.read();
</span><span class="cx">     })).then(test1.step_func(function(result) {
</span><span class="cx">         assert_object_equals(result, { value: 'c', done: false }, '3rd read gives back the 3rd chunk enqueued (queue now contains 1 chunk)');
</span><del>-        assert_equals(enqueue('e'), false, 'After 3 reads, 5th enqueue should return false (queue now contains 2 chunks)');
</del><ins>+
+        assert_equals(controller.desiredSize, -1, '3 reads, 4 enqueues: desiredSize should be -1');
+        controller.enqueue('e');
+        assert_equals(controller.desiredSize, -2, '3 reads, 5 enqueues: desiredSize should be -2');
+
</ins><span class="cx">         return reader.read();
</span><span class="cx">     })).then(test1.step_func(function(result) {
</span><span class="cx">         assert_object_equals(result, { value: 'd', done: false }, '4th read gives back the 4th chunk enqueued (queue now contains 1 chunks)');
</span><span class="cx">         return reader.read();
</span><span class="cx">     })).then(test1.step_func(function(result) {
</span><span class="cx">         assert_object_equals(result, { value: 'e', done: false }, '5th read gives back the 5th chunk enqueued (queue now contains 0 chunks)');
</span><del>-        assert_equals(enqueue('f'), false, 'After 5 reads, 6th enqueue should return false (queue now contains 1 chunk)');
-        assert_equals(enqueue('g'), false, 'After 5 reads, 7th enqueue should return false (queue now contains 2 chunks)');
</del><ins>+
+        assert_equals(controller.desiredSize, 0, '5 reads, 5 enqueues: desiredSize should be 0');
+        controller.enqueue('f');
+        assert_equals(controller.desiredSize, -1, '5 reads, 6 enqueues: desiredSize should be -1');
+        controller.enqueue('g');
+        assert_equals(controller.desiredSize, -2, '5 reads, 7 enqueues: desiredSize should be -2');
+
</ins><span class="cx">         test1.done();
</span><span class="cx">     })).catch(test1.step_func(function(e) { assert_unreached(e); } ));
</span><span class="cx"> });
</span><span class="cx"> 
</span><del>-var test2 = async_test('Correctly governs the return value of a ReadableStream\'s enqueue function (HWM = 1)');
</del><ins>+var test2 = async_test('Correctly governs a ReadableStreamController\'s desiredSize property (HWM = 1)');
</ins><span class="cx"> test2.step(function() {
</span><del>-    var enqueue;
</del><ins>+    var controller;
</ins><span class="cx">     var rs = new ReadableStream({
</span><del>-        start: function(c) { enqueue = c.enqueue.bind(c); },
-        strategy: new CountQueuingStrategy({ &quot;highWaterMark&quot;: 1 })
-    });
</del><ins>+        start: function(c) {
+            controller = c;
+        },
+    },
+    new CountQueuingStrategy({ highWaterMark: 1 })
+    );
</ins><span class="cx">     var reader = rs.getReader();
</span><span class="cx"> 
</span><del>-    assert_equals(enqueue('a'), true, 'After 0 reads, 1st enqueue should return true (queue now contains 1 chunk)');
-    assert_equals(enqueue('b'), false, 'After 0 reads, 2nd enqueue should return false (queue now contains 2 chunks)');
-    assert_equals(enqueue('c'), false, 'After 0 reads, 3rd enqueue should return false (queue now contains 3 chunks)');
-    assert_equals(enqueue('d'), false, 'After 0 reads, 4th enqueue should return false (queue now contains 4 chunks)');
</del><ins>+    assert_equals(controller.desiredSize, 1, '0 reads, 0 enqueues: desiredSize should be 1');
+    controller.enqueue('a');
+    assert_equals(controller.desiredSize, 0, '0 reads, 1 enqueue: desiredSize should be 0');
+    controller.enqueue('b');
+    assert_equals(controller.desiredSize, -1, '0 reads, 2 enqueues: desiredSize should be -1');
+    controller.enqueue('c');
+    assert_equals(controller.desiredSize, -2, '0 reads, 3 enqueues: desiredSize should be -2');
+    controller.enqueue('d');
+    assert_equals(controller.desiredSize, -3, '0 reads, 4 enqueues: desiredSize should be -3');
</ins><span class="cx"> 
</span><span class="cx">     reader.read().then(test2.step_func(function(result) {
</span><span class="cx">         assert_object_equals(result, { value: 'a', done: false }, '1st read gives back the 1st chunk enqueued (queue now contains 3 chunks)');
</span><span class="lines">@@ -74,41 +110,65 @@
</span><span class="cx">         return reader.read();
</span><span class="cx">     })).then(test2.step_func(function(result) {
</span><span class="cx">         assert_object_equals(result, { value: 'c', done: false }, '3rd read gives back the 3rd chunk enqueued (queue now contains 1 chunk)');
</span><del>-        assert_equals(enqueue('e'), false, 'After 3 reads, 5th enqueue should return false (queue now contains 2 chunks)');
</del><ins>+
+        assert_equals(controller.desiredSize, 0, '3 reads, 4 enqueues: desiredSize should be 0');
+        controller.enqueue('e');
+        assert_equals(controller.desiredSize, -1, '3 reads, 5 enqueues: desiredSize should be -1');
+
</ins><span class="cx">         return reader.read();
</span><span class="cx">     })).then(test2.step_func(function(result) {
</span><span class="cx">         assert_object_equals(result, { value: 'd', done: false }, '4th read gives back the 4th chunk enqueued (queue now contains 1 chunks)');
</span><span class="cx">         return reader.read();
</span><span class="cx">     })).then(test2.step_func(function(result) {
</span><span class="cx">         assert_object_equals(result, { value: 'e', done: false }, '5th read gives back the 5th chunk enqueued (queue now contains 0 chunks)');
</span><del>-        assert_equals(enqueue('f'), true, 'After 5 reads, 6th enqueue should return true (queue now contains 1 chunk)');
-        assert_equals(enqueue('g'), false, 'After 5 reads, 7th enqueue should return false (queue now contains 2 chunks)');
</del><ins>+
+        assert_equals(controller.desiredSize, 1, '5 reads, 5 enqueues: desiredSize should be 1');
+        controller.enqueue('f');
+        assert_equals(controller.desiredSize, 0, '5 reads, 6 enqueues: desiredSize should be 0');
+        controller.enqueue('g');
+        assert_equals(controller.desiredSize, -1, '5 reads, 7 enqueues: desiredSize should be -1');
+
</ins><span class="cx">         test2.done();
</span><span class="cx">     })).catch(test2.step_func(function(e) { assert_unreached(e); } ));
</span><span class="cx"> });
</span><span class="cx"> 
</span><del>-var test3 = async_test('Correctly governs the return value of a ReadableStream\'s enqueue function (HWM = 4)');
</del><ins>+var test3 = async_test('Correctly governs a ReadableStreamController\'s desiredSize property (HWM = 4)');
</ins><span class="cx"> test3.step(function() {
</span><del>-    var enqueue;
</del><ins>+    var controller;
</ins><span class="cx">     var rs = new ReadableStream({
</span><del>-        start: function(c) { enqueue = c.enqueue.bind(c); },
-        strategy: new CountQueuingStrategy({ &quot;highWaterMark&quot;: 4 })
-    });
</del><ins>+        start: function(c) {
+            controller = c;
+        }
+    },
+    new CountQueuingStrategy({ highWaterMark: 4 })
+    );
</ins><span class="cx">     var reader = rs.getReader();
</span><span class="cx"> 
</span><del>-    assert_equals(enqueue('a'), true, 'After 0 reads, 1st enqueue should return true (queue now contains 1 chunk)');
-    assert_equals(enqueue('b'), true, 'After 0 reads, 2nd enqueue should return true (queue now contains 2 chunks)');
-    assert_equals(enqueue('c'), true, 'After 0 reads, 3rd enqueue should return true (queue now contains 3 chunks)');
-    assert_equals(enqueue('d'), true, 'After 0 reads, 4th enqueue should return true (queue now contains 4 chunks)');
-    assert_equals(enqueue('e'), false, 'After 0 reads, 5th enqueue should return false (queue now contains 5 chunks)');
-    assert_equals(enqueue('f'), false, 'After 0 reads, 6th enqueue should return false (queue now contains 6 chunks)');
</del><ins>+    assert_equals(controller.desiredSize, 4, '0 reads, 0 enqueues: desiredSize should be 4');
+    controller.enqueue('a');
+    assert_equals(controller.desiredSize, 3, '0 reads, 1 enqueue: desiredSize should be 3');
+    controller.enqueue('b');
+    assert_equals(controller.desiredSize, 2, '0 reads, 2 enqueues: desiredSize should be 2');
+    controller.enqueue('c');
+    assert_equals(controller.desiredSize, 1, '0 reads, 3 enqueues: desiredSize should be 1');
+    controller.enqueue('d');
+    assert_equals(controller.desiredSize, 0, '0 reads, 4 enqueues: desiredSize should be 0');
+    controller.enqueue('e');
+    assert_equals(controller.desiredSize, -1, '0 reads, 5 enqueues: desiredSize should be -1');
+    controller.enqueue('f');
+    assert_equals(controller.desiredSize, -2, '0 reads, 6 enqueues: desiredSize should be -2');
</ins><span class="cx"> 
</span><ins>+
</ins><span class="cx">     reader.read().then(test3.step_func(function(result) {
</span><span class="cx">         assert_object_equals(result, { value: 'a', done: false }, '1st read gives back the 1st chunk enqueued (queue now contains 5 chunks)');
</span><span class="cx">         return reader.read();
</span><span class="cx">     })).then(test3.step_func(function(result) {
</span><span class="cx">         assert_object_equals(result, { value: 'b', done: false }, '2nd read gives back the 2nd chunk enqueued (queue now contains 4 chunks)');
</span><del>-        assert_equals(enqueue('g'), false, 'After 2 reads, 7th enqueue should return false (queue now contains 5 chunks)');
</del><ins>+
+        assert_equals(controller.desiredSize, 0, '2 reads, 6 enqueues: desiredSize should be 0');
+        controller.enqueue('g');
+        assert_equals(controller.desiredSize, -1, '2 reads, 7 enqueues: desiredSize should be -1');
+
</ins><span class="cx">         return reader.read();
</span><span class="cx">     })).then(test3.step_func(function(result) {
</span><span class="cx">         assert_object_equals(result, { value: 'c', done: false }, '3rd read gives back the 3rd chunk enqueued (queue now contains 4 chunks)');
</span><span class="lines">@@ -120,12 +180,19 @@
</span><span class="cx">         assert_object_equals(result, { value: 'e', done: false }, '5th read gives back the 5th chunk enqueued (queue now contains 2 chunks)');
</span><span class="cx">         return reader.read();
</span><span class="cx">     })).then(test3.step_func(function(result) {
</span><del>-        assert_object_equals(result, { value: 'f', done: false }, '6th read gives back the 6th chunk enqueued (queue now contains 1 chunk)');
-        assert_equals(enqueue('h'), true, 'After 6 reads, 8th enqueue should return true (queue now contains 2 chunks)');
-        assert_equals(enqueue('i'), true, 'After 6 reads, 9th enqueue should return true (queue now contains 3 chunks)');
-        assert_equals(enqueue('j'), true, 'After 6 reads, 10th enqueue should return true (queue now contains 4 chunks)');
-        assert_equals(enqueue('k'), false, 'After 6 reads, 11th enqueue should return false (queue now contains 5 chunks)');
</del><ins>+        assert_object_equals(result, { value: 'f', done: false }, '6th read gives back the 6th chunk enqueued (queue now contains 0 chunks)');
+
+        assert_equals(controller.desiredSize, 3, '6 reads, 7 enqueues: desiredSize should be 3');
+        controller.enqueue('h');
+        assert_equals(controller.desiredSize, 2, '6 reads, 8 enqueues: desiredSize should be 2');
+        controller.enqueue('i');
+        assert_equals(controller.desiredSize, 1, '6 reads, 9 enqueues: desiredSize should be 1');
+        controller.enqueue('j');
+        assert_equals(controller.desiredSize, 0, '6 reads, 10 enqueues: desiredSize should be 0');
+        controller.enqueue('k');
+        assert_equals(controller.desiredSize, -1, '6 reads, 11 enqueues: desiredSize should be -1');
+
</ins><span class="cx">         test3.done();
</span><del>-    })).catch(test3.step_func(function(e) { assert_reached(e); } ));
</del><ins>+    })).catch(test3.step_func(function(e) { assert_unreached(e); } ));
</ins><span class="cx"> });
</span><span class="cx"> &lt;/script&gt;
</span></span></pre></div>
<a id="trunkLayoutTestsstreamsreferenceimplementationreadablestreamcancelexpectedtxt"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/streams/reference-implementation/readable-stream-cancel-expected.txt (185585 => 185586)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/streams/reference-implementation/readable-stream-cancel-expected.txt        2015-06-16 07:40:09 UTC (rev 185585)
+++ trunk/LayoutTests/streams/reference-implementation/readable-stream-cancel-expected.txt        2015-06-16 08:19:04 UTC (rev 185586)
</span><span class="lines">@@ -2,11 +2,11 @@
</span><span class="cx"> FAIL ReadableStream cancellation: integration test on an infinite stream derived from a random push source cancel is not implemented
</span><span class="cx"> FAIL ReadableStream cancellation: cancel(reason) should pass through the given reason to the underlying source cancel is not implemented
</span><span class="cx"> FAIL ReadableStream cancellation: cancel() on a locked stream should fail and not call the underlying source cancel cancel is not implemented
</span><ins>+FAIL ReadableStream cancellation: should fulfill promise when cancel callback went fine cancel is not implemented
</ins><span class="cx"> FAIL ReadableStream cancellation: returning a value from the underlying source's cancel should not affect the fulfillment value of the promise returned by the stream's cancel cancel is not implemented
</span><del>-FAIL ReadableStream cancellation: if the underlying source's cancel method returns a promise, the promise returned by the stream's cancel should fulfill when that one does cancel is not implemented
</del><ins>+FAIL ReadableStream cancellation: should reject promise when cancel callback raises an exception cancel is not implemented
+FAIL ReadableStream cancellation: if the underlying source's cancel method returns a promise, the promise returned by the stream's cancel should fulfill when that one does (1) cancel is not implemented
+FAIL ReadableStream cancellation: if the underlying source's cancel method returns a promise, the promise returned by the stream's cancel should fulfill when that one does (2) cancel is not implemented
</ins><span class="cx"> FAIL ReadableStream cancellation: if the underlying source's cancel method returns a promise, the promise returned by the stream's cancel should reject when that one does cancel is not implemented
</span><span class="cx"> FAIL ReadableStream cancellation: cancelling before start finishes should prevent pull() from being called cancel is not implemented
</span><del>-FAIL ReadableStream cancel should fulfill promise when cancel callback went fine cancel is not implemented
-FAIL ReadableStream cancel should reject promise when cancel callback raises an exception cancel is not implemented
-FAIL ReadableStream cancel should fulfill promise when cancel callback went fine after returning a promise cancel is not implemented
</del><span class="cx"> 
</span></span></pre></div>
<a id="trunkLayoutTestsstreamsreferenceimplementationreadablestreamcancelhtml"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/streams/reference-implementation/readable-stream-cancel.html (185585 => 185586)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/streams/reference-implementation/readable-stream-cancel.html        2015-06-16 07:40:09 UTC (rev 185585)
+++ trunk/LayoutTests/streams/reference-implementation/readable-stream-cancel.html        2015-06-16 08:19:04 UTC (rev 185586)
</span><span class="lines">@@ -27,7 +27,7 @@
</span><span class="cx">                 setTimeout(test1.step_func(function() {
</span><span class="cx">                     cancellationFinished = true;
</span><span class="cx">                     resolve();
</span><del>-                }), standardTimeout);
</del><ins>+                }), 500);
</ins><span class="cx">             }));
</span><span class="cx">         }
</span><span class="cx">     });
</span><span class="lines">@@ -37,7 +37,7 @@
</span><span class="cx">         assert_equals(cancellationFinished, false, 'it did not wait for the cancellation process to finish before closing');
</span><span class="cx">         assert_greater_than(chunks.length, 0, 'at least one chunk should be read');
</span><span class="cx">         for (var i = 0; i &lt; chunks.length; i++) {
</span><del>-            assert_equals(chunks[i].length, 128, &quot;chunk should have 128 bytes&quot;);
</del><ins>+            assert_equals(chunks[i].length, 128, 'chunk ' + i + ' should have 128 bytes');
</ins><span class="cx">         }
</span><span class="cx">     }), test1.step_func(function(e) { assert_unreached(e); }));
</span><span class="cx"> 
</span><span class="lines">@@ -46,7 +46,7 @@
</span><span class="cx">             assert_equals(cancellationFinished, true, 'it returns a promise that is fulfilled when the cancellation finishes');
</span><span class="cx">             test1.done();
</span><span class="cx">         })).catch(test1.step_func(function(e) { assert_unreached(e); }));
</span><del>-    }), standardTimeout + 50);
</del><ins>+    }), 1000);
</ins><span class="cx"> });
</span><span class="cx"> 
</span><span class="cx"> test(function() {
</span><span class="lines">@@ -91,33 +91,103 @@
</span><span class="cx">     }));
</span><span class="cx"> });
</span><span class="cx"> 
</span><del>-var test3 = async_test('ReadableStream cancellation: returning a value from the underlying source\'s cancel should not affect the fulfillment value of the promise returned by the stream\'s cancel');
-test3.step(function() {
</del><ins>+var test3 = async_test('ReadableStream cancellation: should fulfill promise when cancel callback went fine');
+test3.step(function()
+{
+    var cancelReceived = false;
+    var cancelReason = new Error('I am tired of this stream, I prefer to cancel it');
</ins><span class="cx">     var rs = new ReadableStream({
</span><span class="cx">         cancel: function(reason) {
</span><ins>+            cancelReceived = true;
+            assert_equals(reason, cancelReason, 'cancellation reason given to the underlying source should be equal to the one passed');
+        }
+    });
+
+    rs.cancel(cancelReason).then(
+        test3.step_func(function() {
+            assert_true(cancelReceived);
+            test3.done('stream was successfully cancelled');
+        }),
+        test3.step_func(function(e) {
+            assert_unreached(&quot;received error &quot; + e)
+        }));
+});
+
+var test4 = async_test('ReadableStream cancellation: returning a value from the underlying source\'s cancel should not affect the fulfillment value of the promise returned by the stream\'s cancel');
+test4.step(function() {
+    var rs = new ReadableStream({
+        cancel: function(reason) {
</ins><span class="cx">             return 'Hello';
</span><span class="cx">         }
</span><span class="cx">     });
</span><span class="cx"> 
</span><del>-    rs.cancel().then(test3.step_func(function(v) {
</del><ins>+    rs.cancel().then(test4.step_func(function(v) {
</ins><span class="cx">         assert_equals(v, undefined, 'cancel() return value should be fulfilled with undefined');
</span><del>-        test3.done();
-    }), test3.step_func(function() {
</del><ins>+        test4.done();
+    }), test4.step_func(function() {
</ins><span class="cx">         assert_unreached('cancel() return value should not be rejected');
</span><span class="cx">     }));
</span><span class="cx"> });
</span><span class="cx"> 
</span><del>-var test4 = async_test('ReadableStream cancellation: if the underlying source\'s cancel method returns a promise, the promise returned by the stream\'s cancel should fulfill when that one does');
-test4.step(function() {
</del><ins>+var test5 = async_test('ReadableStream cancellation: should reject promise when cancel callback raises an exception');
+test5.step(function()
+{
+    var thrownError = new Error('test');
+    var cancelCalled = false;
+
+    var rs = new ReadableStream({
+        cancel: function() {
+            cancelCalled = true;
+            throw thrownError;
+        }
+    });
+
+    rs.cancel('test').then(
+        test5.step_func(function() { assert_unreached('cancel should reject'); }),
+        test5.step_func(function(e) {
+            assert_true(cancelCalled);
+            assert_equals(e, thrownError);
+            test5.done();
+        })
+    );
+});
+
+var test6 = async_test('ReadableStream cancellation: if the underlying source\'s cancel method returns a promise, the promise returned by the stream\'s cancel should fulfill when that one does (1)');
+test6.step(function()
+{
+    var cancelReason = new Error('test');
+
+    var rs = new ReadableStream({
+        cancel: function(error) {
+            assert_equals(error, cancelReason);
+            return new Promise(test6.step_func(function(resolve, reject) {
+                setTimeout(test6.step_func(function() {
+                    resolve();
+                }), 500);
+            }))
+        }
+    })
+
+    rs.cancel(cancelReason).then(
+        test6.step_func(function() {
+            test6.done('stream successfully cancelled');
+        }),
+        test6.step_func(function(e) {
+            assert_unreached(&quot;received error &quot; + e)
+        }))
+});
+
+var test7 = async_test('ReadableStream cancellation: if the underlying source\'s cancel method returns a promise, the promise returned by the stream\'s cancel should fulfill when that one does (2)');
+test7.step(function() {
</ins><span class="cx">     var resolveSourceCancelPromise;
</span><span class="cx">     var sourceCancelPromiseHasFulfilled = false;
</span><span class="cx">     var rs = new ReadableStream({
</span><span class="cx">         cancel: function() {
</span><del>-            var sourceCancelPromise = new Promise(test4.step_func(function(resolve, reject) {
</del><ins>+            var sourceCancelPromise = new Promise(test7.step_func(function(resolve, reject) {
</ins><span class="cx">                 resolveSourceCancelPromise = resolve;
</span><span class="cx">             }));
</span><span class="cx"> 
</span><del>-            sourceCancelPromise.then(test4.step_func(function() {
</del><ins>+            sourceCancelPromise.then(test7.step_func(function() {
</ins><span class="cx">                 sourceCancelPromiseHasFulfilled = true;
</span><span class="cx">             }));
</span><span class="cx"> 
</span><span class="lines">@@ -125,28 +195,32 @@
</span><span class="cx">         }
</span><span class="cx">     });
</span><span class="cx"> 
</span><del>-    rs.cancel().then(test4.step_func(function(value) {
-        assert_equals(sourceCancelPromiseHasFulfilled, true, 'cancel() return value should be fulfilled only after the promise returned by the underlying source\'s cancel');
-        assert_equals(value, undefined, 'cancel() return value should be fulfilled with undefined');
-        test4.done();
-    }), test4.step_func(function() { assert_unreached('cancel() return value should not be rejected'); } ));
</del><span class="cx"> 
</span><del>-    setTimeout(test4.step_func(function() {
</del><ins>+    rs.cancel().then(
+        test7.step_func(function(value) {
+            assert_true(sourceCancelPromiseHasFulfilled, 'cancel() return value should be fulfilled only after the promise returned by the underlying source\'s cancel');
+            assert_equals(value, undefined, 'cancel() return value should be fulfilled with undefined');
+            test7.done();
+        }),
+        test7.step_func(function() { assert_unreached('cancel() return value should not be rejected'); })
+    );
+
+    setTimeout(test7.step_func(function() {
</ins><span class="cx">         resolveSourceCancelPromise('Hello');
</span><del>-    }), standardTimeout);
</del><ins>+    }), 500);
</ins><span class="cx"> });
</span><span class="cx"> 
</span><del>-var test5 = async_test('ReadableStream cancellation: if the underlying source\'s cancel method returns a promise, the promise returned by the stream\'s cancel should reject when that one does');
-test5.step(function() {
</del><ins>+var test8 = async_test('ReadableStream cancellation: if the underlying source\'s cancel method returns a promise, the promise returned by the stream\'s cancel should reject when that one does');
+test8.step(function() {
</ins><span class="cx">     var rejectSourceCancelPromise;
</span><span class="cx">     var sourceCancelPromiseHasRejected = false;
</span><span class="cx">     var rs = new ReadableStream({
</span><span class="cx">         cancel: function() {
</span><del>-            var sourceCancelPromise = new Promise(test5.step_func(function(resolve, reject) {
</del><ins>+            var sourceCancelPromise = new Promise(test8.step_func(function(resolve, reject) {
</ins><span class="cx">                 rejectSourceCancelPromise = reject;
</span><span class="cx">             }));
</span><span class="cx"> 
</span><del>-            sourceCancelPromise.catch(test5.step_func(function() {
</del><ins>+            sourceCancelPromise.catch(test8.step_func(function() {
</ins><span class="cx">                 sourceCancelPromiseHasRejected = true;
</span><span class="cx">             }));
</span><span class="cx"> 
</span><span class="lines">@@ -157,98 +231,29 @@
</span><span class="cx">     var errorInCancel = new Error('Sorry, it just wasn\'t meant to be.');
</span><span class="cx"> 
</span><span class="cx">     rs.cancel().then(
</span><del>-        test5.step_func(function() { assert_function('cancel() return value should not be rejected'); }),
-        test5.step_func(function(r) {
-            assert_equals(sourceCancelPromiseHasRejected, true, 'cancel() return value should be rejected only after the promise returned by the underlying source\'s cancel');
</del><ins>+        test8.step_func(function() { assert_unreached('cancel() return value should not be rejected'); }),
+        test8.step_func(function(r) {
+            assert_true(sourceCancelPromiseHasRejected, 'cancel() return value should be rejected only after the promise returned by the underlying source\'s cancel');
</ins><span class="cx">             assert_equals(r, errorInCancel, 'cancel() return value should be rejected with the underlying source\'s rejection reason');
</span><del>-            test5.done();
-        }));
</del><ins>+            test8.done();
+        })
+    );
</ins><span class="cx"> 
</span><del>-    setTimeout(test5.step_func(function() {
</del><ins>+    setTimeout(test8.step_func(function() {
</ins><span class="cx">         rejectSourceCancelPromise(errorInCancel);
</span><del>-    }), standardTimeout);
</del><ins>+    }), 500);
</ins><span class="cx"> });
</span><span class="cx"> 
</span><del>-var test6 = async_test('ReadableStream cancellation: cancelling before start finishes should prevent pull() from being called');
-test6.step(function() {
</del><ins>+var test9 = async_test('ReadableStream cancellation: cancelling before start finishes should prevent pull() from being called');
+test9.step(function() {
</ins><span class="cx">     var rs = new ReadableStream({
</span><span class="cx">         pull: function() {
</span><span class="cx">             assert_unreached('pull should not have been called');
</span><span class="cx">         }
</span><span class="cx">     });
</span><span class="cx"> 
</span><del>-    Promise.all([rs.cancel(), rs.getReader().closed]).then(test6.step_func(function() {
-        test6.done('pull should never have been called');
-    })).catch(test6.step_func(function(e) { assert_reached(e); } ));
</del><ins>+    Promise.all([rs.cancel(), rs.getReader().closed]).then(test9.step_func(function() {
+        test9.done('pull should never have been called');
+    })).catch(test9.step_func(function(e) { assert_reached(e); } ));
</ins><span class="cx"> });
</span><del>-
-var test7 = async_test('ReadableStream cancel should fulfill promise when cancel callback went fine');
-test7.step(function()
-{
-    var cancelReceived = false;
-    var cancelReason = &quot;I am tired of this stream, I prefer to cancel it&quot;;
-    var rs = new ReadableStream({
-        cancel: function(reason) {
-            cancelReceived = true;
-            assert_equals(reason, cancelReason);
-        }
-    });
-    rs.cancel(cancelReason).then(
-        test7.step_func(function() {
-            assert_true(cancelReceived);
-            test7.done();
-        }),
-        test7.step_func(function(e) {
-            assert_unreached(&quot;received error &quot; + e)
-        }));
-});
-
-var test8 = async_test('ReadableStream cancel should reject promise when cancel callback raises an exception');
-test8.step(function()
-{
-    var thrownError = undefined;
-
-    var rs = new ReadableStream({
-        cancel: function(error) {
-            thrownError = new Error(error);
-            throw thrownError;
-        }
-    });
-
-    rs.cancel(&quot;test&quot;).then(
-        test8.step_func(function() {
-            assert_unreached(&quot;cancel should fail&quot;)
-        }),
-        test8.step_func(function(e) {
-            assert_not_equals(thrownError, undefined);
-            assert_equals(e, thrownError);
-            test8.done();
-        })
-    );
-});
-
-var test9 = async_test('ReadableStream cancel should fulfill promise when cancel callback went fine after returning a promise');
-test9.step(function()
-{
-    var cancelReason = &quot;test&quot;;
-
-    var rs = new ReadableStream({
-        cancel: function(error) {
-            assert_equals(error, cancelReason);
-            return new Promise(test9.step_func(function(resolve, reject) {
-                setTimeout(test9.step_func(function() {
-                    resolve();
-                }), standardTimeout);
-            }))
-        }
-    })
-
-    rs.cancel(cancelReason).then(
-        test9.step_func(function() {
-            test9.done();
-        }),
-        test9.step_func(function(e) {
-            assert_unreached(&quot;received error &quot; + e)
-        }))
-});
</del><span class="cx"> &lt;/script&gt;
</span></span></pre></div>
<a id="trunkLayoutTestsstreamsreferenceimplementationreadablestreamexpectedtxt"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/streams/reference-implementation/readable-stream-expected.txt (185585 => 185586)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/streams/reference-implementation/readable-stream-expected.txt        2015-06-16 07:40:09 UTC (rev 185585)
+++ trunk/LayoutTests/streams/reference-implementation/readable-stream-expected.txt        2015-06-16 08:19:04 UTC (rev 185586)
</span><span class="lines">@@ -1,25 +1,33 @@
</span><span class="cx"> 
</span><span class="cx"> PASS ReadableStream can be constructed with no errors 
</span><del>-FAIL ReadableStream instances should have the correct list of properties assert_array_equals: should have all the correct methods lengths differ, expected 6 got 5
</del><ins>+PASS ReadableStream can't be constructed with garbage 
+FAIL ReadableStream instances should have the correct list of properties assert_array_equals: should have all the correct methods lengths differ, expected 7 got 5
</ins><span class="cx"> PASS ReadableStream constructor should throw for non-function start arguments 
</span><span class="cx"> PASS ReadableStream constructor can get initial garbage as cancel argument 
</span><span class="cx"> PASS ReadableStream constructor can get initial garbage as pull argument 
</span><del>-PASS ReadableStream constructor can get initial garbage as strategy argument 
</del><ins>+FAIL ReadableStream start should be called with the proper parameters assert_array_equals: the controller should have the right properties lengths differ, expected 5 got 4
+FAIL ReadableStream start controller parameter should be extensible assert_array_equals: prototype should have the right properties lengths differ, expected 5 got 4
+PASS ReadableStream should be able to call start method within prototype chain of its source 
</ins><span class="cx"> PASS ReadableStream start should be able to return a promise 
</span><del>-PASS ReadableStream start should be able to return a promise and reject it 
</del><ins>+TIMEOUT ReadableStream start should be able to return a promise and reject it Test timed out
</ins><span class="cx"> PASS ReadableStream should be able to enqueue different objects. 
</span><del>-PASS ReadableStream: if start throws an error, it should be re-thrown 
</del><span class="cx"> TIMEOUT ReadableStream: if pull rejects, it should error the stream Test timed out
</span><del>-FAIL ReadableStream: should not call pull until the previous pull call's promise fulfills assert_equals: after the promise returned by pull is fulfilled, pull should be called a second time expected 2 but got 1
</del><ins>+PASS ReadableStream: should only call pull once upon starting the stream 
+FAIL ReadableStream: should call pull when trying to read from a started, empty stream assert_equals: pull should be called again in reaction to calling read expected 2 but got 3
+PASS ReadableStream: should only call pull once on a non-empty stream read from before start fulfills 
+PASS ReadableStream: should only call pull once on a non-empty stream read from after start fulfills 
+PASS ReadableStream: should not call pull() in reaction to read()ing the last chunk, if draining 
+FAIL ReadableStream: should not call pull until the previous pull call's promise fulfills assert_equals: pull should have been called once after start, but not yet have been called a second time expected 1 but got 2
+FAIL ReadableStream: should pull after start, and after every read assert_equals: pull() should be called exactly four times expected 4 but got 1
</ins><span class="cx"> PASS ReadableStream: should not call pull after start if the stream is now closed 
</span><span class="cx"> FAIL ReadableStream: should call pull after enqueueing from inside pull (with no read requests), if strategy allows assert_equals: pull() should have been called four times expected 4 but got 1
</span><span class="cx"> PASS ReadableStream pull should be able to close a stream. 
</span><del>-FAIL ReadableStream: enqueue should throw when the stream is readable but draining assert_equals: the first enqueue should return true expected (boolean) true but got (undefined) undefined
</del><ins>+PASS ReadableStream: enqueue should throw when the stream is readable but draining 
</ins><span class="cx"> PASS ReadableStream: enqueue should throw when the stream is closed 
</span><span class="cx"> PASS ReadableStream: enqueue should throw the stored error when the stream is errored 
</span><span class="cx"> FAIL ReadableStream: should call underlying source methods as methods releaseLock is not implemented
</span><del>-FAIL ReadableStream strategies: the default strategy should return false for all but the first enqueue call assert_equals: first enqueue should return true expected (boolean) true but got (undefined) undefined
-FAIL ReadableStream strategies: the default strategy should continue returning true from enqueue if the chunks are read immediately assert_equals: first enqueue should return true expected (boolean) true but got (undefined) undefined
</del><ins>+FAIL ReadableStream strategies: the default strategy should give desiredSize of 1 to start, decreasing by 1 per enqueue assert_equals: expected (number) 1 but got (undefined) undefined
+FAIL ReadableStream strategies: the default strategy should continue giving desiredSize of 1 if the chunks are read immediately assert_equals: desiredSize should start at 1 expected (number) 1 but got (undefined) undefined
</ins><span class="cx"> PASS ReadableStream integration test: adapting a random push source 
</span><span class="cx"> PASS ReadableStream integration test: adapting a sync pull source 
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkLayoutTestsstreamsreferenceimplementationreadablestreamreaderexpectedtxt"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/streams/reference-implementation/readable-stream-reader-expected.txt (185585 => 185586)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/streams/reference-implementation/readable-stream-reader-expected.txt        2015-06-16 07:40:09 UTC (rev 185585)
+++ trunk/LayoutTests/streams/reference-implementation/readable-stream-reader-expected.txt        2015-06-16 08:19:04 UTC (rev 185586)
</span><span class="lines">@@ -6,13 +6,16 @@
</span><span class="cx"> PASS Constructing a ReadableStreamReader directly should fail if the stream is already locked (via direct construction) 
</span><span class="cx"> PASS Getting a ReadableStreamReader via getReader should fail if the stream is already locked (via direct construction) 
</span><span class="cx"> PASS Constructing a ReadableStreamReader directly should fail if the stream is already locked (via getReader) 
</span><del>-PASS Getting a ReadableStreamReader via getReader should fail if the stream is already locked (via direct getReader) 
</del><ins>+PASS Getting a ReadableStreamReader via getReader should fail if the stream is already locked (via getReader) 
</ins><span class="cx"> PASS Constructing a ReadableStreamReader directly should be OK if the stream is closed 
</span><span class="cx"> PASS Constructing a ReadableStreamReader directly should be OK if the stream is errored 
</span><span class="cx"> PASS Reading from a reader for an empty stream will wait until a chunk is available 
</span><span class="cx"> FAIL cancel() on a reader releases the reader before calling through cancel is not implemented
</span><span class="cx"> PASS closed should be fulfilled after stream is closed (.closed access before acquiring) 
</span><span class="cx"> FAIL closed should be fulfilled after reader releases its lock (multiple stream locks) releaseLock is not implemented
</span><ins>+FAIL Multiple readers can access the stream in sequence releaseLock is not implemented
</ins><span class="cx"> FAIL Cannot use an already-released reader to unlock a stream again releaseLock is not implemented
</span><ins>+FAIL cancel() on a released reader is a no-op and does not pass through releaseLock is not implemented
</ins><span class="cx"> PASS Getting a second reader after erroring the stream should succeed 
</span><ins>+PASS Garbage-collecting a ReadableStreamReader should not unlock its stream 
</ins><span class="cx"> 
</span></span></pre></div>
<a id="trunkLayoutTestsstreamsreferenceimplementationreadablestreamreaderhtml"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/streams/reference-implementation/readable-stream-reader.html (185585 => 185586)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/streams/reference-implementation/readable-stream-reader.html        2015-06-16 07:40:09 UTC (rev 185585)
+++ trunk/LayoutTests/streams/reference-implementation/readable-stream-reader.html        2015-06-16 08:19:04 UTC (rev 185586)
</span><span class="lines">@@ -2,6 +2,7 @@
</span><span class="cx"> &lt;script src='../../resources/testharness.js'&gt;&lt;/script&gt;
</span><span class="cx"> &lt;script src='../../resources/testharnessreport.js'&gt;&lt;/script&gt;
</span><span class="cx"> &lt;script src='resources/streams-utils.js'&gt;&lt;/script&gt;
</span><ins>+&lt;script src='../../resources/gc.js'&gt;&lt;/script&gt;
</ins><span class="cx"> &lt;script&gt;
</span><span class="cx"> var ReadableStreamReader;
</span><span class="cx"> 
</span><span class="lines">@@ -84,7 +85,7 @@
</span><span class="cx">     var rs = new ReadableStream();
</span><span class="cx">     rs.getReader(); // getReader() should be fine.
</span><span class="cx">     assert_throws(new TypeError(), function() { rs.getReader(); }, 'getReader() should fail');
</span><del>-}, 'Getting a ReadableStreamReader via getReader should fail if the stream is already locked (via direct getReader)');
</del><ins>+}, 'Getting a ReadableStreamReader via getReader should fail if the stream is already locked (via getReader)');
</ins><span class="cx"> 
</span><span class="cx"> test(function() {
</span><span class="cx">     var rs = new ReadableStream({
</span><span class="lines">@@ -190,37 +191,33 @@
</span><span class="cx">     }));
</span><span class="cx"> });
</span><span class="cx"> 
</span><del>-// var test5 = async_test('Multiple readers can access the stream in sequence');
-// test5.step(function() {
-//     var readCount = 0;
-//     var rs = new ReadableStream({
-//         start: function(c) {
-//             c.enqueue('a');
-//             c.enqueue('b');
-//             c.close();
-//         }
-//     });
</del><ins>+var test5 = async_test('Multiple readers can access the stream in sequence');
+test5.step(function() {
+    var readCount = 0;
+    var rs = new ReadableStream({
+        start: function(c) {
+            c.enqueue('a');
+            c.enqueue('b');
+            c.close();
+        }
+    });
</ins><span class="cx"> 
</span><del>-//     var reader1 = rs.getReader();
-//     reader1.read().then(test5.step_func(function(r) {
-//         assert_object_equals(r, { value: 'a', done: false }, 'reading the first chunk from reader1 works');
-//         ++readCount;
-//     }));
-//     reader1.releaseLock();
</del><ins>+    var reader1 = rs.getReader();
+    reader1.read().then(test5.step_func(function(r) {
+        assert_object_equals(r, { value: 'a', done: false }, 'reading the first chunk from reader1 works');
+        ++readCount;
+    }));
+    reader1.releaseLock();
</ins><span class="cx"> 
</span><del>-//     var reader2 = rs.getReader();
-//     reader2.read().then(test5.step_func(function(r) {
-//         assert_object_equals(r, { value: 'b', done: false }, 'reading the second chunk from reader2 works');
-//         ++readCount;
-//     }));
-//     reader2.releaseLock();
</del><ins>+    var reader2 = rs.getReader();
+    reader2.read().then(test5.step_func(function(r) {
+        assert_object_equals(r, { value: 'b', done: false }, 'reading the second chunk from reader2 works');
+        assert_equals(++readCount, 2);
+        test5.done();
+    }));
+    reader2.releaseLock();
+});
</ins><span class="cx"> 
</span><del>-//     setTimeout(test5.step_func(function() {
-//         assert_equals(readCount, 2);
-//         test5.done();
-//     }), standardTimeout);
-// });
-
</del><span class="cx"> var test6 = async_test('Cannot use an already-released reader to unlock a stream again');
</span><span class="cx"> test6.step(function() {
</span><span class="cx">     var rs = new ReadableStream({
</span><span class="lines">@@ -241,39 +238,33 @@
</span><span class="cx">     }));
</span><span class="cx"> });
</span><span class="cx"> 
</span><del>-// var test7 = async_test('cancel() on a released reader is a no-op and does not pass through');
-// test7.step(function() {
-//     var readCounts = 0;
-//     var cancelled = false;
-//     var rs = new ReadableStream({
-//         start: function(c) {
-//             c.enqueue('a');
-//         },
-//         cancel: function() {
-//             assert_unreached('underlying source cancel should not be called');
-//         }
-//     });
</del><ins>+var test7 = async_test('cancel() on a released reader is a no-op and does not pass through');
+test7.step(function() {
+    var cancelled = false;
+    var rs = new ReadableStream({
+        start: function(c) {
+            c.enqueue('a');
+        },
+        cancel: function() {
+            assert_unreached('underlying source cancel should not be called');
+        }
+    });
</ins><span class="cx"> 
</span><del>-//     var reader = rs.getReader();
-//     reader.releaseLock();
-//     reader.cancel().then(test7.step_func(function(v) {
-//         assert_equals(v, undefined, 'cancel() on the reader should fulfill with undefined')
-//         cancelled = true;
-//     }));
</del><ins>+    var reader = rs.getReader();
+    reader.releaseLock();
+    reader.cancel().then(test7.step_func(function(v) {
+        assert_equals(v, undefined, 'cancel() on the reader should fulfill with undefined')
+        cancelled = true;
+    }));
</ins><span class="cx"> 
</span><del>-//     var reader2 = rs.getReader();
-//     reader2.read().then(test7.step_func(function(r) {
-//         assert_object_equals(r, { value: 'a', done: false }, 'a new reader should be able to read a chunk');
-//         ++readCounts;
-//     }));
</del><ins>+    var reader2 = rs.getReader();
+    reader2.read().then(test7.step_func(function(r) {
+        assert_object_equals(r, { value: 'a', done: false }, 'a new reader should be able to read a chunk');
+        assert_true(cancelled);
+        test7.done();
+    }));
+});
</ins><span class="cx"> 
</span><del>-//     setTimeout(test7.step_func(function() {
-//         assert_true(cancelled);
-//         assert_equals(readCounts, 1);
-//         test7.done();
-//     }), standardTimeout);
-// });
-
</del><span class="cx"> var test8 = async_test('Getting a second reader after erroring the stream should succeed');
</span><span class="cx"> test8.step(function() {
</span><span class="cx">     var controller;
</span><span class="lines">@@ -312,4 +303,13 @@
</span><span class="cx">         test8.done();
</span><span class="cx">     }));
</span><span class="cx"> });
</span><ins>+
+test(function() {
+    var rs = new ReadableStream({});
+
+    rs.getReader();
+    window.gc();
+
+    assert_throws(new TypeError(), function() { rs.getReader(); }, 'old reader should still be locking the stream even after garbage collection');
+}, 'Garbage-collecting a ReadableStreamReader should not unlock its stream');
</ins><span class="cx"> &lt;/script&gt;
</span></span></pre></div>
<a id="trunkLayoutTestsstreamsreferenceimplementationreadablestreamteeexpectedtxt"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/streams/reference-implementation/readable-stream-tee-expected.txt (0 => 185586)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/streams/reference-implementation/readable-stream-tee-expected.txt                                (rev 0)
+++ trunk/LayoutTests/streams/reference-implementation/readable-stream-tee-expected.txt        2015-06-16 08:19:04 UTC (rev 185586)
</span><span class="lines">@@ -0,0 +1,12 @@
</span><ins>+
+FAIL ReadableStream teeing: rs.tee() returns an array of two ReadableStreams rs.tee is not a function. (In 'rs.tee()', 'rs.tee' is undefined)
+FAIL ReadableStream teeing: should be able to read one branch to the end without affecting the other rs.tee is not a function. (In 'rs.tee()', 'rs.tee' is undefined)
+FAIL ReadableStream teeing: values should be equal across each branch rs.tee is not a function. (In 'rs.tee()', 'rs.tee' is undefined)
+FAIL ReadableStream teeing: errors in the source should propagate to both branches rs.tee is not a function. (In 'rs.tee()', 'rs.tee' is undefined)
+FAIL ReadableStream teeing: canceling branch1 should not impact branch2 rs.tee is not a function. (In 'rs.tee()', 'rs.tee' is undefined)
+FAIL ReadableStream teeing: canceling branch2 should not impact branch1 rs.tee is not a function. (In 'rs.tee()', 'rs.tee' is undefined)
+FAIL ReadableStream teeing: canceling both branches should aggregate the cancel reasons into an array rs.tee is not a function. (In 'rs.tee()', 'rs.tee' is undefined)
+FAIL ReadableStream teeing: failing to cancel the original stream should cause cancel() to reject on branches rs.tee is not a function. (In 'rs.tee()', 'rs.tee' is undefined)
+FAIL ReadableStream teeing: closing the original should immediately close the branches rs.tee is not a function. (In 'rs.tee()', 'rs.tee' is undefined)
+FAIL ReadableStream teeing: erroring the original should immediately error the branches rs.tee is not a function. (In 'rs.tee()', 'rs.tee' is undefined)
+
</ins></span></pre></div>
<a id="trunkLayoutTestsstreamsreferenceimplementationreadablestreamteehtml"></a>
<div class="addfile"><h4>Added: trunk/LayoutTests/streams/reference-implementation/readable-stream-tee.html (0 => 185586)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/streams/reference-implementation/readable-stream-tee.html                                (rev 0)
+++ trunk/LayoutTests/streams/reference-implementation/readable-stream-tee.html        2015-06-16 08:19:04 UTC (rev 185586)
</span><span class="lines">@@ -0,0 +1,306 @@
</span><ins>+&lt;!DOCTYPE html&gt;
+&lt;script src='../../resources/testharness.js'&gt;&lt;/script&gt;
+&lt;script src='../../resources/testharnessreport.js'&gt;&lt;/script&gt;
+&lt;script src='resources/streams-utils.js'&gt;&lt;/script&gt;
+&lt;script&gt;
+test(function() {
+    var rs = new ReadableStream();
+
+    var result = rs.tee();
+
+    assert_true(Array.isArray(result), 'return value should be an array');
+    assert_equals(result.length, 2, 'array should have length 2');
+    assert_equals(result[0].constructor, ReadableStream, '0th element should be a ReadableStream');
+    assert_equals(result[1].constructor, ReadableStream, '1st element should be a ReadableStream');
+}, 'ReadableStream teeing: rs.tee() returns an array of two ReadableStreams');
+
+var test1 = async_test('ReadableStream teeing: should be able to read one branch to the end without affecting the other');
+test1.step(function() {
+    var closedCalled = false;
+    var readCalls = 0;
+    const rs = new ReadableStream({
+        start: function(c) {
+            c.enqueue('a');
+            c.enqueue('b');
+            c.close();
+        }
+    });
+
+    var branch = rs.tee();
+    var branch1 = branch[0];
+    var branch2 = branch[1];
+    var reader1 = branch1.getReader();
+    var reader2 = branch2.getReader();
+
+    reader1.closed.then(test1.step_func(function() {
+        closedCalled = true;
+    })).catch(test1.step_func(function(e) { assert_unreached(e); }));
+    reader2.closed.then(test1.step_func(function() { assert_unreached('branch2 should not be closed'); }));
+
+    reader1.read().then(test1.step_func(function(r) {
+        assert_object_equals(r, { value: 'a', done: false }, 'first chunk from branch1 should be correct');
+        ++readCalls;
+    }));
+    reader1.read().then(test1.step_func(function(r) {
+        assert_object_equals(r, { value: 'b', done: false }, 'second chunk from branch1 should be correct');
+        ++readCalls;
+    }));
+    reader1.read().then(test1.step_func(function(r) {
+        assert_object_equals(r, { value: undefined, done: true }, 'third read() from branch1 should be done');
+        assert_true(closedCalled);
+        assert_equals(++readCalls, 4);
+        test1.done();
+    }));
+
+    reader2.read().then(test1.step_func(function(r) {
+        assert_object_equals(r, { value: 'a', done: false }, 'first chunk from branch2 should be correct');
+        ++readCalls;
+    }));
+});
+
+var test2 = async_test('ReadableStream teeing: values should be equal across each branch');
+test2.step(function() {
+    var theObject = { the: 'test object' };
+    var rs = new ReadableStream({
+        start: function(c) {
+            c.enqueue(theObject);
+        }
+    });
+
+    var branch = rs.tee();
+    var branch1 = branch[0];
+    var branch2 = branch[1];
+    var reader1 = branch1.getReader();
+    var reader2 = branch2.getReader();
+
+    Promise.all([reader1.read(), reader2.read()]).then(test2.step_func(function(values) {
+        assert_object_equals(values[0], values[1], 'the values should be equal');
+        test2.done();
+    }));
+});
+
+var test3 = async_test('ReadableStream teeing: errors in the source should propagate to both branches');
+test3.step(function() {
+    var closedRejects = 0;
+    var readCalls = 0;
+    var readRejects = 0;
+    var theError = new Error('boo!');
+    var rs = new ReadableStream({
+        start: function(c) {
+            c.enqueue('a');
+            c.enqueue('b');
+        },
+        pull: function() {
+            throw theError;
+        }
+    });
+
+    var branch = rs.tee();
+    var branch1 = branch[0];
+    var branch2 = branch[1];
+    var reader1 = branch1.getReader();
+    var reader2 = branch2.getReader();
+
+    reader1.label = 'reader1';
+    reader2.label = 'reader2';
+
+    reader1.closed.catch(test3.step_func(function(e) {
+        ++closedRejects;
+        assert_equals(e, theError, 'branch1 closed promise should reject with the error');
+    }));
+    reader2.closed.catch(test3.step_func(function(e) {
+        ++closedRejects;
+        assert_equals(e, theError, 'branch2 closed promise should reject with the error');
+    }));
+
+    reader1.read().then(test3.step_func(function(r) {
+        ++readCalls;
+        assert_object_equals(r, { value: 'a', done: false }, 'should be able to read the first chunk in branch1');
+    }));
+
+    reader1.read().then(test3.step_func(function(r) {
+        ++readCalls;
+        assert_object_equals(r, { value: 'b', done: false }, 'should be able to read the second chunk in branch1');
+
+        return reader2.read().then(
+            test3.step_func(function() { assert_unreached('once the root stream has errored, you should not be able to read from branch2'); }),
+            test3.step_func(function(e) {
+                ++readRejects;
+                assert_equals(e, theError, 'branch2 read() promise should reject with the error');
+            }));
+    })).then(test3.step_func(function() {
+        return reader1.read().then(
+            test3.step_func(function() { assert_unreached('once the root stream has errored, you should not be able to read from branch1 either'); }),
+            test3.step_func(function(e) {
+                assert_equals(closedRejects, 2);
+                assert_equals(readCalls, 2);
+                assert_equals(++readRejects, 2);
+                assert_equals(e, theError, 'branch1 read() promise should reject with the error');
+                test3.done();
+            })
+        );
+    })).catch(test3.step_func(function(e) { assert_unreached(e); }));
+});
+
+var test4 = async_test('ReadableStream teeing: canceling branch1 should not impact branch2');
+test4.step(function() {
+    var branch1Read = false;
+    var rs = new ReadableStream({
+        start: function(c) {
+            c.enqueue('a');
+            c.enqueue('b');
+            c.close();
+        }
+    });
+
+    var branch = rs.tee();
+    var branch1 = branch[0];
+    var branch2 = branch[1];
+    branch1.cancel();
+
+    readableStreamToArray(branch1).then(test4.step_func(function(chunks) {
+        assert_array_equals(chunks, [], 'branch1 should have no chunks');
+        branch1Read = true;
+    }));
+                                                       
+    readableStreamToArray(branch2).then(test4.step_func(function(chunks) {
+        assert_array_equals(chunks, ['a', 'b'], 'branch2 should have two chunks');
+        assert_true(branch1Read);
+        test4.done();
+    }));
+});
+
+var test5 = async_test('ReadableStream teeing: canceling branch2 should not impact branch1');
+test5.step(function() {
+    var branch2Read = false;
+    var rs = new ReadableStream({
+        start: function(c) {
+            c.enqueue('a');
+            c.enqueue('b');
+            c.close();
+        }
+    });
+
+    var branch = rs.tee();
+    var branch1 = branch[0];
+    var branch2 = branch[1];
+    branch2.cancel();
+
+    readableStreamToArray(branch1).then(test5.step_func(function(chunks) {
+        assert_array_equals(chunks, ['a', 'b'], 'branch1 should have two chunks');
+        assert_true(branch2Read);
+        test5.done();
+    }));
+    readableStreamToArray(branch2).then(test5.step_func(function(chunks) {
+        assert_array_equals(chunks, [], 'branch2 should have no chunks');
+        branch2Read = true;
+    }));
+});
+
+var test6 = async_test('ReadableStream teeing: canceling both branches should aggregate the cancel reasons into an array');
+test6.step(function() {
+    var reason1 = new Error('We\'re wanted men.');
+    var reason2 = new Error('I have the death sentence on twelve systems.');
+
+    var rs = new ReadableStream({
+        cancel: function(reason) {
+            assert_array_equals(reason, [reason1, reason2], 'the cancel reason should be an array containing those from the branches');
+            test6.done();
+        }
+    });
+
+    var branch = rs.tee();
+    var branch1 = branch[0];
+    var branch2 = branch[1];
+    branch1.cancel(reason1);
+    branch2.cancel(reason2);
+});
+
+var test7 = async_test('ReadableStream teeing: failing to cancel the original stream should cause cancel() to reject on branches');
+test7.step(function() {
+    var cancel1Rejected = false;
+    var theError = new Error('I\'ll be careful.');
+    var rs = new ReadableStream({
+        cancel: function() {
+            throw theError;
+        }
+    });
+
+    var branch = rs.tee();
+    var branch1 = branch[0];
+    var branch2 = branch[1];
+    branch1.cancel().catch(test7.step_func(function(e) {
+        assert_equals(e, theError, 'branch1.cancel() should reject with the error');
+        cancel1Rejected = true;
+    }));
+    branch2.cancel().catch(test7.step_func(function(e) {
+        assert_equals(e, theError, 'branch2.cancel() should reject with the error');
+        assert_true(cancel1Rejected);
+        test7.done();
+    }));
+});
+
+var test8 = async_test('ReadableStream teeing: closing the original should immediately close the branches');
+test8.step(function() {
+    var reader1Closed = false;
+    var controller;
+    var rs = new ReadableStream({
+        start: function(c) {
+            controller = c;
+        }
+    });
+
+    var branch = rs.tee();
+    var branch1 = branch[0];
+    var branch2 = branch[1];
+    var reader1 = branch1.getReader();
+    var reader2 = branch2.getReader();
+
+    reader1.closed.then(test8.step_func(function() {
+        reader1Closed = true; //branch1 should be closed
+    })).catch(test8.step_func(function(e) { assert_unreached(e); }));
+    reader2.closed.then(test8.step_func(function() {
+        assert_true(reader1Closed);
+        test8.done('branch2 should be closed');
+    })).catch(test8.step_func(function(e) { assert_unreached(e); }));
+
+    controller.close();
+});
+
+var test9 = async_test('ReadableStream teeing: erroring the original should immediately error the branches');
+test9.step(function() {
+    var reader1Rejected = false;
+    var controller;
+    var rs = new ReadableStream({
+        start(c) {
+            controller = c;
+        }
+    });
+
+    var branch = rs.tee();
+    var branch1 = branch[0];
+    var branch2 = branch[1];
+    var reader1 = branch1.getReader();
+    var reader2 = branch2.getReader();
+
+    var theError = new Error('boo!');
+
+    reader1.closed.then(
+        test9.step_func(function() { assert_unreached('branch1 should not be closed'); }),
+        test9.step_func(function(e) {
+            assert_equals(e, theError, 'branch1 should be errored with the error');
+            reader1Rejected = true;
+        })
+    );
+    reader2.closed.then(
+        test9.step_func(function() { assert_unreached('branch2 should not be closed'); }),
+        test9.step_func(function(e) {
+            assert_equals(e, theError, 'branch2 should be errored with the error');
+            assert_true(reader1Rejected);
+            test9.done();
+        })
+    );
+
+    controller.error(theError);
+});
+&lt;/script&gt;
</ins></span></pre></div>
<a id="trunkLayoutTestsstreamsreferenceimplementationreadablestreamtemplatedexpectedtxt"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/streams/reference-implementation/readable-stream-templated-expected.txt (185585 => 185586)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/streams/reference-implementation/readable-stream-templated-expected.txt        2015-06-16 07:40:09 UTC (rev 185585)
+++ trunk/LayoutTests/streams/reference-implementation/readable-stream-templated-expected.txt        2015-06-16 08:19:04 UTC (rev 185586)
</span><span class="lines">@@ -1,34 +1,50 @@
</span><span class="cx"> 
</span><span class="cx"> PASS Running templatedRSEmpty with ReadableStream (empty) 
</span><del>-PASS instances have the correct methods and properties 
</del><ins>+FAIL instances have the correct methods and properties assert_equals: has a boolean locked getter expected &quot;boolean&quot; but got &quot;undefined&quot;
</ins><span class="cx"> PASS Running templatedRSEmptyReader with ReadableStream (empty) reader 
</span><span class="cx"> PASS instances have the correct methods and properties 
</span><ins>+FAIL locked should be true assert_true: locked getter should return true expected true got undefined
+PASS read() should never settle 
+PASS two read()s should both never settle 
</ins><span class="cx"> PASS read() should return distinct promises each time 
</span><span class="cx"> PASS getReader() again on the stream should fail 
</span><ins>+FAIL releasing the lock with pending read requests should throw but the read requests should stay pending releaseLock is not implemented
</ins><span class="cx"> FAIL releasing the lock should cause further read() calls to resolve as if the stream is closed releaseLock is not implemented
</span><span class="cx"> FAIL releasing the lock should cause closed to fulfill releaseLock is not implemented
</span><ins>+FAIL releasing the lock should cause locked to become false releaseLock is not implemented
</ins><span class="cx"> FAIL canceling via the reader should cause the reader to act closed cancel is not implemented
</span><span class="cx"> FAIL canceling via the stream should fail cancel is not implemented
</span><span class="cx"> PASS Running templatedRSClosed with ReadableStream (closed via call in start) 
</span><span class="cx"> FAIL cancel() should return a distinct fulfilled promise each time cancel is not implemented
</span><ins>+FAIL locked should be false assert_false: locked getter should return false expected false got undefined
</ins><span class="cx"> PASS getReader() should be OK 
</span><span class="cx"> PASS should be able to acquire multiple readers, since they are all auto-released 
</span><span class="cx"> PASS Running templatedRSClosedReader with ReadableStream (closed via call in start) reader 
</span><span class="cx"> PASS read() should fulfill with { value: undefined, done: true } 
</span><span class="cx"> PASS closed should fulfill with undefined 
</span><ins>+FAIL cancel() should return a distinct fulfilled promise each time cancel is not implemented
</ins><span class="cx"> PASS Running templatedRSClosed with ReadableStream (closed via cancel) 
</span><span class="cx"> FAIL cancel() should return a distinct fulfilled promise each time cancel is not implemented
</span><ins>+FAIL locked should be false cancel is not implemented
</ins><span class="cx"> FAIL getReader() should be OK cancel is not implemented
</span><span class="cx"> FAIL should be able to acquire multiple readers, since they are all auto-released cancel is not implemented
</span><span class="cx"> PASS Running templatedRSClosedReader with ReadableStream (closed via cancel) reader 
</span><span class="cx"> FAIL read() should fulfill with { value: undefined, done: true } cancel is not implemented
</span><span class="cx"> FAIL closed should fulfill with undefined cancel is not implemented
</span><ins>+FAIL cancel() should return a distinct fulfilled promise each time cancel is not implemented
</ins><span class="cx"> PASS Running templatedRSErrored with ReadableStream (errored via call in start) 
</span><span class="cx"> PASS getReader() should return a reader that acts errored 
</span><ins>+FAIL locked should be false assert_false: locked getter should return false expected false got undefined
</ins><span class="cx"> PASS Running templatedRSErroredSyncOnly with ReadableStream (errored via call in start) 
</span><span class="cx"> FAIL cancel() should return a distinct rejected promise each time cancel is not implemented
</span><span class="cx"> FAIL reader cancel() should return a distinct rejected promise each time cancel is not implemented
</span><span class="cx"> PASS should be able to acquire multiple readers, since they are all auto-released 
</span><ins>+PASS Running templatedRSErrored with ReadableStream (errored via returning a rejected promise in start) 
+PASS getReader() should return a reader that acts errored 
+FAIL locked should be false assert_false: locked getter should return false expected false got undefined
+PASS Running templatedRSErroredReader with ReadableStream (errored via returning a rejected promise in start) reader 
+PASS closed should reject with the error 
+PASS read() should reject with the error 
</ins><span class="cx"> PASS Running templatedRSTwoChunksOpenReader with ReadableStream (two chunks enqueued, still open) reader 
</span><span class="cx"> PASS calling read() twice without waiting will eventually give both chunks 
</span><span class="cx"> PASS calling read() twice with waiting will eventually give both chunks 
</span><span class="lines">@@ -37,7 +53,7 @@
</span><span class="cx"> PASS Running templatedRSTwoChunksClosedReader with ReadableStream (two chunks enqueued, then closed) reader 
</span><span class="cx"> PASS third read(), without waiting, should give { value: undefined, done: true } 
</span><span class="cx"> PASS third read, with waiting, should give { value: undefined, done: true } 
</span><del>-PASS draining the stream via read() should cause the reader closed promise to fulfill 
</del><ins>+FAIL draining the stream via read() should cause the reader closed promise to fulfill and locked to be false assert_false: stream should no longer be locked expected false got undefined
</ins><span class="cx"> FAIL releasing the lock after the stream is closed should do nothing releaseLock is not implemented
</span><span class="cx"> FAIL releasing the lock should cause read() to act as if the stream is closed releaseLock is not implemented
</span><span class="cx"> FAIL reader's closed property always returns the same promise releaseLock is not implemented
</span></span></pre></div>
<a id="trunkLayoutTestsstreamsreferenceimplementationreadablestreamtemplatedhtml"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/streams/reference-implementation/readable-stream-templated.html (185585 => 185586)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/streams/reference-implementation/readable-stream-templated.html        2015-06-16 07:40:09 UTC (rev 185585)
+++ trunk/LayoutTests/streams/reference-implementation/readable-stream-templated.html        2015-06-16 08:19:04 UTC (rev 185586)
</span><span class="lines">@@ -10,10 +10,12 @@
</span><span class="cx">     test(function() {
</span><span class="cx">         var rs = factory();
</span><span class="cx"> 
</span><ins>+        assert_equals(typeof rs.locked, 'boolean', 'has a boolean locked getter');
</ins><span class="cx">         assert_equals(typeof rs.cancel, 'function', 'has a cancel method');
</span><span class="cx">         assert_equals(typeof rs.getReader, 'function', 'has a getReader method');
</span><span class="cx">         assert_equals(typeof rs.pipeThrough, 'function', 'has a pipeThrough method');
</span><span class="cx">         assert_equals(typeof rs.pipeTo, 'function', 'has a pipeTo method');
</span><ins>+        assert_equals(typeof rs.tee, 'function', 'has a tee method');
</ins><span class="cx">     }, 'instances have the correct methods and properties');
</span><span class="cx"> }
</span><span class="cx"> 
</span><span class="lines">@@ -25,6 +27,7 @@
</span><span class="cx">     test1.step(function() {
</span><span class="cx">         var rs = factory();
</span><span class="cx">         var promisesCount = 0;
</span><ins>+        var allChecked = false;
</ins><span class="cx"> 
</span><span class="cx">         var cancelPromise1 = rs.cancel();
</span><span class="cx">         var cancelPromise2 = rs.cancel();
</span><span class="lines">@@ -36,14 +39,22 @@
</span><span class="cx">         cancelPromise2.then(test1.step_func(function(v) {
</span><span class="cx">             assert_equals(v, undefined, 'second cancel() call should fulfill with undefined');
</span><span class="cx">             assert_equals(++promisesCount, 2);
</span><ins>+            assert_true(allChecked);
</ins><span class="cx">             test1.done();
</span><span class="cx">         }));
</span><span class="cx">         assert_not_equals(cancelPromise1, cancelPromise2, 'cancel() calls should return distinct promises');
</span><ins>+        allChecked = true;
</ins><span class="cx">     });
</span><span class="cx"> 
</span><span class="cx">     test(function() {
</span><span class="cx">         var rs = factory();
</span><span class="cx"> 
</span><ins>+        assert_false(rs.locked, 'locked getter should return false');
+    }, 'locked should be false');
+
+    test(function() {
+        var rs = factory();
+
</ins><span class="cx">         rs.getReader(); // getReader() should not throw.
</span><span class="cx">     }, 'getReader() should be OK');
</span><span class="cx"> 
</span><span class="lines">@@ -78,6 +89,12 @@
</span><span class="cx">             test1.done();
</span><span class="cx">         }));
</span><span class="cx">     });
</span><ins>+
+    test(function() {
+        var rs = factory();
+
+        assert_false(rs.locked, 'locked getter should return false');
+    }, 'locked should be false');
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> function templatedRSErroredSyncOnly(label, factory, error) {
</span><span class="lines">@@ -88,6 +105,7 @@
</span><span class="cx">     test1.step(function() {
</span><span class="cx">         var rs = factory();
</span><span class="cx">         var promisesCount = 0;
</span><ins>+        var allChecked = false;
</ins><span class="cx"> 
</span><span class="cx">         var cancelPromise1 = rs.cancel();
</span><span class="cx">         var cancelPromise2 = rs.cancel();
</span><span class="lines">@@ -99,9 +117,11 @@
</span><span class="cx">         cancelPromise2.catch(test1.step_func(function(e) {
</span><span class="cx">             assert_equals(e, error, 'second cancel() call should reject with the error');
</span><span class="cx">             assert_equals(++promisesCount, 2);
</span><ins>+            assert_true(allChecked);
</ins><span class="cx">             test1.done();
</span><span class="cx">         }));
</span><span class="cx">         assert_not_equals(cancelPromise1, cancelPromise2, 'cancel() calls should return distinct promises');
</span><ins>+        allChecked = true;
</ins><span class="cx">     });
</span><span class="cx"> 
</span><span class="cx">     var test2 = async_test('reader cancel() should return a distinct rejected promise each time');
</span><span class="lines">@@ -109,6 +129,7 @@
</span><span class="cx">         var rs = factory();
</span><span class="cx">         var reader = rs.getReader();
</span><span class="cx">         var promisesCount = 0;
</span><ins>+        var allChecked = false;
</ins><span class="cx"> 
</span><span class="cx">         var cancelPromise1 = reader.cancel();
</span><span class="cx">         var cancelPromise2 = reader.cancel();
</span><span class="lines">@@ -120,9 +141,11 @@
</span><span class="cx">         cancelPromise2.catch(test2.step_func(function(e) {
</span><span class="cx">             assert_equals(e, error, 'second cancel() call should reject with the error');
</span><span class="cx">             assert_equals(++promisesCount, 2);
</span><ins>+            assert_true(allChecked);
</ins><span class="cx">             test2.done();
</span><span class="cx">         }));
</span><span class="cx">         assert_not_equals(cancelPromise1, cancelPromise2, 'cancel() calls should return distinct promises');
</span><ins>+        allChecked = true;
</ins><span class="cx">     });
</span><span class="cx"> 
</span><span class="cx">     test(function() {
</span><span class="lines">@@ -150,35 +173,41 @@
</span><span class="cx">         assert_equals(typeof reader.releaseLock, 'function', 'has a releaseLock method');
</span><span class="cx">     }, 'instances have the correct methods and properties');
</span><span class="cx"> 
</span><del>-    // var test1 = async_test('read() should never settle');
-    // test1.step(function() {
-    //     var { reader } = factory();
</del><ins>+    test(function() {
+        var { stream } = factory();
</ins><span class="cx"> 
</span><del>-    //     reader.read().then(
-    //         test1.step_func(function() { assert_unreached('read() should not fulfill'); }),
-    //         test1.step_func(function() { assert_unreached('read() should not reject'); })
-    //     );
</del><ins>+        assert_true(stream.locked, 'locked getter should return true');
+    }, 'locked should be true');
</ins><span class="cx"> 
</span><del>-    //     setTimeout(test1.step_func(function() { test1.done(); }), standardTimeout);
-    // });
</del><ins>+    var test1 = async_test('read() should never settle');
+    test1.step(function() {
+        var { reader } = factory();
</ins><span class="cx"> 
</span><del>-    // var test2 = async_test('two read()s should both never settle');
-    // test2.step(function() {
-    //     var { reader } = factory();
</del><ins>+        reader.read().then(
+            test1.step_func(function() { assert_unreached('read() should not fulfill'); }),
+            test1.step_func(function() { assert_unreached('read() should not reject'); })
+        );
</ins><span class="cx"> 
</span><del>-    //     reader.read().then(
-    //         test2.step_func(function() { assert_unreached('first read() should not fulfill'); }),
-    //         test2.step_func(function() { assert_unreached('first read() should not reject'); })
-    //     );
</del><ins>+        setTimeout(test1.step_func(function() { test1.done(); }), 1000);
+    });
</ins><span class="cx"> 
</span><del>-    //     reader.read().then(
-    //         test2.step_func(function() { assert_unreached('second read() should not fulfill'); }),
-    //         test2.step_func(function() { assert_unreached('second read() should not reject'); })
-    //     );
</del><ins>+    var test2 = async_test('two read()s should both never settle');
+    test2.step(function() {
+        var { reader } = factory();
</ins><span class="cx"> 
</span><del>-    //     setTimeout(test2.step_func(function() { test2.done(); }), standardTimeout);
-    // });
</del><ins>+        reader.read().then(
+            test2.step_func(function() { assert_unreached('first read() should not fulfill'); }),
+            test2.step_func(function() { assert_unreached('first read() should not reject'); })
+        );
</ins><span class="cx"> 
</span><ins>+        reader.read().then(
+            test2.step_func(function() { assert_unreached('second read() should not fulfill'); }),
+            test2.step_func(function() { assert_unreached('second read() should not reject'); })
+        );
+
+        setTimeout(test2.step_func(function() { test2.done(); }), 1000);
+    });
+
</ins><span class="cx">     test(function() {
</span><span class="cx">         var { reader } = factory();
</span><span class="cx"> 
</span><span class="lines">@@ -191,29 +220,29 @@
</span><span class="cx">         assert_throws(new TypeError(), function() { stream.getReader(); }, 'stream.getReader() should throw a TypeError');
</span><span class="cx">     }, 'getReader() again on the stream should fail');
</span><span class="cx"> 
</span><del>-    // var test3 = async_test('releasing the lock with pending read requests should throw but the read requests should stay pending');
-    // test3.step(function() {
-    //     var { reader } = factory();
</del><ins>+    var test3 = async_test('releasing the lock with pending read requests should throw but the read requests should stay pending');
+    test3.step(function() {
+        var { reader } = factory();
</ins><span class="cx"> 
</span><del>-    //     reader.read().then(
-    //         test3.step_func(function() { assert_unreached('first read() should not fulfill'); }),
-    //         test3.step_func(function() { assert_unreached('first read() should not reject'); })
-    //     );
</del><ins>+        reader.read().then(
+            test3.step_func(function() { assert_unreached('first read() should not fulfill'); }),
+            test3.step_func(function() { assert_unreached('first read() should not reject'); })
+        );
</ins><span class="cx"> 
</span><del>-    //     reader.read().then(
-    //         test3.step_func(function() { assert_unreached('second read() should not fulfill'); }),
-    //         test3.step_func(function() { assert_unreached('second read() should not reject'); })
-    //     );
</del><ins>+        reader.read().then(
+            test3.step_func(function() { assert_unreached('second read() should not fulfill'); }),
+            test3.step_func(function() { assert_unreached('second read() should not reject'); })
+        );
</ins><span class="cx"> 
</span><del>-    //     reader.closed.then(
-    //         test3.step_func(function() { assert_unreached('closed should not fulfill'); }),
-    //         test3.step_func(function() { assert_unreached('closed should not reject'); })
-    //     );
</del><ins>+        reader.closed.then(
+            test3.step_func(function() { assert_unreached('closed should not fulfill'); }),
+            test3.step_func(function() { assert_unreached('closed should not reject'); })
+        );
</ins><span class="cx"> 
</span><del>-    //     assert_throws(new TypeError(), test3.step_func(function() { reader.releaseLock(); }, 'releaseLock should throw a TypeError'));
</del><ins>+        assert_throws(new TypeError(), test3.step_func(function() { reader.releaseLock(); }, 'releaseLock should throw a TypeError'));
</ins><span class="cx"> 
</span><del>-    //     setTimeout(test3.step_func(function() { test3.done(); }), standardTimeout);
-    // });
</del><ins>+        setTimeout(test3.step_func(function() { test3.done(); }), 1000);
+    });
</ins><span class="cx"> 
</span><span class="cx">     var test4 = async_test('releasing the lock should cause further read() calls to resolve as if the stream is closed');
</span><span class="cx">     test4.step(function() {
</span><span class="lines">@@ -252,6 +281,13 @@
</span><span class="cx">         }));
</span><span class="cx">     });
</span><span class="cx"> 
</span><ins>+    test(function() {
+        var { stream, reader } = factory();
+
+        reader.releaseLock();
+        assert_false(stream.locked, 'locked getter should return false');
+    }, 'releasing the lock should cause locked to become false');
+
</ins><span class="cx">     var test6 = async_test('canceling via the reader should cause the reader to act closed');
</span><span class="cx">     test6.step(function() {
</span><span class="cx">         var { reader } = factory();
</span><span class="lines">@@ -304,39 +340,38 @@
</span><span class="cx">         );
</span><span class="cx">     });
</span><span class="cx"> 
</span><del>-    // var test3 = async_test('cancel() should return a distinct fulfilled promise each time');
-    // test3.step(function() {
-    //     var { reader } = factory();
-    //     var promiseCount = 0;
</del><ins>+    var test3 = async_test('cancel() should return a distinct fulfilled promise each time');
+    test3.step(function() {
+        var { reader } = factory();
+        var promiseCount = 0;
+        var allChecked = false;
</ins><span class="cx"> 
</span><del>-    //     var cancelPromise1 = reader.cancel();
-    //     var cancelPromise2 = reader.cancel();
-    //     var closedReaderPromise = reader.closed;
</del><ins>+        var cancelPromise1 = reader.cancel();
+        var cancelPromise2 = reader.cancel();
+        var closedReaderPromise = reader.closed;
</ins><span class="cx"> 
</span><del>-    //     cancelPromise1.then(test3.step_func(function(v) {
-    //         assert_equals(v, undefined, 'first cancel() call should fulfill with undefined');
-    //         ++promiseCount;
-    //     }));
-    //     cancelPromise2.then(test3.step_func(function(v) {
-    //         assert_equals(v, undefined, 'second cancel() call should fulfill with undefined');
-    //         ++promiseCount;
-    //     }));
-    //     assert_not_equals(cancelPromise1, cancelPromise2, 'cancel() calls should return distinct promises');
-    //     assert_not_equals(cancelPromise1, closedReaderPromise, 'cancel() promise 1 should be distinct from reader.closed');
-    //     assert_not_equals(cancelPromise2, closedReaderPromise, 'cancel() promise 2 should be distinct from reader.closed');
-
-    //     setTimeout(test3.step_func(function() {
-    //         assert_equals(promiseCount, 2);
-    //         test3.done();
-    //     }), standardTimeout);
-    // });
</del><ins>+        cancelPromise1.then(test3.step_func(function(v) {
+            assert_equals(v, undefined, 'first cancel() call should fulfill with undefined');
+            ++promiseCount;
+        }));
+        cancelPromise2.then(test3.step_func(function(v) {
+            assert_equals(v, undefined, 'second cancel() call should fulfill with undefined');
+            assert_equals(++promiseCount, 2);
+            assert_true(allChecked);
+            test3.done();
+        }));
+        assert_not_equals(cancelPromise1, cancelPromise2, 'cancel() calls should return distinct promises');
+        assert_not_equals(cancelPromise1, closedReaderPromise, 'cancel() promise 1 should be distinct from reader.closed');
+        assert_not_equals(cancelPromise2, closedReaderPromise, 'cancel() promise 2 should be distinct from reader.closed');
+        allChecked = true;
+    });
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> function templatedRSErroredReader(label, factory, error) {
</span><span class="cx">     test(function() {
</span><span class="cx">     }, 'Running templatedRSErroredReader with ' + label);
</span><span class="cx"> 
</span><del>-    var test1 = async_test('closed should reject with the error', { timeout: 50 });
</del><ins>+    var test1 = async_test('closed should reject with the error');
</ins><span class="cx">     test1.step(function() {
</span><span class="cx">         var { reader } = factory();
</span><span class="cx"> 
</span><span class="lines">@@ -472,15 +507,16 @@
</span><span class="cx">         })).catch(test2.step_func(function(e) { assert_unreached(e); }));
</span><span class="cx">     });
</span><span class="cx"> 
</span><del>-    var test3 = async_test('draining the stream via read() should cause the reader closed promise to fulfill');
</del><ins>+    var test3 = async_test('draining the stream via read() should cause the reader closed promise to fulfill and locked to be false');
</ins><span class="cx">     test3.step(function() {
</span><del>-        var { reader } = factory();
</del><ins>+        var { stream, reader } = factory();
</ins><span class="cx">         var readCalled = false;
</span><span class="cx"> 
</span><span class="cx">         reader.closed.then(
</span><span class="cx">             test3.step_func(function(v) {
</span><span class="cx">                 assert_true(readCalled);
</span><span class="cx">                 assert_equals(v, undefined, 'reader closed should fulfill with undefined');
</span><ins>+                assert_false(stream.locked, 'stream should no longer be locked');
</ins><span class="cx">                 test3.done();
</span><span class="cx">             }),
</span><span class="cx">             test3.step_func(function() { assert_unreached('reader closed should not reject'); })
</span><span class="lines">@@ -615,24 +651,23 @@
</span><span class="cx">     theError
</span><span class="cx"> );
</span><span class="cx"> 
</span><del>-// FIXME: Activate these tests once Promise handling is supported in start function.
-// templatedRSErrored('ReadableStream (errored via returning a rejected promise in start)', function() {
-//     return new ReadableStream({
-//         start: function() {
-//             return Promise.reject(theError);
-//         }
-//     })},
-//     theError
-// );
</del><ins>+templatedRSErrored('ReadableStream (errored via returning a rejected promise in start)', function() {
+    return new ReadableStream({
+        start: function() {
+            return Promise.reject(theError);
+        }
+    })},
+    theError
+);
</ins><span class="cx"> 
</span><del>-// templatedRSErroredReader('ReadableStream (errored via returning a rejected promise in start) reader', function() {
-//     return streamAndDefaultReader(new ReadableStream({
-//         start: function() {
-//             return Promise.reject(theError);
-//         }
-//     }))},
-//     theError
-// );
</del><ins>+templatedRSErroredReader('ReadableStream (errored via returning a rejected promise in start) reader', function() {
+    return streamAndDefaultReader(new ReadableStream({
+        start: function() {
+            return Promise.reject(theError);
+        }
+    }))},
+    theError
+);
</ins><span class="cx"> 
</span><span class="cx"> var chunks = ['a', 'b'];
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkLayoutTestsstreamsreferenceimplementationreadablestreamhtml"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/streams/reference-implementation/readable-stream.html (185585 => 185586)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/streams/reference-implementation/readable-stream.html        2015-06-16 07:40:09 UTC (rev 185585)
+++ trunk/LayoutTests/streams/reference-implementation/readable-stream.html        2015-06-16 08:19:04 UTC (rev 185586)
</span><span class="lines">@@ -12,21 +12,33 @@
</span><span class="cx"> }, 'ReadableStream can be constructed with no errors');
</span><span class="cx"> 
</span><span class="cx"> test(function() {
</span><ins>+    assert_throws(new TypeError(), function() { new ReadableStream(null); }, 'constructor should throw when the source is null');
+}, 'ReadableStream can\'t be constructed with garbage');
+
+test(function() {
</ins><span class="cx">     var methods = ['cancel', 'constructor', 'getReader', 'pipeThrough', 'pipeTo', 'tee'];
</span><ins>+    var properties = methods.concat(['locked']).sort();
</ins><span class="cx"> 
</span><span class="cx">     var rs = new ReadableStream();
</span><span class="cx">     var proto = Object.getPrototypeOf(rs);
</span><span class="cx"> 
</span><del>-    assert_array_equals(Object.getOwnPropertyNames(proto).sort(), methods, 'should have all the correct methods');
</del><ins>+    assert_array_equals(Object.getOwnPropertyNames(proto).sort(), properties, 'should have all the correct methods');
</ins><span class="cx"> 
</span><span class="cx">     for (var m of methods) {
</span><span class="cx">         var propDesc = Object.getOwnPropertyDescriptor(proto, m);
</span><del>-        assert_equals(propDesc.enumerable, false, 'method should be non-enumerable');
-        assert_equals(propDesc.configurable, true, 'method should be configurable');
-        assert_equals(propDesc.writable, true, 'method should be writable');
</del><ins>+        assert_false(propDesc.enumerable, 'method should be non-enumerable');
+        assert_true(propDesc.configurable, 'method should be configurable');
+        assert_true(propDesc.writable, 'method should be writable');
</ins><span class="cx">         assert_equals(typeof rs[m], 'function', 'should have be a method');
</span><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    var lockedPropDesc = Object.getOwnPropertyDescriptor(proto, 'locked');
+    assert_false(lockedPropDesc.enumerable, 'locked should be non-enumerable');
+    assert_equals(lockedPropDesc.writable, undefined, 'locked should not be a data property');
+    assert_equals(typeof lockedPropDesc.get, 'function', 'locked should have a getter');
+    assert_equals(lockedPropDesc.set, undefined, 'locked should not have a setter');
+    assert_true(lockedPropDesc.configurable, 'locked should be configurable');
+
</ins><span class="cx">     assert_equals(rs.cancel.length, 1, 'cancel should have 1 parameter');
</span><span class="cx">     assert_equals(rs.constructor.length, 0, 'constructor should have no parameters');
</span><span class="cx">     assert_equals(rs.getReader.length, 0, 'getReader should have no parameters');
</span><span class="lines">@@ -50,60 +62,132 @@
</span><span class="cx"> }, 'ReadableStream constructor can get initial garbage as pull argument');
</span><span class="cx"> 
</span><span class="cx"> test(function() {
</span><del>-    new ReadableStream({ strategy: 2 }); // Constructor should not throw when strategy is not an object.
-}, 'ReadableStream constructor can get initial garbage as strategy argument');
</del><ins>+    var startCalled = false;
+    var source = {
+        start: function(controller) {
+            assert_equals(this, source, 'source is this during start');
</ins><span class="cx"> 
</span><del>-var test1 = async_test('ReadableStream start should be able to return a promise');
</del><ins>+            var methods = ['close', 'enqueue', 'error', 'constructor'];
+            var properties = ['desiredSize'].concat(methods).sort();
+            var proto = Object.getPrototypeOf(controller);
+
+            assert_array_equals(Object.getOwnPropertyNames(proto).sort(), properties,
+                                'the controller should have the right properties');
+
+            for (var m of methods) {
+                var propDesc = Object.getOwnPropertyDescriptor(proto, m);
+                assert_equals(typeof controller[m], 'function', `should have a ${m} method`);
+                assert_false(propDesc.enumerable, m + &quot; should be non-enumerable&quot;);
+                assert_true(propDesc.configurable, m + &quot; should be configurable&quot;);
+                assert_true(propDesc.writable, m + &quot; should be writable&quot;);
+            }
+
+            var desiredSizePropDesc = Object.getOwnPropertyDescriptor(proto, 'desiredSize');
+            assert_false(desiredSizePropDesc.enumerable, 'desiredSize should be non-enumerable');
+            assert_equals(desiredSizePropDesc.writable, undefined, 'desiredSize should not be a data property');
+            assert_equals(typeof desiredSizePropDesc.get, 'function', 'desiredSize should have a getter');
+            assert_equals(desiredSizePropDesc.set, undefined, 'desiredSize should not have a setter');
+            assert_true(desiredSizePropDesc.configurable, 'desiredSize should be configurable');
+
+            assert_equals(controller.close.length, 0, 'close should have no parameters');
+            assert_equals(controller.constructor.length, 1, 'constructor should have 1 parameter');
+            assert_equals(controller.enqueue.length, 1, 'enqueue should have 1 parameter');
+            assert_equals(controller.error.length, 1, 'error should have 1 parameter');
+
+            startCalled = true;
+        }
+    };
+
+    new ReadableStream(source);
+    assert_true(startCalled);
+}, 'ReadableStream start should be called with the proper parameters');
+
+test(function() {
+    var startCalled = false;
+    var source = {
+        start: function(controller) {
+            var properties = ['close', 'constructor', 'desiredSize', 'enqueue', 'error'];
+            assert_array_equals(Object.getOwnPropertyNames(Object.getPrototypeOf(controller)).sort(), properties,
+                                'prototype should have the right properties');
+            controller.test = '';
+            assert_array_equals(Object.getOwnPropertyNames(Object.getPrototypeOf(controller)).sort(), properties,
+                                'prototype should still have the right properties');
+            assert_not_equals(Object.getOwnPropertyNames(controller).indexOf('test'), -1,
+                              '&quot;test&quot; should be a property of the controller');
+
+            startCalled = true;
+        }
+    };
+
+    var rs = new ReadableStream(source);
+    assert_true(startCalled);
+}, 'ReadableStream start controller parameter should be extensible');
+
+var test1 = async_test('ReadableStream should be able to call start method within prototype chain of its source');
</ins><span class="cx"> test1.step(function()
</span><span class="cx"> {
</span><ins>+    function SimpleStreamSource() {
+    };
+    SimpleStreamSource.prototype = {
+        start: function() {
+            test1.done('start should be called');
+        },
+    }
+
+    new ReadableStream(new SimpleStreamSource());
+});
+
+var test2 = async_test('ReadableStream start should be able to return a promise');
+test2.step(function()
+{
</ins><span class="cx">     var readCalled = false;
</span><span class="cx">     var rs = new ReadableStream({
</span><span class="cx">         start: function(c) {
</span><del>-            return new Promise(test1.step_func(function(resolve, reject) {
-                setTimeout(test1.step_func(function() {
</del><ins>+            return new Promise(test2.step_func(function(resolve, reject) {
+                setTimeout(test2.step_func(function() {
</ins><span class="cx">                     c.enqueue('a');
</span><span class="cx">                     c.close();
</span><span class="cx">                     resolve();
</span><del>-                }), standardTimeout);
</del><ins>+                }), 500);
</ins><span class="cx">             }));
</span><span class="cx">         },
</span><span class="cx">     });
</span><span class="cx"> 
</span><span class="cx">     var reader = rs.getReader();
</span><span class="cx"> 
</span><del>-    reader.read().then(test1.step_func(function(r) {
</del><ins>+    reader.read().then(test2.step_func(function(r) {
</ins><span class="cx">         readCalled = true;
</span><span class="cx">         assert_object_equals(r, { value: 'a', done: false }, 'value read should be the one enqueued');
</span><span class="cx">     }));
</span><span class="cx"> 
</span><del>-    reader.closed.then(test1.step_func(function() {
</del><ins>+    reader.closed.then(test2.step_func(function() {
</ins><span class="cx">         assert_true(readCalled);
</span><del>-        test1.done('stream should close successfully');
</del><ins>+        test2.done('stream should close successfully');
</ins><span class="cx">     }));
</span><span class="cx"> });
</span><span class="cx"> 
</span><del>-var test2 = async_test('ReadableStream start should be able to return a promise and reject it');
-test2.step(function()
</del><ins>+var test3 = async_test('ReadableStream start should be able to return a promise and reject it', { timeout: 100 });
+test3.step(function()
</ins><span class="cx"> {
</span><span class="cx">     var theError = new Error('rejected!');
</span><span class="cx">     var rs = new ReadableStream({
</span><span class="cx">         start: function() {
</span><del>-            return new Promise(test2.step_func(function(resolve, reject) {
-                setTimeout(test2.step_func(function() {
</del><ins>+            return new Promise(test3.step_func(function(resolve, reject) {
+                setTimeout(test3.step_func(function() {
</ins><span class="cx">                     reject(theError);
</span><del>-                }), standardTimeout);
</del><ins>+                }), 500);
</ins><span class="cx">             }));
</span><span class="cx">         },
</span><span class="cx">     });
</span><span class="cx"> 
</span><del>-    rs.getReader().closed.catch(test2.step_func(function(e) {
</del><ins>+    rs.getReader().closed.catch(test3.step_func(function(e) {
</ins><span class="cx">         assert_equals(e, theError, 'promise should be rejected with the same error');
</span><del>-        test2.done();
</del><ins>+        test3.done();
</ins><span class="cx">     }));
</span><span class="cx"> });
</span><span class="cx"> 
</span><del>-var test3 = async_test('ReadableStream should be able to enqueue different objects.');
-test3.step(function() {
</del><ins>+var test4 = async_test('ReadableStream should be able to enqueue different objects.');
+test4.step(function() {
</ins><span class="cx">     var readCalls = 0;
</span><span class="cx">     var objects = [
</span><span class="cx">     { potato: 'Give me more!'},
</span><span class="lines">@@ -122,32 +206,26 @@
</span><span class="cx"> 
</span><span class="cx">     var reader = rs.getReader();
</span><span class="cx"> 
</span><del>-    reader.read().then(test3.step_func(function(r) {
</del><ins>+    reader.read().then(test4.step_func(function(r) {
</ins><span class="cx">         assert_object_equals(r, { value: objects[readCalls++], done: false }, 'value read should be the one enqueued');
</span><span class="cx">     }));
</span><span class="cx"> 
</span><del>-    reader.read().then(test3.step_func(function(r) {
</del><ins>+    reader.read().then(test4.step_func(function(r) {
</ins><span class="cx">         assert_object_equals(r, { value: objects[readCalls++], done: false }, 'value read should be the one enqueued');
</span><span class="cx">     }));
</span><span class="cx"> 
</span><del>-    reader.read().then(test3.step_func(function(r) {
</del><ins>+    reader.read().then(test4.step_func(function(r) {
</ins><span class="cx">         assert_object_equals(r, { value: objects[readCalls++], done: false }, 'value read should be the one enqueued');
</span><span class="cx">     }));
</span><span class="cx"> 
</span><del>-    reader.closed.then(test3.step_func(function() {
</del><ins>+    reader.closed.then(test4.step_func(function() {
</ins><span class="cx">         assert_equals(readCalls, 3);
</span><del>-        test3.done('stream should close correctly correctly');
</del><ins>+        test4.done('stream should close correctly correctly');
</ins><span class="cx">     }));
</span><span class="cx"> });
</span><span class="cx"> 
</span><del>-test(function() {
-    var error = new Error('aaaugh!!');
-
-    assert_throws(error, function() { new ReadableStream({ start() { throw error; } }) }, 'error should be re-thrown');
-}, 'ReadableStream: if start throws an error, it should be re-thrown');
-
-var test4 = async_test('ReadableStream: if pull rejects, it should error the stream', { timeout: 50 });
-test4.step(function() {
</del><ins>+var test5 = async_test('ReadableStream: if pull rejects, it should error the stream', { timeout: 50 });
+test5.step(function() {
</ins><span class="cx">     var error = new Error('pull failure');
</span><span class="cx">     var rs = new ReadableStream({
</span><span class="cx">         pull: function() {
</span><span class="lines">@@ -160,214 +238,173 @@
</span><span class="cx">     var closed = false;
</span><span class="cx">     var read = false;
</span><span class="cx"> 
</span><del>-    reader.closed.catch(test4.step_func(function(e) {
</del><ins>+    reader.closed.catch(test5.step_func(function(e) {
</ins><span class="cx">         closed = true;
</span><span class="cx">         assert_false(read);
</span><span class="cx">         assert_equals(e, error, 'closed should reject with the thrown error');
</span><span class="cx">     }));
</span><span class="cx"> 
</span><del>-    reader.read().catch(test4.step_func(function(e) {
</del><ins>+    reader.read().catch(test5.step_func(function(e) {
</ins><span class="cx">         read = true;
</span><span class="cx">         assert_true(closed);
</span><span class="cx">         assert_equals(e, error, 'read() should reject with the thrown error');
</span><del>-        test4.done();
</del><ins>+        test5.done();
</ins><span class="cx">     }));
</span><span class="cx"> });
</span><span class="cx"> 
</span><del>-// var test5 = async_test('ReadableStream: should only call pull once upon starting the stream');
-// test5.step(function() {
-//     var pullCount = 0;
-//     var startPromise = Promise.resolve();
-//     var rs = new ReadableStream({
-//         start: function() {
-//             return startPromise;
-//         },
-//         pull: function() {
-//             pullCount++;
-//         }
-//     });
</del><ins>+var test6 = async_test('ReadableStream: should only call pull once upon starting the stream');
+test6.step(function() {
+    var pullCount = 0;
+    var startPromise = Promise.resolve();
+    var rs = new ReadableStream({
+        start: function() {
+            return startPromise;
+        },
+        pull: function() {
+            pullCount++;
+        }
+    });
</ins><span class="cx"> 
</span><del>-//     startPromise.then(test5.step_func(function() {
-//         assert_equals(pullCount, 1, 'pull should be called once start finishes');
-//     }));
</del><ins>+    startPromise.then(test6.step_func(function() {
+        assert_equals(pullCount, 1, 'pull should be called once start finishes');
+    }));
</ins><span class="cx"> 
</span><del>-//     setTimeout(test5.step_func(function() {
-//         assert_equals(pullCount, 1, 'pull should be called exactly once');
-//         test5.done();
-//     }), standardTimeout);
-// });
</del><ins>+    setTimeout(test6.step_func(function() {
+        assert_equals(pullCount, 1, 'pull should be called exactly once');
+        test6.done();
+    }), 1000);
+});
</ins><span class="cx"> 
</span><del>-// var test6 = async_test('ReadableStream: should only call pull once for a forever-empty stream, even after reading');
-// test6.step(function() {
-//     var pullCount = 0;
-//     var startPromise = Promise.resolve();
-//     var rs = new ReadableStream({
-//         start: function() {
-//             return startPromise;
-//         },
-//         pull: function() {
-//             pullCount++;
-//         }
-//     });
</del><ins>+var test7 = async_test('ReadableStream: should call pull when trying to read from a started, empty stream');
+test7.step(function() {
+    var pullCount = 0;
+    var startPromise = Promise.resolve();
+    var rs = new ReadableStream({
+        start: function() {
+            return startPromise;
+        },
+        pull: function(c) {
+            // Don't enqueue immediately after start. We want the stream to be empty when we call .read() on it.
+            if (pullCount &gt; 0) {
+                c.enqueue(pullCount);
+            }
</ins><span class="cx"> 
</span><del>-//     startPromise.then(test6.step_func(function() {
-//         assert_equals(pullCount, 1, 'pull should be called once start finishes');
-//     }));
</del><ins>+            ++pullCount;
+        }
+    });
</ins><span class="cx"> 
</span><del>-//     rs.getReader().read();
</del><ins>+    startPromise.then(test7.step_func(function() {
+        assert_equals(pullCount, 1, 'pull should be called once start finishes');
</ins><span class="cx"> 
</span><del>-//     setTimeout(test6.step_func(function() {
-//         assert_equals(pullCount, 1, 'pull should be called exactly once');
-//         test6.done();
-//     }), standardTimeout);
-// });
</del><ins>+        var reader = rs.getReader();
+        return reader.read().then(test7.step_func(function(result) {
+            assert_equals(pullCount, 2, 'pull should be called again in reaction to calling read');
+            assert_object_equals(result, { value: 1, done: false }, 'the result read should be the one enqueued');
+            test7.done();
+        }));
+    })).catch(test7.step_func(function(e) { assert_unreached(e); }));
+});
</ins><span class="cx"> 
</span><del>-// var test7 = async_test('ReadableStream: should only call pull once on a non-empty stream read from before start fulfills');
-// test7.step(function() {
-//     var pullCount = 0;
-//     var startPromise = Promise.resolve();
-//     var rs = new ReadableStream({
-//         start: function(c) {
-//             c.enqueue('a');
-//             return startPromise;
-//         },
-//         pull: function() {
-//             pullCount++;
-//         }
-//     });
</del><ins>+var test8 = async_test('ReadableStream: should only call pull once on a non-empty stream read from before start fulfills');
+test8.step(function() {
+    var pullCount = 0;
+    var startPromise = Promise.resolve();
+    var rs = new ReadableStream({
+        start: function(c) {
+            c.enqueue('a');
+            return startPromise;
+        },
+        pull: function() {
+            pullCount++;
+        }
+    });
</ins><span class="cx"> 
</span><del>-//     startPromise.then(test7.step_func(function() {
-//         assert_equals(pullCount, 1, 'pull should be called once start finishes');
-//     }));
</del><ins>+    startPromise.then(test8.step_func(function() {
+        assert_equals(pullCount, 1, 'pull should be called once start finishes');
+    }));
</ins><span class="cx"> 
</span><del>-//     rs.getReader().read().then(test7.step_func(function(r) {
-//         assert_object_equals(r, { value: 'a', done: false }, 'first read() should return first chunk');
-//         assert_equals(pullCount, 1, 'pull should not have been called again');
-//     }));
</del><ins>+    rs.getReader().read().then(test8.step_func(function(r) {
+        assert_object_equals(r, { value: 'a', done: false }, 'first read() should return first chunk');
+        assert_equals(pullCount, 1, 'pull should not have been called again');
+    }));
</ins><span class="cx"> 
</span><del>-//     assert_equals(pullCount, 0, 'calling read() should not cause pull to be called yet');
</del><ins>+    assert_equals(pullCount, 0, 'calling read() should not cause pull to be called yet');
</ins><span class="cx"> 
</span><del>-//     setTimeout(test7.step_func(function() {
-//         assert_equals(pullCount, 1, 'pull should be called exactly once');
-//         test7.done();
-//     }), standardTimeout);
-// });
</del><ins>+    setTimeout(test8.step_func(function() {
+        assert_equals(pullCount, 1, 'pull should be called exactly once');
+        test8.done();
+    }), 1000);
+});
</ins><span class="cx"> 
</span><del>-// var test8 = async_test('ReadableStream: should only call pull twice on a non-empty stream read from after start fulfills');
-// test8.step(function() {
-//     var pullCount = 0;
-//     var startPromise = Promise.resolve();
-//     var rs = new ReadableStream({
-//         start: function(c) {
-//             c.enqueue('a');
-//             return startPromise;
-//         },
-//         pull: function() {
-//             pullCount++;
-//         }
-//     });
</del><ins>+var test9 = async_test('ReadableStream: should only call pull once on a non-empty stream read from after start fulfills');
+test9.step(function() {
+    var pullCount = 0;
+    var startPromise = Promise.resolve();
+    var rs = new ReadableStream({
+        start: function(c) {
+            c.enqueue('a');
+            return startPromise;
+        },
+        pull: function() {
+            pullCount++;
+        }
+    });
</ins><span class="cx"> 
</span><del>-//     startPromise.then(test8.step_func(function() {
-//         assert_equals(pullCount, 1, 'pull should be called once start finishes');
</del><ins>+    startPromise.then(test9.step_func(function() {
+        assert_equals(pullCount, 0, 'pull should not be called once start finishes, since the queue is full');
</ins><span class="cx"> 
</span><del>-//         rs.getReader().read().then(test8.step_func(function(r) {
-//             assert_object_equals(r, { value: 'a', done: false }, 'first read() should return first chunk');
-//             assert_equals(pullCount, 2, 'pull should be called again once read fulfills');
-//         }));
-//     }));
</del><ins>+        rs.getReader().read().then(test9.step_func(function(r) {
+            assert_object_equals(r, { value: 'a', done: false }, 'first read() should return first chunk');
</ins><span class="cx"> 
</span><del>-//     assert_equals(pullCount, 0, 'calling read() should not cause pull to be called yet');
</del><ins>+            setTimeout(test9.step_func(function() {
+                assert_equals(pullCount, 1, 'pull should be called exactly once');
+                test9.done();
+            }), 1000);
+                                       
+        }));
</ins><span class="cx"> 
</span><del>-//     setTimeout(test8.step_func(function() {
-//         assert_equals(pullCount, 2, 'pull should be called exactly twice')
-//         test8.done();
-//     }), standardTimeout);
-// });
</del><ins>+        assert_equals(pullCount, 1, 'calling read() should not cause pull to be called immediately');
+    }));
+});
</ins><span class="cx"> 
</span><del>-// var test9 = async_test('ReadableStream: should call pull in reaction to read()ing the last chunk, if not draining');
-// test9.step(function() {
-//     var pullCount = 0;
-//     var controller;
-//     var startPromise = Promise.resolve();
-//     var pullPromise = Promise.resolve();
-//     var rs = new ReadableStream({
-//         start: function(c) {
-//             controller = c;
-//             return startPromise;
-//         },
-//         pull: function() {
-//             ++pullCount;
-//             return pullPromise;
-//         }
-//     });
</del><ins>+var test10 = async_test('ReadableStream: should not call pull() in reaction to read()ing the last chunk, if draining');
+test10.step(function() {
+    var pullCount = 0;
+    var controller;
+    var startPromise = Promise.resolve();
+    var pullPromise = Promise.resolve();
+    var rs = new ReadableStream({
+        start: function(c) {
+            controller = c;
+            return startPromise;
+        },
+        pull: function() {
+            ++pullCount;
+            return pullPromise;
+        }
+    });
</ins><span class="cx"> 
</span><del>-//     var reader = rs.getReader();
</del><ins>+    var reader = rs.getReader();
</ins><span class="cx"> 
</span><del>-//     startPromise.then(test9.step_func(function() {
-//         assert_equals(pullCount, 1, 'pull should have been called once after read');
</del><ins>+    startPromise.then(test10.step_func(function() {
+        assert_equals(pullCount, 1, 'pull should have been called once by the time the stream starts');
</ins><span class="cx"> 
</span><del>-//         controller.enqueue('a');
</del><ins>+        controller.enqueue('a');
+        assert_equals(pullCount, 1, 'pull should not have been called again after enqueue');
</ins><span class="cx"> 
</span><del>-//         return pullPromise.then(test9.step_func(function() {
-//             assert_equals(pullCount, 2, 'pull should have been called a second time after enqueue');
</del><ins>+        controller.close();
</ins><span class="cx"> 
</span><del>-//             return reader.read().then(test9.step_func(function() {
-//                 assert_equals(pullCount, 3, 'pull should have been called a third time after read');
-//             }));
-//         }));
-//     })).catch(test9.step_func(function(e) {
-//         assert_unreached(e);
-//     }));
</del><ins>+        return reader.read().then(test10.step_func(function() {
+            assert_equals(pullCount, 1, 'pull should not have been called a second time after read');
</ins><span class="cx"> 
</span><del>-//     setTimeout(test9.step_func(function() {
-//         assert_equals(pullCount, 3, 'pull should be called exactly thrice')
-//         test9.done();
-//     }), standardTimeout);
-// });
</del><ins>+            setTimeout(test10.step_func(function() {
+                assert_equals(pullCount, 1, 'pull should be called exactly once');
+                test10.done();
+            }), 1000);
+        }));
+    })).catch(test10.step_func(function(e) { assert_unreached(e); }));
+});
</ins><span class="cx"> 
</span><del>-// var test10 = async_test('ReadableStream: should not call pull() in reaction to read()ing the last chunk, if draining');
-// test10.step(function() {
-//     var pullCount = 0;
-//     var controller;
-//     var startPromise = Promise.resolve();
-//     var pullPromise = Promise.resolve();
-//     var rs = new ReadableStream({
-//         start: function(c) {
-//             controller = c;
-//             return startPromise;
-//         },
-//         pull: function() {
-//             ++pullCount;
-//             return pullPromise;
-//         }
-//     });
-
-//     var reader = rs.getReader();
-
-//     startPromise.then(test10.step_func(function() {
-//         assert_equals(pullCount, 1, 'pull should have been called once after read');
-
-//         controller.enqueue('a');
-
-//         return pullPromise.then(test10.step_func(function() {
-//             assert_equals(pullCount, 2, 'pull should have been called a second time after enqueue');
-
-//             controller.close();
-
-//             return reader.read().then(test10.step_func(function() {
-//                 assert_equals(pullCount, 2, 'pull should not have been called a third time after read');
-//             }));
-//         }));
-//     })).catch(test10.step_func(function(e) {
-//         assert_unreached(e)
-//     }));
-
-//     setTimeout(test10.step_func(function() {
-//         assert_equals(pullCount, 2, 'pull should be called exactly twice')
-//         test10.done();
-//     }), standardTimeout);
-// });
-
</del><span class="cx"> var test11 = async_test('ReadableStream: should not call pull until the previous pull call\'s promise fulfills');
</span><span class="cx"> test11.step(function() {
</span><span class="cx">     var resolve;
</span><span class="lines">@@ -375,12 +412,11 @@
</span><span class="cx">     var timesCalled = 0;
</span><span class="cx">     var startPromise = Promise.resolve();
</span><span class="cx">     var rs = new ReadableStream({
</span><del>-        start: function(c) {
-            c.enqueue('a');
</del><ins>+        start: function() {
</ins><span class="cx">             return startPromise;
</span><span class="cx">         },
</span><del>-        pull: function() {
-            ++timesCalled;
</del><ins>+        pull: function(c) {
+            c.enqueue(++timesCalled);
</ins><span class="cx">             returnedPromise = new Promise(test11.step_func(function(r) { resolve = r; }));
</span><span class="cx">             return returnedPromise;
</span><span class="cx">         }
</span><span class="lines">@@ -388,9 +424,10 @@
</span><span class="cx">     var reader = rs.getReader();
</span><span class="cx"> 
</span><span class="cx">     startPromise.then(test11.step_func(function() {
</span><del>-        reader.read().then(test11.step_func(function(result1) {
-            assert_equals(timesCalled, 1, 'pull should have been called once after start, but not yet have been called a second time');
-            assert_object_equals(result1, { value: 'a', done: false }, 'read() should fulfill with the enqueued value');
</del><ins>+        return reader.read().then(test11.step_func(function(result1) {
+            assert_equals(timesCalled, 1,
+                          'pull should have been called once after start, but not yet have been called a second time');
+            assert_object_equals(result1, { value: 1, done: false }, 'read() should fulfill with the enqueued value');
</ins><span class="cx"> 
</span><span class="cx">             setTimeout(test11.step_func(function() {
</span><span class="cx">                 assert_equals(timesCalled, 1, 'after 30 ms, pull should still only have been called once');
</span><span class="lines">@@ -398,61 +435,58 @@
</span><span class="cx">                 resolve();
</span><span class="cx"> 
</span><span class="cx">                 returnedPromise.then(test11.step_func(function() {
</span><del>-                    assert_equals(timesCalled, 2, 'after the promise returned by pull is fulfilled, pull should be called a second time');
</del><ins>+                    assert_equals(timesCalled, 2,
+                                  'after the promise returned by pull is fulfilled, pull should be called a second time');
</ins><span class="cx">                     test11.done();
</span><span class="cx">                 }));
</span><del>-            }), standardTimeout);
-        }))
-    })).catch(test11.step_func(function(e) {
-        assert_unreached(e)
-    }));
</del><ins>+            }), 500);
+        }));
+    })).catch(test11.step_func(function(e) { assert_unreached(e); }));
</ins><span class="cx"> });
</span><span class="cx"> 
</span><del>-// var test12 = async_test('ReadableStream: should pull after start, and after every read');
-// test12.step(function() {
-//     var timesCalled = 0;
-//     var startPromise = Promise.resolve();
-//     var rs = new ReadableStream({
-//         start: function(c) {
-//             c.enqueue('a');
-//             c.enqueue('b');
-//             c.enqueue('c');
-//             return startPromise;
-//         },
-//         pull: function() {
-//             ++timesCalled;
-//         },
-//         strategy: {
-//             size: function() {
-//                 return 1;
-//             },
-//             shouldApplyBackpressure: function() {
-//                 return false;
-//             }
-//         }
-//     });
-//     var reader = rs.getReader();
</del><ins>+var test12 = async_test('ReadableStream: should pull after start, and after every read');
+test12.step(function() {
+    var timesCalled = 0;
+    var startPromise = Promise.resolve();
+    var rs = new ReadableStream({
+        start: function(c) {
+            c.enqueue('a');
+            c.enqueue('b');
+            c.enqueue('c');
+            return startPromise;
+        },
+        pull() {
+            ++timesCalled;
+        }
+    },
+    {
+        size: function() {
+            return 1;
+        },
+        highWaterMark: Infinity
+    });
+    var reader = rs.getReader();
</ins><span class="cx"> 
</span><del>-//     startPromise.then(test12.step_func(function() {
-//         return reader.read().then(test12.step_func(function(result1) {
-//             assert_object_equals(result1, { value: 'a', done: false }, 'first chunk should be as expected');
</del><ins>+    startPromise.then(test12.step_func(function() {
+        return reader.read().then(test12.step_func(function(result1) {
+            assert_object_equals(result1, { value: 'a', done: false }, 'first chunk should be as expected');
</ins><span class="cx"> 
</span><del>-//             return reader.read().then(test12.step_func(function(result2) {
-//                 assert_object_equals(result2, { value: 'b', done: false }, 'second chunk should be as expected');
</del><ins>+            return reader.read().then(test12.step_func(function(result2) {
+                assert_object_equals(result2, { value: 'b', done: false }, 'second chunk should be as expected');
</ins><span class="cx"> 
</span><del>-//                 return reader.read().then(test12.step_func(function(result3) {
-//                     assert_object_equals(result3, { value: 'c', done: false }, 'third chunk should be as expected');
</del><ins>+                return reader.read().then(test12.step_func(function(result3) {
+                    assert_object_equals(result3, { value: 'c', done: false }, 'third chunk should be as expected');
</ins><span class="cx"> 
</span><del>-//                     setTimeout(test12.step_func(function() {
-//                         // Once for after start, and once for every read.
-//                         assert_equals(timesCalled, 4, 'pull() should be called exactly four times');
-//                         test12.done();
-//                     }), standardTimeout);
-//                 }));
-//             }));
-//         }));
-//     })).catch(test12.step_func(function(e) { assert_unreached(e); }));
-// });
</del><ins>+                    setTimeout(test12.step_func(function() {
+                        // Once for after start, and once for every read.
+                        assert_equals(timesCalled, 4, 'pull() should be called exactly four times');
+                        test12.done();
+                    }), 1000);
+                }));
+            }));
+        }));
+    })).catch(test12.step_func(function(e) { assert_unreached(e); }));
+});
</ins><span class="cx"> 
</span><span class="cx"> var test13 = async_test('ReadableStream: should not call pull after start if the stream is now closed');
</span><span class="cx"> test13.step(function() {
</span><span class="lines">@@ -494,18 +528,16 @@
</span><span class="cx">         },
</span><span class="cx">         pull: function(c) {
</span><span class="cx">             c.enqueue(++timesCalled);
</span><ins>+        }
+    },
+    {
+        size: function() {
+            return 1;
</ins><span class="cx">         },
</span><del>-        strategy: {
-            size: function() {
-                return 1;
-            },
-            shouldApplyBackpressure: function(size) {
-                return size &gt; 3;
-            }
-        }
</del><ins>+        highWaterMark: 4
</ins><span class="cx">     });
</span><span class="cx"> 
</span><del>-    startPromise.then(test14.step_func(function() {
</del><ins>+    setTimeout(test14.step_func(function() {
</ins><span class="cx">         // after start: size = 0, pull()
</span><span class="cx">         // after enqueue(1): size = 1, pull()
</span><span class="cx">         // after enqueue(2): size = 2, pull()
</span><span class="lines">@@ -513,7 +545,7 @@
</span><span class="cx">         // after enqueue(4): size = 4, do not pull
</span><span class="cx">         assert_equals(timesCalled, 4, 'pull() should have been called four times');
</span><span class="cx">         test14.done();
</span><del>-    }));
</del><ins>+    }), 1000);
</ins><span class="cx"> });
</span><span class="cx"> 
</span><span class="cx"> var test15 = async_test('ReadableStream pull should be able to close a stream.');
</span><span class="lines">@@ -534,35 +566,44 @@
</span><span class="cx"> });
</span><span class="cx"> 
</span><span class="cx"> test(function() {
</span><del>-  var rs = new ReadableStream({
-      start: function(c) {
-          assert_equals(c.enqueue('a'), true, 'the first enqueue should return true');
-          c.close();
</del><ins>+    var startCalled = false;
+    var rs = new ReadableStream({
+        start: function(c) {
+            assert_equals(c.enqueue('a'), undefined, 'the first enqueue should return undefined');
+            c.close();
</ins><span class="cx"> 
</span><del>-          assert_throws(new TypeError(''), function() { c.enqueue('b'); }, 'enqueue after close should throw a TypeError');
-      }
-  });
</del><ins>+            assert_throws(new TypeError(''), function() { c.enqueue('b'); }, 'enqueue after close should throw a TypeError');
+            startCalled = true;
+        }
+    });
+    assert_true(startCalled);
</ins><span class="cx"> }, 'ReadableStream: enqueue should throw when the stream is readable but draining');
</span><span class="cx"> 
</span><span class="cx"> test(function() {
</span><ins>+    var startCalled = false;
</ins><span class="cx">     var rs = new ReadableStream({
</span><span class="cx">         start: function(c) {
</span><span class="cx">             c.close();
</span><span class="cx"> 
</span><span class="cx">             assert_throws(new TypeError(), function() { c.enqueue('a'); }, 'enqueue after close should throw a TypeError');
</span><ins>+            startCalled = true;
</ins><span class="cx">         }
</span><span class="cx">     });
</span><ins>+    assert_true(startCalled);
</ins><span class="cx"> }, 'ReadableStream: enqueue should throw when the stream is closed');
</span><span class="cx"> 
</span><span class="cx"> test(function() {
</span><ins>+    var startCalled = false;
</ins><span class="cx">     var expectedError = new Error('i am sad');
</span><span class="cx">     var rs = new ReadableStream({
</span><span class="cx">         start: function(c) {
</span><span class="cx">             c.error(expectedError);
</span><span class="cx"> 
</span><span class="cx">             assert_throws(expectedError, function() { c.enqueue('a'); }, 'enqueue after error should throw that error');
</span><ins>+            startCalled = true;
</ins><span class="cx">         }
</span><span class="cx">     });
</span><ins>+    assert_true(startCalled);
</ins><span class="cx"> }, 'ReadableStream: enqueue should throw the stored error when the stream is errored');
</span><span class="cx"> 
</span><span class="cx"> var test16 = async_test('ReadableStream: should call underlying source methods as methods');
</span><span class="lines">@@ -570,7 +611,6 @@
</span><span class="cx">     var startCalled = 0;
</span><span class="cx">     var pullCalled = 0;
</span><span class="cx">     var cancelCalled = 0;
</span><del>-    var strategyCalled = 0;
</del><span class="cx"> 
</span><span class="cx">     function Source() {
</span><span class="cx">     }
</span><span class="lines">@@ -591,13 +631,6 @@
</span><span class="cx">             cancelCalled++;
</span><span class="cx">             assert_equals(this, theSource, 'cancel() should be called with the correct this');
</span><span class="cx">         },
</span><del>-
-        get strategy() {
-            // Called three times
-            strategyCalled++;
-            assert_equals(this, theSource, 'strategy getter should be called with the correct this');
-            return undefined;
-        }
</del><span class="cx">     };
</span><span class="cx"> 
</span><span class="cx">     var theSource = new Source();
</span><span class="lines">@@ -611,24 +644,31 @@
</span><span class="cx">         assert_equals(startCalled, 1);
</span><span class="cx">         assert_equals(pullCalled, 1);
</span><span class="cx">         assert_equals(cancelCalled, 1);
</span><del>-        assert_equals(strategyCalled, 3);
</del><span class="cx">         test16.done();
</span><span class="cx">     })).catch(test16.step_func(function(e) { assert_unreached(e); } ));
</span><span class="cx"> });
</span><span class="cx"> 
</span><span class="cx"> test(function() {
</span><del>-  new ReadableStream({
-      start: function(c) {
-          assert_equals(c.enqueue('a'), true, 'first enqueue should return true');
-          assert_equals(c.enqueue('b'), false, 'second enqueue should return false');
-          assert_equals(c.enqueue('c'), false, 'third enqueue should return false');
-          assert_equals(c.enqueue('d'), false, 'fourth enqueue should return false');
-          assert_equals(c.enqueue('e'), false, 'fifth enqueue should return false');
-      }
-  });
-}, 'ReadableStream strategies: the default strategy should return false for all but the first enqueue call');
</del><ins>+    var startCalled = false;
+    new ReadableStream({
+        start: function(c) {
+            assert_equals(c.desiredSize, 1);
+            c.enqueue('a');
+            assert_equals(c.desiredSize, 0);
+            c.enqueue('b');
+            assert_equals(c.desiredSize, -1);
+            c.enqueue('c');
+            assert_equals(c.desiredSize, -2);
+            c.enqueue('d');
+            assert_equals(c.desiredSize, -3);
+            c.enqueue('e');
+            startCalled = true;
+        }
+    });
+    assert_true(startCalled);
+}, 'ReadableStream strategies: the default strategy should give desiredSize of 1 to start, decreasing by 1 per enqueue');
</ins><span class="cx"> 
</span><del>-var test17 = async_test('ReadableStream strategies: the default strategy should continue returning true from enqueue if the chunks are read immediately');
</del><ins>+var test17 = async_test('ReadableStream strategies: the default strategy should continue giving desiredSize of 1 if the chunks are read immediately');
</ins><span class="cx"> test17.step(function() {
</span><span class="cx">     var controller;
</span><span class="cx">     var rs = new ReadableStream({
</span><span class="lines">@@ -638,24 +678,35 @@
</span><span class="cx">     });
</span><span class="cx">     var reader = rs.getReader();
</span><span class="cx"> 
</span><del>-    assert_equals(controller.enqueue('a'), true, 'first enqueue should return true');
</del><ins>+    assert_equals(controller.desiredSize, 1, 'desiredSize should start at 1');
+    controller.enqueue('a');
+    assert_equals(controller.desiredSize, 0, 'desiredSize should decrease to 0 after first enqueue');
</ins><span class="cx"> 
</span><span class="cx">     reader.read().then(test17.step_func(function(result1) {
</span><span class="cx">         assert_object_equals(result1, { value: 'a', done: false }, 'first chunk read should be correct');
</span><del>-        assert_equals(controller.enqueue('b'), true, 'second enqueue should return true');
</del><span class="cx"> 
</span><ins>+        assert_equals(controller.desiredSize, 1, 'desiredSize should go up to 1 after the first read');
+        controller.enqueue('b');
+        assert_equals(controller.desiredSize, 0, 'desiredSize should go down to 0 after the second enqueue');
+
</ins><span class="cx">         return reader.read();
</span><span class="cx">     })).then(test17.step_func(function(result2) {
</span><del>-        assert_object_equals(result2, { value: 'b', done: false }, 'second chunk read should be correct');
-        assert_equals(controller.enqueue('c'), true, 'third enqueue should return true');
</del><ins>+            assert_object_equals(result2, { value: 'b', done: false }, 'second chunk read should be correct');
</ins><span class="cx"> 
</span><del>-        return reader.read();
</del><ins>+            assert_equals(controller.desiredSize, 1, 'desiredSize should go up to 1 after the second read');
+            controller.enqueue('c');
+            assert_equals(controller.desiredSize, 0, 'desiredSize should go down to 0 after the third enqueue');
+
+            return reader.read();
</ins><span class="cx">     })).then(test17.step_func(function(result3) {
</span><del>-        assert_object_equals(result3, { value: 'c', done: false }, 'third chunk read should be correct');
-        assert_equals(controller.enqueue('d'), true, 'fourth enqueue should return true');
</del><ins>+            assert_object_equals(result3, { value: 'c', done: false }, 'third chunk read should be correct');
</ins><span class="cx"> 
</span><del>-        test17.done();
-    })).catch(test17.step_func(function(e) { assert_unreached(e); } ));
</del><ins>+            assert_equals(controller.desiredSize, 1, 'desiredSize should go up to 1 after the third read');
+            controller.enqueue('d');
+            assert_equals(controller.desiredSize, 0, 'desiredSize should go down to 0 after the fourth enqueue');
+
+            test17.done();
+    })).catch(test17.step_func(function(e) { assert_unreached(e); }));
</ins><span class="cx"> });
</span><span class="cx"> 
</span><span class="cx"> var test18 = async_test('ReadableStream integration test: adapting a random push source');
</span><span class="lines">@@ -699,7 +750,7 @@
</span><span class="cx">         }
</span><span class="cx"> 
</span><span class="cx">         test18.done();
</span><del>-    }), test18.step_func(function(e) { assert_reached(e); }));
</del><ins>+    }), test18.step_func(function(e) { assert_unreached(e); }));
</ins><span class="cx"> });
</span><span class="cx"> 
</span><span class="cx"> var test19 = async_test('ReadableStream integration test: adapting a sync pull source');
</span><span class="lines">@@ -707,23 +758,22 @@
</span><span class="cx">     var rs = sequentialReadableStream(10);
</span><span class="cx"> 
</span><span class="cx">     readableStreamToArray(rs).then(test19.step_func(function(chunks) {
</span><del>-        assert_equals(rs.source.closed, true, 'source should be closed after all chunks are read');
</del><ins>+        assert_true(rs.source.closed, 'source should be closed after all chunks are read');
</ins><span class="cx">         assert_array_equals(chunks, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 'the expected 10 chunks should be read');
</span><span class="cx"> 
</span><span class="cx">         test19.done();
</span><span class="cx">     }));
</span><span class="cx"> });
</span><del>-/*
-var test20 = async_test('ReadableStream integration test: adapting an async pull source', { timeout: 50 });
-test20.step(function() {
-    var rs = sequentialReadableStream(10, { async: true });
</del><span class="cx"> 
</span><del>-    readableStreamToArray(rs).then(test20.step_func(function(chunks) {
-        assert_equals(rs.source.closed, true, 'source should be closed after all chunks are read');
-        assert_array_equals(chunks, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 'the expected 10 chunks should be read');
</del><ins>+// var test20 = async_test('ReadableStream integration test: adapting an async pull source');
+// test20.step(function() {
+//     var rs = sequentialReadableStream(10, { async: true });
</ins><span class="cx"> 
</span><del>-        test20.done();
-    }));
-});
-*/
</del><ins>+//     readableStreamToArray(rs).then(test20.step_func(function(chunks) {
+//         assert_true(rs.source.closed, 'source should be closed after all chunks are read');
+//         assert_array_equals(chunks, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], 'the expected 10 chunks should be read');
+
+//         test20.done();
+//     }));
+// });
</ins><span class="cx"> &lt;/script&gt;
</span></span></pre></div>
<a id="trunkLayoutTestsstreamsreferenceimplementationresourcesbytelengthqueuingstrategyjs"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/streams/reference-implementation/resources/byte-length-queuing-strategy.js (185585 => 185586)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/streams/reference-implementation/resources/byte-length-queuing-strategy.js        2015-06-16 07:40:09 UTC (rev 185585)
+++ trunk/LayoutTests/streams/reference-implementation/resources/byte-length-queuing-strategy.js        2015-06-16 08:19:04 UTC (rev 185586)
</span><span class="lines">@@ -1,38 +1,10 @@
</span><span class="cx"> // FIXME: Remove this file when implemented in WebCore.
</span><span class="cx"> 
</span><del>-function typeIsObject(x) {
-    return (typeof x === 'object' &amp;&amp; x !== null) || typeof x === 'function';
</del><ins>+function ByteLengthQueuingStrategy({ highWaterMark }) {
+    createDataProperty(this, 'highWaterMark', highWaterMark);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-function ByteLengthQueuingStrategy(obj) {
-    if (!typeIsObject(obj)) {
-      throw new TypeError('Parameter must be an object.');
-    }
-
-    highWaterMark = Number(obj.highWaterMark);
-
-    if (Number.isNaN(highWaterMark)) {
-      throw new TypeError('highWaterMark must be a number.');
-    }
-    if (highWaterMark &lt; 0) {
-      throw new RangeError('highWaterMark must be nonnegative.');
-    }
-
-    this._blqsHighWaterMark = highWaterMark;
-}
-
</del><span class="cx"> ByteLengthQueuingStrategy.prototype = {
</span><del>-    shouldApplyBackpressure: function(queueSize) {
-        if (!typeIsObject(this)) {
-            throw new TypeError('ByteLengthQueuingStrategy.prototype.shouldApplyBackpressure can only be applied to objects');
-        }
-        if (!Object.prototype.hasOwnProperty.call(this, '_blqsHighWaterMark')) {
-            throw new TypeError('ByteLengthQueuingStrategy.prototype.shouldApplyBackpressure can only be applied to a ' +
-                                'ByteLengthQueuingStrategy');
-        }
-
-        return queueSize &gt; this._blqsHighWaterMark;
-    },
</del><span class="cx">     size: function(chunk) {
</span><span class="cx">         return chunk.byteLength;
</span><span class="cx">     }
</span></span></pre></div>
<a id="trunkLayoutTestsstreamsreferenceimplementationresourcescountqueuingstrategyjs"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/streams/reference-implementation/resources/count-queuing-strategy.js (185585 => 185586)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/streams/reference-implementation/resources/count-queuing-strategy.js        2015-06-16 07:40:09 UTC (rev 185585)
+++ trunk/LayoutTests/streams/reference-implementation/resources/count-queuing-strategy.js        2015-06-16 08:19:04 UTC (rev 185586)
</span><span class="lines">@@ -1,38 +1,10 @@
</span><span class="cx"> // FIXME: Remove this file when implemented in WebCore.
</span><span class="cx"> 
</span><del>-function typeIsObject(x) {
-  return (typeof x === 'object' &amp;&amp; x !== null) || typeof x === 'function';
</del><ins>+function CountQueuingStrategy({ highWaterMark }) {
+    createDataProperty(this, 'highWaterMark', highWaterMark);
</ins><span class="cx"> }
</span><span class="cx"> 
</span><del>-function CountQueuingStrategy(obj) {
-    if (!typeIsObject(obj)) {
-      throw new TypeError('Parameter must be an object.');
-    }
-
-    highWaterMark = Number(obj.highWaterMark);
-
-    if (Number.isNaN(highWaterMark)) {
-      throw new TypeError('highWaterMark must be a number.');
-    }
-    if (highWaterMark &lt; 0) {
-      throw new RangeError('highWaterMark must be nonnegative.');
-    }
-
-    this._cqsHighWaterMark = highWaterMark;
-}
-
</del><span class="cx"> CountQueuingStrategy.prototype = {
</span><del>-    shouldApplyBackpressure: function(queueSize) {
-        if (!typeIsObject(this)) {
-            throw new TypeError('CountQueuingStrategy.prototype.shouldApplyBackpressure can only be applied to objects');
-        }
-        if (!Object.prototype.hasOwnProperty.call(this, '_cqsHighWaterMark')) {
-            throw new TypeError('CountQueuingStrategy.prototype.shouldApplyBackpressure can only be applied to a ' +
-                                'CountQueuingStrategy');
-        }
-
-        return queueSize &gt; this._cqsHighWaterMark;
-    },
</del><span class="cx">     size: function(chunk) {
</span><span class="cx">         return 1;
</span><span class="cx">     }
</span></span></pre></div>
<a id="trunkLayoutTestsstreamsreferenceimplementationresourcesstreamsutilsjs"></a>
<div class="modfile"><h4>Modified: trunk/LayoutTests/streams/reference-implementation/resources/streams-utils.js (185585 => 185586)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/LayoutTests/streams/reference-implementation/resources/streams-utils.js        2015-06-16 07:40:09 UTC (rev 185585)
+++ trunk/LayoutTests/streams/reference-implementation/resources/streams-utils.js        2015-06-16 08:19:04 UTC (rev 185586)
</span><span class="lines">@@ -1,5 +1,3 @@
</span><del>-var standardTimeout = 100;
-
</del><span class="cx"> function RandomPushSource(toPush) {
</span><span class="cx">     this.pushed = 0;
</span><span class="cx">     this.toPush = toPush;
</span><span class="lines">@@ -27,25 +25,24 @@
</span><span class="cx">             this.paused = false;
</span><span class="cx">         }
</span><span class="cx"> 
</span><del>-        var stream = this;
</del><ins>+        var source = this;
</ins><span class="cx">         function writeChunk() {
</span><del>-            if (stream.paused) {
</del><ins>+            if (source.paused) {
</ins><span class="cx">                 return;
</span><span class="cx">             }
</span><span class="cx"> 
</span><del>-            stream.pushed++;
</del><ins>+            source.pushed++;
</ins><span class="cx"> 
</span><del>-            if (stream.toPush &gt; 0 &amp;&amp; stream.pushed &gt; stream.toPush) {
-                if (stream._intervalHandle) {
-                    clearInterval(stream._intervalHandle);
-                    stream._intervalHandle = undefined;
</del><ins>+            if (source.toPush &gt; 0 &amp;&amp; source.pushed &gt; source.toPush) {
+                if (source._intervalHandle) {
+                    clearInterval(source._intervalHandle);
+                    source._intervalHandle = undefined;
</ins><span class="cx">                 }
</span><del>-                stream.closed = true;
-                stream.onend();
</del><ins>+                source.closed = true;
+                source.onend();
+            } else {
+                source.ondata(randomChunk(128));
</ins><span class="cx">             }
</span><del>-            else {
-                stream.ondata(randomChunk(128));
-            }
</del><span class="cx">         }
</span><span class="cx">     },
</span><span class="cx"> 
</span><span class="lines">@@ -150,7 +147,6 @@
</span><span class="cx">                 sequentialSource.open(function(err) {
</span><span class="cx">                     if (err) {
</span><span class="cx">                         reject(err);
</span><del>-                        return;
</del><span class="cx">                     }
</span><span class="cx">                     resolve();
</span><span class="cx">                 });
</span><span class="lines">@@ -158,20 +154,23 @@
</span><span class="cx">         },
</span><span class="cx"> 
</span><span class="cx">         pull: function(c) {
</span><del>-            sequentialSource.read(function(err, done, chunk) {
-                if (err) {
-                    c.error(err);
-                } else if (done) {
-                    sequentialSource.close(function(err) {
-                        if (err) {
-                            c.error(err);
-                            return;
-                        }
-                        c.close();
-                    });
-                } else {
-                    c.enqueue(chunk);
-                }
</del><ins>+            return new Promise(function(resolve, reject) {
+                sequentialSource.read(function(err, done, chunk) {
+                    if (err) {
+                        reject(err);
+                    } else if (done) {
+                        sequentialSource.close(function(err) {
+                            if (err) {
+                                reject(err);
+                            }
+                            c.close();
+                            resolve();
+                        });
+                    } else {
+                        c.enqueue(chunk);
+                        resolve();
+                    }
+                });
</ins><span class="cx">             });
</span><span class="cx">         },
</span><span class="cx">     });
</span><span class="lines">@@ -180,3 +179,15 @@
</span><span class="cx"> 
</span><span class="cx">     return stream;
</span><span class="cx"> };
</span><ins>+
+function typeIsObject(x) {
+    return (typeof x === 'object' &amp;&amp; x !== null) || typeof x === 'function';
+}
+
+function createDataProperty(o, p, v) {
+    if (!typeIsObject(o)) {
+        throw new TypeError('Parameter must be an object.');
+        return
+    }
+    Object.defineProperty(o, p, { value: v, writable: true, enumerable: true, configurable: true });
+}
</ins></span></pre>
</div>
</div>

</body>
</html>