Bug 993937 (part 2) - Update unit tests for http2 draft11. r=mcmanus
authorNicholas Hurley <hurley@todesschaf.org>
Tue, 29 Apr 2014 18:46:01 -0700
changeset 181286 7e0fe75355879100c4be21001a0682ec9ae62dce
parent 181285 1f052f973ee10b534adfe96bcb4020dfa3b2536a
child 181287 3125aa54ca3efa8015fcae12ffb5ead3db50d215
push id272
push userpvanderbeken@mozilla.com
push dateMon, 05 May 2014 16:31:18 +0000
reviewersmcmanus
bugs993937
milestone32.0a1
Bug 993937 (part 2) - Update unit tests for http2 draft11. r=mcmanus This updates our copy of node-http2 to the version that implements draft11, and has the one-line change to make the xpcshell test work.
netwerk/test/unit/test_http2.js
testing/xpcshell/node-http2/.gitignore
testing/xpcshell/node-http2/HISTORY.md
testing/xpcshell/node-http2/README.md
testing/xpcshell/node-http2/lib/http.js
testing/xpcshell/node-http2/lib/index.js
testing/xpcshell/node-http2/node_modules/http2-protocol/.gitignore
testing/xpcshell/node-http2/node_modules/http2-protocol/HISTORY.md
testing/xpcshell/node-http2/node_modules/http2-protocol/README.md
testing/xpcshell/node-http2/node_modules/http2-protocol/lib/compressor.js
testing/xpcshell/node-http2/node_modules/http2-protocol/lib/connection.js
testing/xpcshell/node-http2/node_modules/http2-protocol/lib/flow.js
testing/xpcshell/node-http2/node_modules/http2-protocol/lib/framer.js
testing/xpcshell/node-http2/node_modules/http2-protocol/lib/index.js
testing/xpcshell/node-http2/node_modules/http2-protocol/lib/stream.js
testing/xpcshell/node-http2/node_modules/http2-protocol/package.json
testing/xpcshell/node-http2/node_modules/http2-protocol/test/compressor.js
testing/xpcshell/node-http2/node_modules/http2-protocol/test/framer.js
testing/xpcshell/node-http2/node_modules/http2-protocol/test/stream.js
testing/xpcshell/node-http2/package.json
--- a/netwerk/test/unit/test_http2.js
+++ b/netwerk/test/unit/test_http2.js
@@ -20,17 +20,17 @@ posts.push(generateContent(250000));
 var md5s = ['f1b708bba17f1ce948dc979f4d7092bc',
             '2ef8d3b6c8f329318eb1a119b12622b6'];
 
 var bigListenerData = generateContent(128 * 1024);
 var bigListenerMD5 = '8f607cfdd2c87d6a7eedb657dafbd836';
 
 function checkIsHttp2(request) {
   try {
-    if (request.getResponseHeader("X-Firefox-Spdy") == "h2-10") {
+    if (request.getResponseHeader("X-Firefox-Spdy") == "h2-11") {
       if (request.getResponseHeader("X-Connection-Http2") == "yes") {
         return true;
       }
       return false; // Weird case, but the server disagrees with us
     }
   } catch (e) {
     // Nothing to do here
   }
new file mode 100644
--- /dev/null
+++ b/testing/xpcshell/node-http2/.gitignore
@@ -0,0 +1,4 @@
+node_modules
+.idea
+coverage
+doc
--- a/testing/xpcshell/node-http2/HISTORY.md
+++ b/testing/xpcshell/node-http2/HISTORY.md
@@ -1,12 +1,18 @@
 Version history
 ===============
 
-### 2.3.0 (2014-03-10) ###
+### 2.4.0 (2014-04-16) ###
+
+* Upgrade to the latest draft: [draft-ietf-httpbis-http2-11]
+
+[draft-ietf-httpbis-http2-11]: http://tools.ietf.org/html/draft-ietf-httpbis-http2-11
+
+### 2.3.0 (2014-03-12) ###
 
 * Upgrade to the latest draft: [draft-ietf-httpbis-http2-10]
 
 [draft-ietf-httpbis-http2-10]: http://tools.ietf.org/html/draft-ietf-httpbis-http2-10
 
 ### 2.2.0 (2013-12-25) ###
 
 * Upgrade to the latest draft: [draft-ietf-httpbis-http2-09]
--- a/testing/xpcshell/node-http2/README.md
+++ b/testing/xpcshell/node-http2/README.md
@@ -1,12 +1,12 @@
 node-http2
 ==========
 
-An HTTP/2 ([draft-ietf-httpbis-http2-10](http://tools.ietf.org/html/draft-ietf-httpbis-http2-10))
+An HTTP/2 ([draft-ietf-httpbis-http2-11](http://tools.ietf.org/html/draft-ietf-httpbis-http2-11))
 client and server implementation for node.js.
 
 Installation
 ------------
 
 ```
 npm install http2
 ```
@@ -109,22 +109,22 @@ The developer documentation is generated
 ### Running the tests ###
 
 It's easy, just run `npm test`. The tests are written in BDD style, so they are a good starting
 point to understand the code.
 
 ### Test coverage ###
 
 To generate a code coverage report, run `npm test --coverage` (which runs very slowly, be patient).
-Code coverage summary as of version 1.0.1:
+Code coverage summary as of version 2.3.0:
 ```
-Statements   : 93.26% ( 1563/1676 )
-Branches     : 84.85% ( 605/713 )
-Functions    : 94.81% ( 201/212 )
-Lines        : 93.23% ( 1557/1670 )
+Statements   : 94% ( 392/417 )
+Branches     : 80.63% ( 129/160 )
+Functions    : 93.65% ( 59/63 )
+Lines        : 94% ( 392/417 )
 ```
 
 There's a hosted version of the detailed (line-by-line) coverage report
 [here](http://molnarg.github.io/node-http2/coverage/lcov-report/lib/).
 
 ### Logging ###
 
 Logging is turned off by default. You can turn it on by passing a bunyan logger as `log` option when
@@ -148,16 +148,17 @@ Running the example server and client wi
 
 Contributors
 ------------
 
 Code contributions are always welcome! People who contributed to node-http2 so far:
 
 * Nick Hurley
 * Mike Belshe
+* Yoshihiro Iwanaga
 
 Special thanks to Google for financing the development of this module as part of their [Summer of
 Code program](https://developers.google.com/open-source/soc/) (project: [HTTP/2 prototype server
 implementation](https://google-melange.appspot.com/gsoc/project/google/gsoc2013/molnarg/5001)), and
 Nick Hurley of Mozilla, my GSoC mentor, who helped with regular code review and technical advices.
 
 License
 -------
--- a/testing/xpcshell/node-http2/lib/http.js
+++ b/testing/xpcshell/node-http2/lib/http.js
@@ -116,17 +116,17 @@
 //   - **request.setSocketKeepAlive([enable], [initialDelay])**
 //
 // - **Class: http2.IncomingMessage**
 //   - **Event: 'close'**
 //   - **message.setTimeout(timeout, [callback])**
 //
 // [1]: http://nodejs.org/api/https.html
 // [2]: http://nodejs.org/api/http.html
-// [3]: http://tools.ietf.org/html/draft-ietf-httpbis-http2-10#section-8.1.3.2
+// [3]: http://tools.ietf.org/html/draft-ietf-httpbis-http2-11#section-8.1.3.2
 // [expect-continue]: https://github.com/http2/http2-spec/issues/18
 // [connect]: https://github.com/http2/http2-spec/issues/230
 
 // Common server and client side code
 // ==================================
 
 var net = require('net');
 var url = require('url');
@@ -199,33 +199,23 @@ function IncomingMessage(stream) {
   this._lastHeadersSeen = undefined;
 
   // * Other metadata is filled in when the headers arrive.
   stream.once('headers', this._onHeaders.bind(this));
   stream.once('end', this._onEnd.bind(this));
 }
 IncomingMessage.prototype = Object.create(PassThrough.prototype, { constructor: { value: IncomingMessage } });
 
-// [Request Header Fields](http://tools.ietf.org/html/draft-ietf-httpbis-http2-10#section-8.1.3.1)
+// [Request Header Fields](http://tools.ietf.org/html/draft-ietf-httpbis-http2-11#section-8.1.3.1)
 // * `headers` argument: HTTP/2.0 request and response header fields carry information as a series
 //   of key-value pairs. This includes the target URI for the request, the status code for the
 //   response, as well as HTTP header fields.
 IncomingMessage.prototype._onHeaders = function _onHeaders(headers) {
-  // * An HTTP/2.0 request or response MUST NOT include any of the following header fields:
-  //   Connection, Host, Keep-Alive, Proxy-Connection, TE, Transfer-Encoding, and Upgrade. A server
-  //   MUST treat the presence of any of these header fields as a stream error of type
-  //   PROTOCOL_ERROR.
-  for (var i = 0; i < deprecatedHeaders.length; i++) {
-    var key = deprecatedHeaders[i];
-    if (key in headers) {
-      this._log.error({ key: key, value: headers[key] }, 'Deprecated header found');
-      this.stream.emit('error', 'PROTOCOL_ERROR');
-      return;
-    }
-  }
+  // * Detects malformed headers
+  this._validateHeaders(headers);
 
   // * Store the _regular_ headers in `this.headers`
   for (var name in headers) {
     if (name[0] !== ':') {
       this.headers[name] = headers[name];
     }
   }
 
@@ -240,22 +230,51 @@ IncomingMessage.prototype._onEnd = funct
   this.trailers = this._lastHeadersSeen;
 };
 
 IncomingMessage.prototype.setTimeout = noop;
 
 IncomingMessage.prototype._checkSpecialHeader = function _checkSpecialHeader(key, value) {
   if ((typeof value !== 'string') || (value.length === 0)) {
     this._log.error({ key: key, value: value }, 'Invalid or missing special header field');
-    this.stream.emit('error', 'PROTOCOL_ERROR');
+    this.stream.reset('PROTOCOL_ERROR');
   }
 
   return value;
-}
-;
+};
+
+IncomingMessage.prototype._validateHeaders = function _validateHeaders(headers) {
+  // * An HTTP/2.0 request or response MUST NOT include any of the following header fields:
+  //   Connection, Host, Keep-Alive, Proxy-Connection, TE, Transfer-Encoding, and Upgrade. A server
+  //   MUST treat the presence of any of these header fields as a stream error of type
+  //   PROTOCOL_ERROR.
+  for (var i = 0; i < deprecatedHeaders.length; i++) {
+    var key = deprecatedHeaders[i];
+    if (key in headers) {
+      this._log.error({ key: key, value: headers[key] }, 'Deprecated header found');
+      this.stream.reset('PROTOCOL_ERROR');
+      return;
+    }
+  }
+
+  for (var headerName in headers) {
+    // * Empty header name field is malformed
+    if (headerName.length <= 1) {
+      this.stream.reset('PROTOCOL_ERROR');
+      return;
+    }
+    // * A request or response containing uppercase header name field names MUST be
+    //   treated as malformed (Section 8.1.3.5). Implementations that detect malformed
+    //   requests or responses need to ensure that the stream ends.
+    if(/[A-Z]/.test(headerName)) {
+      this.stream.reset('PROTOCOL_ERROR');
+      return;
+    }
+  }
+};
 
 // OutgoingMessage class
 // ---------------------
 
 function OutgoingMessage() {
   // * This is basically a read-only wrapper for the [Stream](stream.html) class.
   Writable.call(this);
 
@@ -492,17 +511,17 @@ function createServer(options, requestLi
 // IncomingRequest class
 // ---------------------
 
 function IncomingRequest(stream) {
   IncomingMessage.call(this, stream);
 }
 IncomingRequest.prototype = Object.create(IncomingMessage.prototype, { constructor: { value: IncomingRequest } });
 
-// [Request Header Fields](http://tools.ietf.org/html/draft-ietf-httpbis-http2-10#section-8.1.3.1)
+// [Request Header Fields](http://tools.ietf.org/html/draft-ietf-httpbis-http2-11#section-8.1.3.1)
 // * `headers` argument: HTTP/2.0 request and response header fields carry information as a series
 //   of key-value pairs. This includes the target URI for the request, the status code for the
 //   response, as well as HTTP header fields.
 IncomingRequest.prototype._onHeaders = function _onHeaders(headers) {
   // * The ":method" header field includes the HTTP method
   // * The ":scheme" header field includes the scheme portion of the target URI
   // * The ":authority" header field includes the authority portion of the target URI
   // * The ":path" header field includes the path and query parts of the target URI.
@@ -923,17 +942,17 @@ OutgoingRequest.prototype._onPromise = f
 // IncomingResponse class
 // ----------------------
 
 function IncomingResponse(stream) {
   IncomingMessage.call(this, stream);
 }
 IncomingResponse.prototype = Object.create(IncomingMessage.prototype, { constructor: { value: IncomingResponse } });
 
-// [Response Header Fields](http://tools.ietf.org/html/draft-ietf-httpbis-http2-10#section-8.1.3.2)
+// [Response Header Fields](http://tools.ietf.org/html/draft-ietf-httpbis-http2-11#section-8.1.3.2)
 // * `headers` argument: HTTP/2.0 request and response header fields carry information as a series
 //   of key-value pairs. This includes the target URI for the request, the status code for the
 //   response, as well as HTTP header fields.
 IncomingResponse.prototype._onHeaders = function _onHeaders(headers) {
   // * A single ":status" header field is defined that carries the HTTP status code field. This
   //   header field MUST be included in all responses.
   // * A client MUST treat the absence of the ":status" header field, the presence of multiple
   //   values, or an invalid value as a stream error of type PROTOCOL_ERROR.
--- a/testing/xpcshell/node-http2/lib/index.js
+++ b/testing/xpcshell/node-http2/lib/index.js
@@ -1,22 +1,22 @@
-// [node-http2][homepage] is an [HTTP/2 (draft 10)][http2] implementation for [node.js][node].
+// [node-http2][homepage] is an [HTTP/2 (draft 11)][http2] implementation for [node.js][node].
 //
 // The core of the protocol is implemented by the [http2-protocol] module. This module provides
 // two important features on top of http2-protocol:
 //
 // * Implementation of different negotiation schemes that can be used to start a HTTP2 connection.
 //   These include TLS ALPN, Upgrade and Plain TCP.
 //
 // * Providing an API very similar to the standard node.js [HTTPS module API][node-https]
 //   (which is in turn very similar to the [HTTP module API][node-http]).
 //
 // [homepage]:            https://github.com/molnarg/node-http2
 // [http2-protocol]:      https://github.com/molnarg/node-http2-protocol
-// [http2]:               http://tools.ietf.org/html/draft-ietf-httpbis-http2-10
+// [http2]:               http://tools.ietf.org/html/draft-ietf-httpbis-http2-11
 // [node]:                http://nodejs.org/
 // [node-https]:          http://nodejs.org/api/https.html
 // [node-http]:           http://nodejs.org/api/http.html
 
 module.exports   = require('./http');
 
 /*
                   HTTP API
--- a/testing/xpcshell/node-http2/node_modules/http2-protocol/.gitignore
+++ b/testing/xpcshell/node-http2/node_modules/http2-protocol/.gitignore
@@ -1,1 +1,5 @@
 node_modules
+.idea
+coverage
+doc
+npm-debug.log
--- a/testing/xpcshell/node-http2/node_modules/http2-protocol/HISTORY.md
+++ b/testing/xpcshell/node-http2/node_modules/http2-protocol/HISTORY.md
@@ -1,12 +1,18 @@
 Version history
 ===============
 
-### 0.10.0 (2014-03-10) ###
+### 0.11.0 (2014-04-16) ###
+
+* Upgrade to the latest draft: [draft-ietf-httpbis-http2-11][draft-11]
+
+[draft-11]: http://tools.ietf.org/html/draft-ietf-httpbis-http2-11
+
+### 0.10.0 (2014-03-12) ###
 
 * Upgrade to the latest draft: [draft-ietf-httpbis-http2-10][draft-10]
 
 [draft-10]: http://tools.ietf.org/html/draft-ietf-httpbis-http2-10
 
 ### 0.9.1 (2014-01-11) ###
 
 * Updated the examples (#5)
--- a/testing/xpcshell/node-http2/node_modules/http2-protocol/README.md
+++ b/testing/xpcshell/node-http2/node_modules/http2-protocol/README.md
@@ -1,12 +1,12 @@
 node-http2-protocol
 ===================
 
-An HTTP/2 ([draft-ietf-httpbis-http2-10](http://tools.ietf.org/html/draft-ietf-httpbis-http2-10))
+An HTTP/2 ([draft-ietf-httpbis-http2-11](http://tools.ietf.org/html/draft-ietf-httpbis-http2-11))
 framing layer implementaion for node.js.
 
 Installation
 ------------
 
 ```
 npm install http2-protocol
 ```
@@ -47,34 +47,35 @@ just run `npm run-script doc`.
 It's easy, just run `npm test`. The tests are written in BDD style, so they are a good starting
 point to understand the code.
 
 ### Test coverage ###
 
 To generate a code coverage report, run `npm test --coverage` (it may be slow, be patient).
 Code coverage summary as of version 0.9.0:
 ```
-Statements   : 92.43% ( 1257/1360 )
-Branches     : 86.36% ( 500/579 )
-Functions    : 90.12% ( 146/162 )
-Lines        : 92.39% ( 1251/1354 )
+Statements   : 91.86% ( 1276/1389 )
+Branches     : 85.62% ( 524/612 )
+Functions    : 92.31% ( 144/156 )
+Lines        : 91.83% ( 1270/1383 )
 ```
 
 There's a hosted version of the detailed (line-by-line) coverage report
 [here](http://molnarg.github.io/node-http2-protocol/coverage/lcov-report/lib/).
 
 ### Logging ###
 
 Contributors
 ------------
 
 Code contributions are always welcome! People who contributed to node-http2 so far:
 
 * Nick Hurley
 * Mike Belshe
+* vsemogutor
 
 Special thanks to Google for financing the development of this module as part of their [Summer of
 Code program](https://developers.google.com/open-source/soc/) (project: [HTTP/2 prototype server
 implementation](https://google-melange.appspot.com/gsoc/project/google/gsoc2013/molnarg/5001)), and
 Nick Hurley of Mozilla, my GSoC mentor, who helped with regular code review and technical advices.
 
 License
 -------
--- a/testing/xpcshell/node-http2/node_modules/http2-protocol/lib/compressor.js
+++ b/testing/xpcshell/node-http2/node_modules/http2-protocol/lib/compressor.js
@@ -8,17 +8,17 @@
 //
 // The 'integration' part is also implemented by two [Transform Stream][node-transform] subclasses
 // that operate in [object mode][node-objectmode]: the `Compressor` and the `Decompressor`. These
 // provide a layer between the [framer](framer.html) and the
 // [connection handling component](connection.html).
 //
 // [node-transform]: http://nodejs.org/api/stream.html#stream_class_stream_transform
 // [node-objectmode]: http://nodejs.org/api/stream.html#stream_new_stream_readable_options
-// [http2-compression]: http://tools.ietf.org/html/draft-ietf-httpbis-header-compression-05
+// [http2-compression]: http://tools.ietf.org/html/draft-ietf-httpbis-header-compression-07
 
 exports.HeaderTable = HeaderTable;
 exports.HuffmanTable = HuffmanTable;
 exports.HeaderSetCompressor = HeaderSetCompressor;
 exports.HeaderSetDecompressor = HeaderSetDecompressor;
 exports.Compressor = Compressor;
 exports.Decompressor = Decompressor;
 
@@ -30,18 +30,18 @@ var util = require('util');
 // ==================
 
 // The HeaderTable class
 // ---------------------
 
 // The [Header Table] is a component used to associate headers to index values. It is basically an
 // ordered list of `[name, value]` pairs, so it's implemented as a subclass of `Array`.
 // In this implementation, the Header Table and the [Static Table] are handled as a single table.
-// [Header Table]: http://tools.ietf.org/html/draft-ietf-httpbis-header-compression-05#section-3.1.2
-// [Static Table]: http://tools.ietf.org/html/draft-ietf-httpbis-header-compression-05#appendix-B
+// [Header Table]: http://tools.ietf.org/html/draft-ietf-httpbis-header-compression-07#section-3.1.2
+// [Static Table]: http://tools.ietf.org/html/draft-ietf-httpbis-header-compression-07#appendix-B
 function HeaderTable(log, limit) {
   var self = HeaderTable.staticTable.map(entryFromPair);
   self._log = log;
   self._limit = limit || DEFAULT_HEADER_TABLE_LIMIT;
   self._staticLength = self.length;
   self._size = 0;
   self._enforceLimit = HeaderTable.prototype._enforceLimit;
   self.add = HeaderTable.prototype.add;
@@ -54,17 +54,17 @@ function HeaderTable(log, limit) {
 //
 // * [Reference Set][referenceset]: contains a group of headers used as a reference for the
 //   differential encoding of a new set of headers. (`reference` flag)
 // * Emitted headers: the headers that are already emitted as part of the current decompression
 //   process (not part of the spec, `emitted` flag)
 // * Headers to be kept: headers that should not be removed as the last step of the encoding process
 //   (not part of the spec, `keep` flag)
 //
-// [referenceset]: http://tools.ietf.org/html/draft-ietf-httpbis-header-compression-05#section-3.1.3
+// [referenceset]: http://tools.ietf.org/html/draft-ietf-httpbis-header-compression-07#section-3.1.3
 //
 // Relations of the sets:
 //
 //     ,----------------------------------.
 //     |           Header Table           |
 //     |                                  |
 //     |  ,----------------------------.  |
 //     |  |        Reference Set       |  |
@@ -94,17 +94,17 @@ function entryFromPair(pair) {
 // * The size of a header table is the sum of the size of its entries.
 var DEFAULT_HEADER_TABLE_LIMIT = 4096;
 
 function size(entry) {
   return (new Buffer(entry[0] + entry[1], 'utf8')).length + 32;
 }
 
 // The `add(index, entry)` can be used to [manage the header table][tablemgmt]:
-// [tablemgmt]: http://tools.ietf.org/html/draft-ietf-httpbis-header-compression-05#section-3.3
+// [tablemgmt]: http://tools.ietf.org/html/draft-ietf-httpbis-header-compression-07#section-3.3
 //
 // * it pushes the new `entry` at the beggining of the table
 // * before doing such a modification, it has to be ensured that the header table size will stay
 //   lower than or equal to the header table size limit. To achieve this, entries are evicted from
 //   the end of the header table until the size of the header table is less than or equal to
 //   `(this._limit - entry.size)`, or until the table is empty.
 //
 //              <----------  Index Address Space ---------->
@@ -141,38 +141,39 @@ HeaderTable.prototype.add = function(ent
 };
 
 // The table size limit can be changed externally. In this case, the same eviction algorithm is used
 HeaderTable.prototype.setSizeLimit = function setSizeLimit(limit) {
   this._limit = limit;
   this._enforceLimit(this._limit);
 };
 
-// [The Static Table](http://tools.ietf.org/html/draft-ietf-httpbis-header-compression-05#appendix-B)
+// [The Static Table](http://tools.ietf.org/html/draft-ietf-httpbis-header-compression-07#appendix-B)
 // ------------------
-// [statictable]:http://tools.ietf.org/html/draft-ietf-httpbis-header-compression-05#appendix-B
+// [statictable]:http://tools.ietf.org/html/draft-ietf-httpbis-header-compression-07#appendix-B
 
 // The table is generated with feeding the table from the spec to the following sed command:
 //
 //     sed -re "s/\s*\| [0-9]+\s*\| ([^ ]*)/  [ '\1'/g" -e "s/\|\s([^ ]*)/, '\1'/g" -e 's/ \|/],/g'
 
 HeaderTable.staticTable  = [
   [ ':authority'                  , ''            ],
   [ ':method'                     , 'GET'         ],
   [ ':method'                     , 'POST'        ],
   [ ':path'                       , '/'           ],
   [ ':path'                       , '/index.html' ],
   [ ':scheme'                     , 'http'        ],
   [ ':scheme'                     , 'https'       ],
   [ ':status'                     , '200'         ],
-  [ ':status'                     , '500'         ],
+  [ ':status'                     , '204'         ],
+  [ ':status'                     , '206'         ],
+  [ ':status'                     , '304'         ],
+  [ ':status'                     , '400'         ],
   [ ':status'                     , '404'         ],
-  [ ':status'                     , '403'         ],
-  [ ':status'                     , '400'         ],
-  [ ':status'                     , '401'         ],
+  [ ':status'                     , '500'         ],
   [ 'accept-charset'              , ''            ],
   [ 'accept-encoding'             , ''            ],
   [ 'accept-language'             , ''            ],
   [ 'accept-ranges'               , ''            ],
   [ 'accept'                      , ''            ],
   [ 'access-control-allow-origin' , ''            ],
   [ 'age'                         , ''            ],
   [ 'allow'                       , ''            ],
@@ -240,17 +241,17 @@ function HeaderSetDecompressor(log, tabl
 // TransformStream class. It collects the data chunks for later processing.
 // [_transform]: http://nodejs.org/api/stream.html#stream_transform_transform_chunk_encoding_callback
 HeaderSetDecompressor.prototype._transform = function _transform(chunk, encoding, callback) {
   this._chunks.push(chunk);
   callback();
 };
 
 // `execute(rep)` executes the given [header representation][representation].
-// [representation]: http://tools.ietf.org/html/draft-ietf-httpbis-header-compression-05#section-3.1.4
+// [representation]: http://tools.ietf.org/html/draft-ietf-httpbis-header-compression-07#section-3.1.4
 
 // The *JavaScript object representation* of a header representation:
 //
 //     {
 //       name: String || Integer,  // string literal or index
 //       value: String || Integer, // string literal or index
 //       index: Boolean            // with or without indexing
 //     }
@@ -267,49 +268,44 @@ HeaderSetDecompressor.prototype._transfo
 //     { name: 2  , value: 'Y', index: true  } // with indexing
 //     { name: 'A', value: 'Z', index: true  } // with indexing, literal name
 HeaderSetDecompressor.prototype._execute = function _execute(rep) {
   this._log.trace({ key: rep.name, value: rep.value, index: rep.index },
                   'Executing header representation');
 
   var entry, pair;
 
-  // * An _indexed representation_ with an index value of 0 (in our representation, it means -1)
-  //   entails the following actions:
-  //   * If the following byte starts with a set bit, the reference set is emptied.
-  //   * Else, reduce the size of the header table to the value encoded with a 7-bit prefix
+  if (rep.contextUpdate) {
+    if (rep.clearReferenceSet) {
+      for (var i = 0; i < this._table.length; i++) {
+        this._table[i].reference = false;
+      }
+    } else {
+      this.setTableSizeLimit(rep.newMaxSize);
+    }
+  }
+
   // * An _indexed representation_ corresponding to an entry _present_ in the reference set
   //   entails the following actions:
   //   * The entry is removed from the reference set.
   // * An _indexed representation_ corresponding to an entry _not present_ in the reference set
   //   entails the following actions:
   //   * If referencing an element of the static table:
   //     * The header field corresponding to the referenced entry is emitted
   //     * The referenced static entry is added to the header table
   //     * A reference to this new header table entry is added to the reference set (except if
   //       this new entry didn't fit in the header table)
   //   * If referencing an element of the header table:
   //     * The header field corresponding to the referenced entry is emitted
   //     * The referenced header table entry is added to the reference set
-  if (typeof rep.value === 'number') {
+  else if (typeof rep.value === 'number') {
     var index = rep.value;
     entry = this._table[index];
 
-    if (index == -1) {
-      if (rep.index) {
-        for (var i = 0; i < this._table.length; i++) {
-          this._table[i].reference = false;
-        }
-      } else {
-        // Set a new maximum size
-        this.setTableSizeLimit(rep.name);
-      }
-    }
-
-    else if (entry.reference) {
+    if (entry.reference) {
       entry.reference = false;
     }
 
     else {
       pair = entry.slice();
       this.push(pair);
 
       if (index >= this._table.length - this._table._staticLength) {
@@ -355,17 +351,17 @@ HeaderSetDecompressor.prototype._flush =
   var buffer = concat(this._chunks);
 
   // * processes the header representations
   buffer.cursor = 0;
   while (buffer.cursor < buffer.length) {
     this._execute(HeaderSetDecompressor.header(buffer));
   }
 
-  // * [emits the reference set](http://tools.ietf.org/html/draft-ietf-httpbis-header-compression-05#section-3.2.2)
+  // * [emits the reference set](http://tools.ietf.org/html/draft-ietf-httpbis-header-compression-07#section-3.2.2)
   for (var index = 0; index < this._table.length; index++) {
     var entry = this._table[index];
     if (entry.reference && !entry.emitted) {
       this.push(entry.slice());
     }
     entry.emitted = false;
   }
 
@@ -420,16 +416,18 @@ HeaderSetCompressor.prototype._transform
         fullMatch = droppedIndex;
         break;
       } else if (nameMatch === -1) {
         nameMatch = droppedIndex;
       }
     }
   }
 
+  var mustNeverIndex = (name === 'cookie' || name === 'set-cookie' || name === 'authorization');
+
   // * if there's full match, it will be an indexed representation (or more than one) depending
   //   on its presence in the reference, the emitted and the keep set:
   //
   //   * If the entry is outside the reference set, then a single indexed representation puts the
   //     entry into it and emits the header. Note that if the matched entry is in the static table,
   //     then it has to be added to the header table.
   //
   //   * If it's already in the keep set, then 4 indexed representations are needed:
@@ -444,17 +442,17 @@ HeaderSetCompressor.prototype._transform
   //   * If it's in the emitted set, then 2 indexed representations are needed:
   //
   //     1. removes it from the reference set
   //     2. puts it back in the reference set and emits the header once
   //
   //   * If it's in the reference set, but outside the keep set and the emitted set, then this
   //     header is common with the previous header set, and is still untouched. We mark it to keep
   //     in the reference set (that means don't remove at the end of the encoding process).
-  if (fullMatch !== -1) {
+  if (fullMatch !== -1 && !mustNeverIndex) {
     rep = { name: fullMatch, value: fullMatch, index: false };
 
     if (!entry.reference) {
       if (fullMatch >= this._table.length - this._table._staticLength) {
         entry = entryFromPair(pair);
         this._table.add(entry);
       }
       this.send(rep);
@@ -481,33 +479,33 @@ HeaderSetCompressor.prototype._transform
     }
   }
 
   // * otherwise, it will be a literal representation (with a name index if there's a name match)
   else {
     entry = entryFromPair(pair);
     entry.emitted = true;
 
-    var indexing = (entry._size < this._table._limit / 2);
+    var indexing = (entry._size < this._table._limit / 2) && !mustNeverIndex;
 
     if (indexing) {
       entry.reference = true;
       var droppedEntries = this._table.add(entry);
       for (droppedIndex in droppedEntries) {
         droppedIndex = Number(droppedIndex)
         var dropped = droppedEntries[droppedIndex];
         if (dropped.keep) {
           rep = { name: droppedIndex, value: droppedIndex, index: false };
           this.send(rep);
           this.send(rep);
         }
       }
     }
 
-    this.send({ name: (nameMatch !== -1) ? nameMatch : name, value: value, index: indexing });
+    this.send({ name: (nameMatch !== -1) ? nameMatch : name, value: value, index: indexing, mustNeverIndex: mustNeverIndex, contextUpdate: false });
   }
 
   callback();
 };
 
 // `_flush` is the implementation of the [corresponding virtual function][_flush] of the
 // TransformStream class. It gets called when there's no more header to compress. The final step:
 // [_flush]: http://nodejs.org/api/stream.html#stream_transform_flush_callback
@@ -521,17 +519,17 @@ HeaderSetCompressor.prototype._flush = f
     }
     entry.keep = false;
     entry.emitted = false;
   }
 
   callback();
 };
 
-// [Detailed Format](http://tools.ietf.org/html/draft-ietf-httpbis-header-compression-05#section-4)
+// [Detailed Format](http://tools.ietf.org/html/draft-ietf-httpbis-header-compression-07#section-4)
 // -----------------
 
 // ### Integer representation ###
 //
 // The algorithm to represent an integer I is as follows:
 //
 // 1. If I < 2^N - 1, encode I on N bits
 // 2. Else, encode 2^N - 1 on N bits and do the following steps:
@@ -705,238 +703,16 @@ HuffmanTable.prototype.decode = function
 }
 
 // The initializer arrays for the Huffman tables are generated with feeding the tables from the
 // spec to this sed command:
 //
 //     sed -e "s/^.* [|]//g" -e "s/|//g" -e "s/ .*//g" -e "s/^/  '/g" -e "s/$/',/g"
 
 HuffmanTable.huffmanTable = new HuffmanTable([
-  '111111111111111111110111010',
-  '111111111111111111110111011',
-  '111111111111111111110111100',
-  '111111111111111111110111101',
-  '111111111111111111110111110',
-  '111111111111111111110111111',
-  '111111111111111111111000000',
-  '111111111111111111111000001',
-  '111111111111111111111000010',
-  '111111111111111111111000011',
-  '111111111111111111111000100',
-  '111111111111111111111000101',
-  '111111111111111111111000110',
-  '111111111111111111111000111',
-  '111111111111111111111001000',
-  '111111111111111111111001001',
-  '111111111111111111111001010',
-  '111111111111111111111001011',
-  '111111111111111111111001100',
-  '111111111111111111111001101',
-  '111111111111111111111001110',
-  '111111111111111111111001111',
-  '111111111111111111111010000',
-  '111111111111111111111010001',
-  '111111111111111111111010010',
-  '111111111111111111111010011',
-  '111111111111111111111010100',
-  '111111111111111111111010101',
-  '111111111111111111111010110',
-  '111111111111111111111010111',
-  '111111111111111111111011000',
-  '111111111111111111111011001',
-  '11101000',
-  '111111111100',
-  '11111111111010',
-  '111111111111100',
-  '111111111111101',
-  '100100',
-  '1101110',
-  '111111111111110',
-  '11111111010',
-  '11111111011',
-  '1111111010',
-  '11111111100',
-  '11101001',
-  '100101',
-  '00100',
-  '0000',
-  '00101',
-  '00110',
-  '00111',
-  '100110',
-  '100111',
-  '101000',
-  '101001',
-  '101010',
-  '101011',
-  '101100',
-  '111101100',
-  '11101010',
-  '111111111111111110',
-  '101101',
-  '11111111111111100',
-  '111101101',
-  '11111111111011',
-  '1101111',
-  '11101011',
-  '11101100',
-  '11101101',
-  '11101110',
-  '1110000',
-  '111101110',
-  '111101111',
-  '111110000',
-  '111110001',
-  '1111111011',
-  '111110010',
-  '11101111',
-  '111110011',
-  '111110100',
-  '111110101',
-  '111110110',
-  '111110111',
-  '11110000',
-  '11110001',
-  '111111000',
-  '111111001',
-  '111111010',
-  '111111011',
-  '111111100',
-  '1111111100',
-  '11111111111100',
-  '111111111111111111111011010',
-  '1111111111100',
-  '11111111111101',
-  '101110',
-  '1111111111111111110',
-  '01000',
-  '101111',
-  '01001',
-  '110000',
-  '0001',
-  '110001',
-  '110010',
-  '110011',
-  '01010',
-  '1110001',
-  '1110010',
-  '01011',
-  '110100',
-  '01100',
-  '01101',
-  '01110',
-  '11110010',
-  '01111',
-  '10000',
-  '10001',
-  '110101',
-  '1110011',
-  '110110',
-  '11110011',
-  '11110100',
-  '11110101',
-  '11111111111111101',
-  '11111111101',
-  '11111111111111110',
-  '111111111101',
-  '111111111111111111111011011',
-  '111111111111111111111011100',
-  '111111111111111111111011101',
-  '111111111111111111111011110',
-  '111111111111111111111011111',
-  '111111111111111111111100000',
-  '111111111111111111111100001',
-  '111111111111111111111100010',
-  '111111111111111111111100011',
-  '111111111111111111111100100',
-  '111111111111111111111100101',
-  '111111111111111111111100110',
-  '111111111111111111111100111',
-  '111111111111111111111101000',
-  '111111111111111111111101001',
-  '111111111111111111111101010',
-  '111111111111111111111101011',
-  '111111111111111111111101100',
-  '111111111111111111111101101',
-  '111111111111111111111101110',
-  '111111111111111111111101111',
-  '111111111111111111111110000',
-  '111111111111111111111110001',
-  '111111111111111111111110010',
-  '111111111111111111111110011',
-  '111111111111111111111110100',
-  '111111111111111111111110101',
-  '111111111111111111111110110',
-  '111111111111111111111110111',
-  '111111111111111111111111000',
-  '111111111111111111111111001',
-  '111111111111111111111111010',
-  '111111111111111111111111011',
-  '111111111111111111111111100',
-  '111111111111111111111111101',
-  '111111111111111111111111110',
-  '111111111111111111111111111',
-  '11111111111111111110000000',
-  '11111111111111111110000001',
-  '11111111111111111110000010',
-  '11111111111111111110000011',
-  '11111111111111111110000100',
-  '11111111111111111110000101',
-  '11111111111111111110000110',
-  '11111111111111111110000111',
-  '11111111111111111110001000',
-  '11111111111111111110001001',
-  '11111111111111111110001010',
-  '11111111111111111110001011',
-  '11111111111111111110001100',
-  '11111111111111111110001101',
-  '11111111111111111110001110',
-  '11111111111111111110001111',
-  '11111111111111111110010000',
-  '11111111111111111110010001',
-  '11111111111111111110010010',
-  '11111111111111111110010011',
-  '11111111111111111110010100',
-  '11111111111111111110010101',
-  '11111111111111111110010110',
-  '11111111111111111110010111',
-  '11111111111111111110011000',
-  '11111111111111111110011001',
-  '11111111111111111110011010',
-  '11111111111111111110011011',
-  '11111111111111111110011100',
-  '11111111111111111110011101',
-  '11111111111111111110011110',
-  '11111111111111111110011111',
-  '11111111111111111110100000',
-  '11111111111111111110100001',
-  '11111111111111111110100010',
-  '11111111111111111110100011',
-  '11111111111111111110100100',
-  '11111111111111111110100101',
-  '11111111111111111110100110',
-  '11111111111111111110100111',
-  '11111111111111111110101000',
-  '11111111111111111110101001',
-  '11111111111111111110101010',
-  '11111111111111111110101011',
-  '11111111111111111110101100',
-  '11111111111111111110101101',
-  '11111111111111111110101110',
-  '11111111111111111110101111',
-  '11111111111111111110110000',
-  '11111111111111111110110001',
-  '11111111111111111110110010',
-  '11111111111111111110110011',
-  '11111111111111111110110100',
-  '11111111111111111110110101',
-  '11111111111111111110110110',
-  '11111111111111111110110111',
-  '11111111111111111110111000',
-  '11111111111111111110111001',
   '11111111111111111110111010',
   '11111111111111111110111011',
   '11111111111111111110111100',
   '11111111111111111110111101',
   '11111111111111111110111110',
   '11111111111111111110111111',
   '11111111111111111111000000',
   '11111111111111111111000001',
@@ -959,19 +735,241 @@ HuffmanTable.huffmanTable = new HuffmanT
   '11111111111111111111010010',
   '11111111111111111111010011',
   '11111111111111111111010100',
   '11111111111111111111010101',
   '11111111111111111111010110',
   '11111111111111111111010111',
   '11111111111111111111011000',
   '11111111111111111111011001',
+  '00110',
+  '1111111111100',
+  '111110000',
+  '11111111111100',
+  '111111111111100',
+  '011110',
+  '1100100',
+  '1111111111101',
+  '1111111010',
+  '111110001',
+  '1111111011',
+  '1111111100',
+  '1100101',
+  '1100110',
+  '011111',
+  '00111',
+  '0000',
+  '0001',
+  '0010',
+  '01000',
+  '100000',
+  '100001',
+  '100010',
+  '100011',
+  '100100',
+  '100101',
+  '100110',
+  '11101100',
+  '11111111111111100',
+  '100111',
+  '111111111111101',
+  '1111111101',
+  '111111111111110',
+  '1100111',
+  '11101101',
+  '11101110',
+  '1101000',
+  '11101111',
+  '1101001',
+  '1101010',
+  '111110010',
+  '11110000',
+  '111110011',
+  '111110100',
+  '111110101',
+  '1101011',
+  '1101100',
+  '11110001',
+  '11110010',
+  '111110110',
+  '111110111',
+  '1101101',
+  '101000',
+  '11110011',
+  '111111000',
+  '111111001',
+  '11110100',
+  '111111010',
+  '111111011',
+  '11111111100',
   '11111111111111111111011010',
+  '11111111101',
+  '11111111111101',
+  '1101110',
+  '111111111111111110',
+  '01001',
+  '1101111',
+  '01010',
+  '101001',
+  '01011',
+  '1110000',
+  '101010',
+  '101011',
+  '01100',
+  '11110101',
+  '11110110',
+  '101100',
+  '101101',
+  '101110',
+  '01101',
+  '101111',
+  '111111100',
+  '110000',
+  '110001',
+  '01110',
+  '1110001',
+  '1110010',
+  '1110011',
+  '1110100',
+  '1110101',
+  '11110111',
+  '11111111111111101',
+  '111111111100',
+  '11111111111111110',
+  '111111111101',
   '11111111111111111111011011',
-  '11111111111111111111011100'
+  '11111111111111111111011100',
+  '11111111111111111111011101',
+  '11111111111111111111011110',
+  '11111111111111111111011111',
+  '11111111111111111111100000',
+  '11111111111111111111100001',
+  '11111111111111111111100010',
+  '11111111111111111111100011',
+  '11111111111111111111100100',
+  '11111111111111111111100101',
+  '11111111111111111111100110',
+  '11111111111111111111100111',
+  '11111111111111111111101000',
+  '11111111111111111111101001',
+  '11111111111111111111101010',
+  '11111111111111111111101011',
+  '11111111111111111111101100',
+  '11111111111111111111101101',
+  '11111111111111111111101110',
+  '11111111111111111111101111',
+  '11111111111111111111110000',
+  '11111111111111111111110001',
+  '11111111111111111111110010',
+  '11111111111111111111110011',
+  '11111111111111111111110100',
+  '11111111111111111111110101',
+  '11111111111111111111110110',
+  '11111111111111111111110111',
+  '11111111111111111111111000',
+  '11111111111111111111111001',
+  '11111111111111111111111010',
+  '11111111111111111111111011',
+  '11111111111111111111111100',
+  '11111111111111111111111101',
+  '11111111111111111111111110',
+  '11111111111111111111111111',
+  '1111111111111111110000000',
+  '1111111111111111110000001',
+  '1111111111111111110000010',
+  '1111111111111111110000011',
+  '1111111111111111110000100',
+  '1111111111111111110000101',
+  '1111111111111111110000110',
+  '1111111111111111110000111',
+  '1111111111111111110001000',
+  '1111111111111111110001001',
+  '1111111111111111110001010',
+  '1111111111111111110001011',
+  '1111111111111111110001100',
+  '1111111111111111110001101',
+  '1111111111111111110001110',
+  '1111111111111111110001111',
+  '1111111111111111110010000',
+  '1111111111111111110010001',
+  '1111111111111111110010010',
+  '1111111111111111110010011',
+  '1111111111111111110010100',
+  '1111111111111111110010101',
+  '1111111111111111110010110',
+  '1111111111111111110010111',
+  '1111111111111111110011000',
+  '1111111111111111110011001',
+  '1111111111111111110011010',
+  '1111111111111111110011011',
+  '1111111111111111110011100',
+  '1111111111111111110011101',
+  '1111111111111111110011110',
+  '1111111111111111110011111',
+  '1111111111111111110100000',
+  '1111111111111111110100001',
+  '1111111111111111110100010',
+  '1111111111111111110100011',
+  '1111111111111111110100100',
+  '1111111111111111110100101',
+  '1111111111111111110100110',
+  '1111111111111111110100111',
+  '1111111111111111110101000',
+  '1111111111111111110101001',
+  '1111111111111111110101010',
+  '1111111111111111110101011',
+  '1111111111111111110101100',
+  '1111111111111111110101101',
+  '1111111111111111110101110',
+  '1111111111111111110101111',
+  '1111111111111111110110000',
+  '1111111111111111110110001',
+  '1111111111111111110110010',
+  '1111111111111111110110011',
+  '1111111111111111110110100',
+  '1111111111111111110110101',
+  '1111111111111111110110110',
+  '1111111111111111110110111',
+  '1111111111111111110111000',
+  '1111111111111111110111001',
+  '1111111111111111110111010',
+  '1111111111111111110111011',
+  '1111111111111111110111100',
+  '1111111111111111110111101',
+  '1111111111111111110111110',
+  '1111111111111111110111111',
+  '1111111111111111111000000',
+  '1111111111111111111000001',
+  '1111111111111111111000010',
+  '1111111111111111111000011',
+  '1111111111111111111000100',
+  '1111111111111111111000101',
+  '1111111111111111111000110',
+  '1111111111111111111000111',
+  '1111111111111111111001000',
+  '1111111111111111111001001',
+  '1111111111111111111001010',
+  '1111111111111111111001011',
+  '1111111111111111111001100',
+  '1111111111111111111001101',
+  '1111111111111111111001110',
+  '1111111111111111111001111',
+  '1111111111111111111010000',
+  '1111111111111111111010001',
+  '1111111111111111111010010',
+  '1111111111111111111010011',
+  '1111111111111111111010100',
+  '1111111111111111111010101',
+  '1111111111111111111010110',
+  '1111111111111111111010111',
+  '1111111111111111111011000',
+  '1111111111111111111011001',
+  '1111111111111111111011010',
+  '1111111111111111111011011',
+  '1111111111111111111011100'
 ]);
 
 // ### String literal representation ###
 //
 // Literal **strings** can represent header names or header values. There's two variant of the
 // string encoding:
 //
 // String literal with Huffman encoding:
@@ -1035,50 +1033,72 @@ HeaderSetDecompressor.string = function 
 //       0   1   2   3   4   5   6   7
 //     +---+---+---+---+---+---+---+---+
 //     | 1 |        Index (7+)         |  Indexed Representation
 //     +---+---------------------------+
 //
 //       0   1   2   3   4   5   6   7
 //     +---+---+---+---+---+---+---+---+
 //     | 0 | 1 |      Index (6+)       |
-//     +---+---+---+-------------------+  Literal w/o Indexing
+//     +---+---+---+-------------------+  Literal w/ Indexing
 //     |       Value Length (8+)       |
 //     +-------------------------------+  w/ Indexed Name
 //     | Value String (Length octets)  |
 //     +-------------------------------+
 //
 //       0   1   2   3   4   5   6   7
 //     +---+---+---+---+---+---+---+---+
 //     | 0 | 1 |           0           |
 //     +---+---+---+-------------------+
 //     |       Name Length (8+)        |
-//     +-------------------------------+  Literal w/o Indexing
+//     +-------------------------------+  Literal w/ Indexing
 //     |  Name String (Length octets)  |
 //     +-------------------------------+  w/ New Name
 //     |       Value Length (8+)       |
 //     +-------------------------------+
 //     | Value String (Length octets)  |
 //     +-------------------------------+
 //
 //       0   1   2   3   4   5   6   7
 //     +---+---+---+---+---+---+---+---+
-//     | 0 | 0 |      Index (6+)       |
-//     +---+---+---+-------------------+  Literal w/ Incremental Indexing
+//     | 0 | 0 | 0 | 0 |  Index (4+)   |
+//     +---+---+---+-------------------+  Literal w/o Incremental Indexing
 //     |       Value Length (8+)       |
 //     +-------------------------------+  w/ Indexed Name
 //     | Value String (Length octets)  |
 //     +-------------------------------+
 //
 //       0   1   2   3   4   5   6   7
 //     +---+---+---+---+---+---+---+---+
-//     | 0 | 0 |           0           |
+//     | 0 | 0 | 0 | 0 |       0       |
 //     +---+---+---+-------------------+
 //     |       Name Length (8+)        |
-//     +-------------------------------+  Literal w/ Incremental Indexing
+//     +-------------------------------+  Literal w/o Incremental Indexing
+//     |  Name String (Length octets)  |
+//     +-------------------------------+  w/ New Name
+//     |       Value Length (8+)       |
+//     +-------------------------------+
+//     | Value String (Length octets)  |
+//     +-------------------------------+
+//
+//       0   1   2   3   4   5   6   7
+//     +---+---+---+---+---+---+---+---+
+//     | 0 | 0 | 0 | 1 |  Index (4+)   |
+//     +---+---+---+-------------------+  Literal never indexed
+//     |       Value Length (8+)       |
+//     +-------------------------------+  w/ Indexed Name
+//     | Value String (Length octets)  |
+//     +-------------------------------+
+//
+//       0   1   2   3   4   5   6   7
+//     +---+---+---+---+---+---+---+---+
+//     | 0 | 0 | 0 | 1 |       0       |
+//     +---+---+---+-------------------+
+//     |       Name Length (8+)        |
+//     +-------------------------------+  Literal never indexed
 //     |  Name String (Length octets)  |
 //     +-------------------------------+  w/ New Name
 //     |       Value Length (8+)       |
 //     +-------------------------------+
 //     | Value String (Length octets)  |
 //     +-------------------------------+
 //
 // The **Indexed Representation** consists of the 1-bit prefix and the Index that is represented as
@@ -1088,40 +1108,48 @@ HeaderSetDecompressor.string = function 
 // pointer to the Header Table (Index) or a string literal. When the string literal representation
 // is used, the Index is set to 0 and the string literal starts at the second byte.
 //
 // For **all literal representations**, the specification of the header value comes next. It is
 // always represented as a string.
 
 var representations = {
   indexed             : { prefix: 7, pattern: 0x80 },
-  literal             : { prefix: 6, pattern: 0x40 },
-  literalIncremental  : { prefix: 6, pattern: 0x00 }
+  literalIncremental  : { prefix: 6, pattern: 0x40 },
+  contextUpdate       : { prefix: 0, pattern: 0x20 },
+  literalNeverIndexed : { prefix: 4, pattern: 0x10 },
+  literal             : { prefix: 4, pattern: 0x00 }
 };
 
 HeaderSetCompressor.header = function writeHeader(header) {
   var representation, buffers = [];
 
-  if (typeof header.value === 'number') {
+  if (header.contextUpdate) {
+    representation = representations.contextUpdate;
+  } else if (typeof header.value === 'number') {
     representation = representations.indexed;
   } else if (header.index) {
     representation = representations.literalIncremental;
+  } else if (header.mustNeverIndex) {
+    representation = representations.literalNeverIndexed;
   } else {
     representation = representations.literal;
   }
 
-  if (representation === representations.indexed) {
+  if (representation === representations.contextUpdate) {
+    if (header.clearReferenceSet) {
+      var buffer = new Buffer('10', 'hex');
+      buffers.push([buffer]);
+    } else {
+      buffers.push(HeaderSetCompressor.integer(header.newMaxSize, 4));
+    }
+  }
+
+  else if (representation === representations.indexed) {
     buffers.push(HeaderSetCompressor.integer(header.value + 1, representation.prefix));
-    if (header.value == -1) {
-      if (header.index) {
-        buffers.push(HeaderSetCompressor.integer(0x80, 8));
-      } else {
-        buffers.push(HeaderSetCompressor.integer(header.name, 7));
-      }
-    }
   }
 
   else {
     if (typeof header.name === 'number') {
       buffers.push(HeaderSetCompressor.integer(header.name + 1, representation.prefix));
     } else {
       buffers.push(HeaderSetCompressor.integer(0, representation.prefix));
       buffers.push(HeaderSetCompressor.string(header.name));
@@ -1136,41 +1164,54 @@ HeaderSetCompressor.header = function wr
 
 HeaderSetDecompressor.header = function readHeader(buffer) {
   var representation, header = {};
 
   var firstByte = buffer[buffer.cursor];
   if (firstByte & 0x80) {
     representation = representations.indexed;
   } else if (firstByte & 0x40) {
-    representation = representations.literal;
+    representation = representations.literalIncremental;
+  } else if (firstByte & 0x20) {
+    representation = representations.contextUpdate;
+  } else if (firstByte & 0x10) {
+    representation = representations.literalNeverIndexed;
   } else {
-    representation = representations.literalIncremental;
+    representation = representations.literal;
   }
 
-  if (representation === representations.indexed) {
+  header.value = header.name = -1;
+  header.index = false;
+  header.contextUpdate = false;
+  header.clearReferenceSet = false;
+  header.newMaxSize = 0;
+  header.mustNeverIndex = false;
+
+  if (representation === representations.contextUpdate) {
+    header.contextUpdate = true;
+    if (firstByte & 0x10) {
+      header.clearReferenceSet = true;
+      buffer.cursor += 1;
+    } else {
+      header.newMaxSize = HeaderSetDecompressor.integer(buffer, 4);
+    }
+  }
+
+  else if (representation === representations.indexed) {
     header.value = header.name = HeaderSetDecompressor.integer(buffer, representation.prefix) - 1;
-    header.index = false;
-    if (header.value === -1) {
-      if (buffer[buffer.cursor] & 0x80) {
-        header.index = true;
-        buffer.cursor += 1;
-      } else {
-        header.name = HeaderSetDecompressor.integer(buffer, 7);
-      }
-    }
   }
 
   else {
     header.name = HeaderSetDecompressor.integer(buffer, representation.prefix) - 1;
     if (header.name === -1) {
       header.name = HeaderSetDecompressor.string(buffer);
     }
     header.value = HeaderSetDecompressor.string(buffer);
     header.index = (representation === representations.literalIncremental);
+    header.mustNeverIndex = (representation === representations.literalNeverIndexed);
   }
 
   return header;
 };
 
 // Integration with HTTP/2
 // =======================
 
--- a/testing/xpcshell/node-http2/node_modules/http2-protocol/lib/connection.js
+++ b/testing/xpcshell/node-http2/node_modules/http2-protocol/lib/connection.js
@@ -117,17 +117,18 @@ Connection.prototype._initializeStreamMa
   this._streamLimit = Infinity;
   this.on('RECEIVING_SETTINGS_MAX_CONCURRENT_STREAMS', this._updateStreamLimit);
 };
 
 // `_writeControlFrame` is called when there's an incoming frame in the `_control` stream. It
 // broadcasts the message by creating an event on it.
 Connection.prototype._writeControlFrame = function _writeControlFrame(frame) {
   if ((frame.type === 'SETTINGS') || (frame.type === 'PING') ||
-      (frame.type === 'GOAWAY') || (frame.type === 'WINDOW_UPDATE')) {
+      (frame.type === 'GOAWAY') || (frame.type === 'WINDOW_UPDATE') ||
+      (frame.type === 'ALTSVC')) {
     this._log.debug({ frame: frame }, 'Receiving connection level frame');
     this.emit(frame.type, frame);
   } else {
     this._log.error({ frame: frame }, 'Invalid connection level frame');
     this.emit('error', 'PROTOCOL_ERROR');
   }
 };
 
@@ -184,18 +185,18 @@ Connection.prototype._allocateId = funct
   assert(!(id in this._streamIds));
 
   // * adding to `this._streamIds`
   this._log.trace({ s: stream, stream_id: id }, 'Allocating ID for stream.');
   this._streamIds[id] = stream;
   stream.id = id;
   this.emit('new_stream', stream, id);
 
-  // * handling stream errors as connection errors
-  stream.on('error', this.emit.bind(this, 'error'));
+  // * forwarding connection errors from streams
+  stream.on('connectionError', this.emit.bind(this, 'error'));
 
   return id;
 };
 
 // Allocating a priority to a stream, and managing priority changes
 Connection.prototype._allocatePriority = function _allocatePriority(stream) {
   this._log.trace({ s: stream }, 'Allocating priority for stream.');
   this._insert(stream, stream._priority);
--- a/testing/xpcshell/node-http2/node_modules/http2-protocol/lib/flow.js
+++ b/testing/xpcshell/node-http2/node_modules/http2-protocol/lib/flow.js
@@ -14,17 +14,17 @@ exports.Flow = Flow;
 // Public API
 // ----------
 
 // * **Event: 'error' (type)**: signals an error
 //
 // * **setInitialWindow(size)**: the initial flow control window size can be changed *any time*
 //   ([as described in the standard][1]) using this method
 //
-// [1]: http://tools.ietf.org/html/draft-ietf-httpbis-http2-10#section-6.9.2
+// [1]: http://tools.ietf.org/html/draft-ietf-httpbis-http2-11#section-6.9.2
 
 // API for child classes
 // ---------------------
 
 // * **new Flow([flowControlId])**: creating a new flow that will listen for WINDOW_UPDATES frames
 //   with the given `flowControlId` (or every update frame if not given)
 //
 // * **_send()**: called when more frames should be pushed. The child class is expected to override
--- a/testing/xpcshell/node-http2/node_modules/http2-protocol/lib/framer.js
+++ b/testing/xpcshell/node-http2/node_modules/http2-protocol/lib/framer.js
@@ -7,16 +7,17 @@ var assert = require('assert');
 var Transform = require('stream').Transform;
 
 exports.Serializer = Serializer;
 exports.Deserializer = Deserializer;
 
 var logData = Boolean(process.env.HTTP2_LOG_DATA);
 
 var MAX_PAYLOAD_SIZE = 16383;
+var WINDOW_UPDATE_PAYLOAD_SIZE = 4;
 
 // Serializer
 // ----------
 //
 //     Frame Objects
 //     * * * * * * * --+---------------------------
 //                     |                          |
 //                     v                          v           Buffers
@@ -126,33 +127,33 @@ Deserializer.prototype._transform = func
     //
     // Note: If we just finished the parsing of a header and the payload length is 0, this branch
     // will also run.
     if ((this._cursor === this._buffer.length) && !this._waitingForHeader) {
       if (this._frame.type) {
         var error = Deserializer[this._frame.type](this._buffer, this._frame, this._role);
         if (error) {
           this._log.error('Incoming frame parsing error: ' + error);
-          this.emit('error', 'PROTOCOL_ERROR');
+          this.emit('error', error);
         } else {
           this._log.trace({ frame: this._frame }, 'Incoming frame');
           this.push(this._frame);
         }
       } else {
         this._log.error('Unknown type incoming frame');
         this.emit('error', 'PROTOCOL_ERROR');
       }
       this._next(COMMON_HEADER_SIZE);
     }
   }
 
   done();
 };
 
-// [Frame Header](http://tools.ietf.org/html/draft-ietf-httpbis-http2-10#section-4.1)
+// [Frame Header](http://tools.ietf.org/html/draft-ietf-httpbis-http2-11#section-4.1)
 // --------------------------------------------------------------
 //
 // HTTP/2.0 frames share a common base format consisting of an 8-byte header followed by 0 to 65535
 // bytes of data.
 //
 // Additional size limits can be set by specific application uses. HTTP limits the frame size to
 // 16,383 octets.
 //
@@ -256,41 +257,41 @@ Deserializer.commonHeader = function rea
 
 // Every frame type is registered in the following places:
 //
 // * `frameTypes`: a register of frame type codes (used by `commonHeader()`)
 // * `frameFlags`: a register of valid flags for frame types (used by `commonHeader()`)
 // * `typeSpecificAttributes`: a register of frame specific frame object attributes (used by
 //   logging code and also serves as documentation for frame objects)
 
-// [DATA Frames](http://tools.ietf.org/html/draft-ietf-httpbis-http2-10#section-6.1)
+// [DATA Frames](http://tools.ietf.org/html/draft-ietf-httpbis-http2-11#section-6.1)
 // ------------------------------------------------------------
 //
 // DATA frames (type=0x0) convey arbitrary, variable-length sequences of octets associated with a
 // stream.
 //
 // The DATA frame defines the following flags:
 //
 // * END_STREAM (0x1):
 //   Bit 1 being set indicates that this frame is the last that the endpoint will send for the
 //   identified stream.
 // * END_SEGMENT (0x2):
 //   Bit 2 being set indicates that this frame is the last for the current segment. Intermediaries
 //   MUST NOT coalesce frames across a segment boundary and MUST preserve segment boundaries when
 //   forwarding frames.
-// * PAD_LOW (0x10):
+// * PAD_LOW (0x08):
 //   Bit 5 being set indicates that the Pad Low field is present.
-// * PAD_HIGH (0x20):
+// * PAD_HIGH (0x10):
 //   Bit 6 being set indicates that the Pad High field is present. This bit MUST NOT be set unless
 //   the PAD_LOW flag is also set. Endpoints that receive a frame with PAD_HIGH set and PAD_LOW
 //   cleared MUST treat this as a connection error of type PROTOCOL_ERROR.
 
 frameTypes[0x0] = 'DATA';
 
-frameFlags.DATA = ['END_STREAM', 'END_SEGMENT', 'RESERVED4', 'RESERVED8', 'PAD_LOW', 'PAD_HIGH'];
+frameFlags.DATA = ['END_STREAM', 'END_SEGMENT', 'RESERVED4', 'PAD_LOW', 'PAD_HIGH'];
 
 typeSpecificAttributes.DATA = ['data'];
 
 Serializer.DATA = function writeData(frame, buffers) {
   buffers.push(frame.data);
 };
 
 Deserializer.DATA = function readData(buffer, frame) {
@@ -308,64 +309,79 @@ Deserializer.DATA = function readData(bu
   }
   if (paddingLength) {
     frame.data = buffer.slice(dataOffset, -1 * paddingLength);
   } else {
     frame.data = buffer.slice(dataOffset);
   }
 };
 
-// [HEADERS](http://tools.ietf.org/html/draft-ietf-httpbis-http2-10#section-6.2)
+// [HEADERS](http://tools.ietf.org/html/draft-ietf-httpbis-http2-11#section-6.2)
 // --------------------------------------------------------------
 //
 // The HEADERS frame (type=0x1) allows the sender to create a stream.
 //
 // The HEADERS frame defines the following flags:
 //
 // * END_STREAM (0x1):
 //   Bit 1 being set indicates that this frame is the last that the endpoint will send for the
 //   identified stream.
 // * END_SEGMENT (0x2):
 //   Bit 2 being set indicates that this frame is the last for the current segment. Intermediaries
 //   MUST NOT coalesce frames across a segment boundary and MUST preserve segment boundaries when
 //   forwarding frames.
 // * END_HEADERS (0x4):
 //   The END_HEADERS bit indicates that this frame contains the entire payload necessary to provide
 //   a complete set of headers.
-// * PRIORITY (0x8):
-//   Bit 4 being set indicates that the first four octets of this frame contain a single reserved
-//   bit and a 31-bit priority.
-// * PAD_LOW (0x10):
+// * PAD_LOW (0x08):
 //   Bit 5 being set indicates that the Pad Low field is present.
-// * PAD_HIGH (0x20):
+// * PAD_HIGH (0x10):
 //   Bit 6 being set indicates that the Pad High field is present. This bit MUST NOT be set unless
 //   the PAD_LOW flag is also set. Endpoints that receive a frame with PAD_HIGH set and PAD_LOW
 //   cleared MUST treat this as a connection error of type PROTOCOL_ERROR.
 
 frameTypes[0x1] = 'HEADERS';
 
-frameFlags.HEADERS = ['END_STREAM', 'END_SEGMENT', 'END_HEADERS', 'PRIORITY', 'PAD_LOW', 'PAD_HIGH'];
+frameFlags.HEADERS = ['END_STREAM', 'END_SEGMENT', 'END_HEADERS', 'PAD_LOW', 'PAD_HIGH', 'PRIORITY_GROUP', 'PRIORITY_DEPENDENCY'];
 
-typeSpecificAttributes.HEADERS = ['priority', 'headers', 'data'];
+typeSpecificAttributes.HEADERS = ['priorityGroup', 'groupWeight', 'priorityDependency', 'exclusiveDependency', 'headers', 'data'];
 
 //      0                   1                   2                   3
 //      0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
 //     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-//     |X|               (Optional) Priority (31)                      |
+//     | Pad High? (8) |  Pad Low? (8) |
+//     +-+-------------+---------------+-------------------------------+
+//     |R|              Priority Group Identifier? (31)                |
+//     +-+-------------+-----------------------------------------------+
+//     |  Weight? (8)  |
+//     +-+-------------+-----------------------------------------------+
+//     |E|                 Stream Dependency? (31)                     |
 //     +-+-------------------------------------------------------------+
-//     |                    Header Block (*)                         ...
+//     |                   Header Block Fragment (*)                 ...
+//     +---------------------------------------------------------------+
+//     |                           Padding (*)                       ...
 //     +---------------------------------------------------------------+
 //
 // The payload of a HEADERS frame contains a Headers Block
 
 Serializer.HEADERS = function writeHeadersPriority(frame, buffers) {
-  if (frame.flags.PRIORITY) {
+  if (frame.flags.PRIORITY_GROUP) {
+    var buffer = new Buffer(5);
+    assert((0 <= frame.priorityGroup) && (frame.priorityGroup <= 0x7fffffff), frame.priorityGroup);
+    buffer.writeUInt32BE(frame.priorityGroup, 0);
+    assert((0 <= frame.groupWeight) && (frame.groupWeight <= 0xff), frame.groupWeight);
+    buffer.writeUInt8(frame.groupWeight, 4);
+    buffers.push(buffer);
+  } else if (frame.flags.PRIORITY_DEPENDENCY) {
     var buffer = new Buffer(4);
-    assert((0 <= frame.priority) && (frame.priority <= 0xffffffff), frame.priority);
-    buffer.writeUInt32BE(frame.priority, 0);
+    assert((0 <= frame.priorityDependency) && (frame.priorityDependency <= 0x7fffffff), frame.priorityDependency);
+    buffer.writeUInt32BE(frame.priorityDependency, 0);
+    if (frame.exclusiveDependency) {
+      buffer[0] |= 0x80;
+    }
     buffers.push(buffer);
   }
   buffers.push(frame.data);
 };
 
 Deserializer.HEADERS = function readHeadersPriority(buffer, frame) {
   var dataOffset = 0;
   var paddingLength = 0;
@@ -374,59 +390,110 @@ Deserializer.HEADERS = function readHead
       paddingLength = (buffer.readUInt8(dataOffset) & 0xff) * 256;
       dataOffset += 1;
     }
     paddingLength += (buffer.readUInt8(dataOffset) & 0xff);
     dataOffset += 1;
   } else if (frame.flags.PAD_HIGH) {
     return 'HEADERS frame got PAD_HIGH without PAD_LOW';
   }
-  if (frame.flags.PRIORITY) {
-    frame.priority = buffer.readUInt32BE(dataOffset) & 0x7fffffff;
+
+  if (frame.flags.PRIORITY_GROUP) {
+    if (frame.flags.PRIORITY_DEPENDENCY) {
+      return 'HEADERS frame got both PRIORITY_GROUP and PRIORITY_DEPENDENCY';
+    }
+    frame.priorityGroup = buffer.readUInt32BE(dataOffset) & 0x7fffffff;
     dataOffset += 4;
+    frame.groupWeight = buffer.readUInt8(dataOffset);
+    dataOffset += 1;
+  } else if (frame.flags.PRIORITY_DEPENDENCY) {
+    var dependencyData = new Buffer(4);
+    buffer.copy(dependencyData, 0, dataOffset, dataOffset + 4);
+    dataOffset += 4;
+    frame.exclusiveDependency = !!(dependencyData[0] & 0x80);
+    dependencyData[0] &= 0x7f;
+    frame.priorityDependency = dependencyData.readUInt32BE(0);
   }
+
   if (paddingLength) {
     frame.data = buffer.slice(dataOffset, -1 * paddingLength);
   } else {
     frame.data = buffer.slice(dataOffset);
   }
 };
 
-// [PRIORITY](http://tools.ietf.org/html/draft-ietf-httpbis-http2-10#section-6.3)
+// [PRIORITY](http://tools.ietf.org/html/draft-ietf-httpbis-http2-11#section-6.3)
 // -------------------------------------------------------
 //
 // The PRIORITY frame (type=0x2) specifies the sender-advised priority of a stream.
 //
 // The PRIORITY frame does not define any flags.
 
 frameTypes[0x2] = 'PRIORITY';
 
-frameFlags.PRIORITY = [];
+frameFlags.PRIORITY = ['RESERVED1', 'RESERVED2', 'RESERVED4', 'RESERVED8', 'RESERVED16', 'PRIORITY_GROUP', 'PRIORITY_DEPENDENCY'];
 
-typeSpecificAttributes.PRIORITY = ['priority'];
+typeSpecificAttributes.PRIORITY = ['priorityGroup', 'groupWeight', 'priorityDependency', 'exclusiveDependency'];
 
 //      0                   1                   2                   3
 //      0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
 //     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-//     |X|                   Priority (31)                             |
+//     |R|              Priority Group Identifier? (31)                |
+//     +-+-------------+-----------------------------------------------+
+//     |  Weight? (8)  |
+//     +-+-------------+-----------------------------------------------+
+//     |E|                 Stream Dependency? (31)                     |
 //     +-+-------------------------------------------------------------+
 //
 // The payload of a PRIORITY frame contains a single reserved bit and a 31-bit priority.
 
 Serializer.PRIORITY = function writePriority(frame, buffers) {
-  var buffer = new Buffer(4);
-  buffer.writeUInt32BE(frame.priority, 0);
+  var buffer;
+
+  assert((frame.flags.PRIORITY_GROUP || frame.flags.PRIORITY_DEPENDENCY) &&
+          !(frame.flags.PRIORITY_GROUP && frame.flags.PRIORITY_DEPENDENCY),
+         frame.flags.PRIORITY_GROUP && frame.flags.PRIORITY_DEPENDENCY);
+
+  if (frame.flags.PRIORITY_GROUP) {
+    buffer = new Buffer(5);
+    assert((0 <= frame.priorityGroup) && (frame.priorityGroup <= 0x7fffffff), frame.priorityGroup);
+    buffer.writeUInt32BE(frame.priorityGroup, 0);
+    assert((0 <= frame.groupWeight) && (frame.groupWeight <= 0xff), frame.groupWeight);
+    buffer.writeUInt8(frame.groupWeight, 4);
+  } else { // frame.flags.PRIORITY_DEPENDENCY
+    buffer = new Buffer(4);
+    assert((0 <= frame.priorityDependency) && (frame.priorityDependency <= 0x7fffffff), frame.priorityDependency);
+    buffer.writeUInt32BE(frame.priorityDependency, 0);
+    if (frame.exclusiveDependency) {
+      buffer[0] |= 0x80;
+    }
+  }
+
   buffers.push(buffer);
 };
 
 Deserializer.PRIORITY = function readPriority(buffer, frame) {
-  frame.priority = buffer.readUInt32BE(0);
+  if (frame.flags.PRIORITY_GROUP) {
+    if (frame.flags.PRIORITY_DEPENDENCY) {
+      return 'PRIORITY frame got both PRIORITY_GROUP and PRIORITY_DEPENDENCY';
+    }
+    frame.priorityGroup = buffer.readUInt32BE(0) & 0x7fffffff;
+    frame.groupWeight = buffer.readUInt8(4);
+  } else if (frame.flags.PRIORITY_DEPENDENCY) {
+    var dependencyData = new Buffer(4);
+    buffer.copy(dependencyData, 0, 0, 4);
+    frame.exclusiveDependency = !!(dependencyData[0] & 0x80);
+    dependencyData[0] &= 0x7f;
+    frame.priorityDependency = dependencyData.readUInt32BE(0);
+  } else {
+    return 'PRIORITY frame got neither PRIORITY_GROUP nor PRIORITY_DEPENDENCY';
+  }
 };
 
-// [RST_STREAM](http://tools.ietf.org/html/draft-ietf-httpbis-http2-10#section-6.4)
+// [RST_STREAM](http://tools.ietf.org/html/draft-ietf-httpbis-http2-11#section-6.4)
 // -----------------------------------------------------------
 //
 // The RST_STREAM frame (type=0x3) allows for abnormal termination of a stream.
 //
 // No type-flags are defined.
 
 frameTypes[0x3] = 'RST_STREAM';
 
@@ -450,17 +517,17 @@ Serializer.RST_STREAM = function writeRs
   buffer.writeUInt32BE(code, 0);
   buffers.push(buffer);
 };
 
 Deserializer.RST_STREAM = function readRstStream(buffer, frame) {
   frame.error = errorCodes[buffer.readUInt32BE(0)];
 };
 
-// [SETTINGS](http://tools.ietf.org/html/draft-ietf-httpbis-http2-10#section-6.5)
+// [SETTINGS](http://tools.ietf.org/html/draft-ietf-httpbis-http2-11#section-6.5)
 // -------------------------------------------------------
 //
 // The SETTINGS frame (type=0x4) conveys configuration parameters that affect how endpoints
 // communicate.
 //
 // The SETTINGS frame defines the following flag:
 
 // * ACK (0x1):
@@ -507,19 +574,26 @@ Serializer.SETTINGS = function writeSett
     buffer.writeUInt32BE(settings[i].value, i*5 + 1);
   }
 
   buffers.push(buffer);
 };
 
 Deserializer.SETTINGS = function readSettings(buffer, frame, role) {
   frame.settings = {};
+  
+  // Receipt of a SETTINGS frame with the ACK flag set and a length
+  // field value other than 0 MUST be treated as a connection error
+  // (Section 5.4.1) of type FRAME_SIZE_ERROR.
+  if(frame.flags.ACK && buffer.length != 0) {
+    return 'FRAME_SIZE_ERROR';
+  }
 
   if (buffer.length % 5 !== 0) {
-    return 'Invalid SETTINGS frame';
+    return 'PROTOCOL_ERROR';
   }
   for (var i = 0; i < buffer.length / 5; i++) {
     var id = buffer.readUInt8(i*5) & 0xff;
     var setting = definedSettings[id];
     if (setting) {
       if (role == 'CLIENT' && setting.name == 'SETTINGS_ENABLE_PUSH') {
         return 'SETTINGS frame on client got SETTINGS_ENABLE_PUSH';
       }
@@ -549,31 +623,31 @@ definedSettings[2] = { name: 'SETTINGS_E
 // * SETTINGS_MAX_CONCURRENT_STREAMS (4):
 //   indicates the maximum number of concurrent streams that the sender will allow.
 definedSettings[3] = { name: 'SETTINGS_MAX_CONCURRENT_STREAMS', flag: false };
 
 // * SETTINGS_INITIAL_WINDOW_SIZE (7):
 //   indicates the sender's initial stream window size (in bytes) for new streams.
 definedSettings[4] = { name: 'SETTINGS_INITIAL_WINDOW_SIZE', flag: false };
 
-// [PUSH_PROMISE](http://tools.ietf.org/html/draft-ietf-httpbis-http2-10#section-6.6)
+// [PUSH_PROMISE](http://tools.ietf.org/html/draft-ietf-httpbis-http2-11#section-6.6)
 // ---------------------------------------------------------------
 //
 // The PUSH_PROMISE frame (type=0x5) is used to notify the peer endpoint in advance of streams the
 // sender intends to initiate.
 //
 // The PUSH_PROMISE frame defines the following flags:
 //
 // * END_PUSH_PROMISE (0x4):
 //   The END_PUSH_PROMISE bit indicates that this frame contains the entire payload necessary to
 //   provide a complete set of headers.
 
 frameTypes[0x5] = 'PUSH_PROMISE';
 
-frameFlags.PUSH_PROMISE = ['RESERVED1', 'RESERVED2', 'END_PUSH_PROMISE'];
+frameFlags.PUSH_PROMISE = ['RESERVED1', 'RESERVED2', 'END_PUSH_PROMISE', 'PAD_LOW', 'PAD_HIGH'];
 
 typeSpecificAttributes.PUSH_PROMISE = ['promised_stream', 'headers', 'data'];
 
 //      0                   1                   2                   3
 //      0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
 //     +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 //     |X|                Promised-Stream-ID (31)                      |
 //     +-+-------------------------------------------------------------+
@@ -591,21 +665,38 @@ Serializer.PUSH_PROMISE = function write
   assert((0 <= promised_stream) && (promised_stream <= 0x7fffffff), promised_stream);
   buffer.writeUInt32BE(promised_stream, 0);
 
   buffers.push(buffer);
   buffers.push(frame.data);
 };
 
 Deserializer.PUSH_PROMISE = function readPushPromise(buffer, frame) {
-  frame.promised_stream = buffer.readUInt32BE(0) & 0x7fffffff;
-  frame.data = buffer.slice(4);
+  var dataOffset = 0;
+  var paddingLength = 0;
+  if (frame.flags.PAD_LOW) {
+    if (frame.flags.PAD_HIGH) {
+      paddingLength = (buffer.readUInt8(dataOffset) & 0xff) * 256;
+      dataOffset += 1;
+    }
+    paddingLength += (buffer.readUInt8(dataOffset) & 0xff);
+    dataOffset += 1;
+  } else if (frame.flags.PAD_HIGH) {
+    return 'PUSH_PROMISE frame got PAD_HIGH without PAD_LOW';
+  }
+  frame.promised_stream = buffer.readUInt32BE(dataOffset) & 0x7fffffff;
+  dataOffset += 4;
+  if (paddingLength) {
+    frame.data = buffer.slice(dataOffset, -1 * paddingLength);
+  } else {
+    frame.data = buffer.slice(dataOffset);
+  }
 };
 
-// [PING](http://tools.ietf.org/html/draft-ietf-httpbis-http2-10#section-6.7)
+// [PING](http://tools.ietf.org/html/draft-ietf-httpbis-http2-11#section-6.7)
 // -----------------------------------------------
 //
 // The PING frame (type=0x6) is a mechanism for measuring a minimal round-trip time from the
 // sender, as well as determining whether an idle connection is still functional.
 //
 // The PING frame defines one type-specific flag:
 //
 // * ACK (0x1):
@@ -620,22 +711,22 @@ typeSpecificAttributes.PING = ['data'];
 // In addition to the frame header, PING frames MUST contain 8 additional octets of opaque data.
 
 Serializer.PING = function writePing(frame, buffers) {
   buffers.push(frame.data);
 };
 
 Deserializer.PING = function readPing(buffer, frame) {
   if (buffer.length !== 8) {
-    return 'Invalid size PING frame';
+    return 'FRAME_SIZE_ERROR';
   }
   frame.data = buffer;
 };
 
-// [GOAWAY](http://tools.ietf.org/html/draft-ietf-httpbis-http2-10#section-6.8)
+// [GOAWAY](http://tools.ietf.org/html/draft-ietf-httpbis-http2-11#section-6.8)
 // ---------------------------------------------------
 //
 // The GOAWAY frame (type=0x7) informs the remote peer to stop creating streams on this connection.
 //
 // The GOAWAY frame does not define any flags.
 
 frameTypes[0x7] = 'GOAWAY';
 
@@ -672,17 +763,17 @@ Serializer.GOAWAY = function writeGoaway
   buffers.push(buffer);
 };
 
 Deserializer.GOAWAY = function readGoaway(buffer, frame) {
   frame.last_stream = buffer.readUInt32BE(0) & 0x7fffffff;
   frame.error = errorCodes[buffer.readUInt32BE(4)];
 };
 
-// [WINDOW_UPDATE](http://tools.ietf.org/html/draft-ietf-httpbis-http2-10#section-6.9)
+// [WINDOW_UPDATE](http://tools.ietf.org/html/draft-ietf-httpbis-http2-11#section-6.9)
 // -----------------------------------------------------------------
 //
 // The WINDOW_UPDATE frame (type=0x8) is used to implement flow control.
 //
 // The WINDOW_UPDATE frame does not define any flags.
 
 frameTypes[0x8] = 'WINDOW_UPDATE';
 
@@ -701,39 +792,42 @@ Serializer.WINDOW_UPDATE = function writ
   var window_size = frame.window_size;
   assert((0 <= window_size) && (window_size <= 0x7fffffff), window_size);
   buffer.writeUInt32BE(window_size, 0);
 
   buffers.push(buffer);
 };
 
 Deserializer.WINDOW_UPDATE = function readWindowUpdate(buffer, frame) {
+  if (buffer.length !== WINDOW_UPDATE_PAYLOAD_SIZE) {
+    return 'FRAME_SIZE_ERROR';
+  }
   frame.window_size = buffer.readUInt32BE(0) & 0x7fffffff;
 };
 
-// [CONTINUATION](http://tools.ietf.org/html/draft-ietf-httpbis-http2-10#section-6.10)
+// [CONTINUATION](http://tools.ietf.org/html/draft-ietf-httpbis-http2-11#section-6.10)
 // ------------------------------------------------------------
 //
-// The CONTINUATION frame (type=0xA) is used to continue a sequence of header block fragments.
+// The CONTINUATION frame (type=0x9) is used to continue a sequence of header block fragments.
 //
 // The CONTINUATION frame defines the following flag:
 //
 // * END_HEADERS (0x4):
 //   The END_HEADERS bit indicates that this frame ends the sequence of header block fragments
 //   necessary to provide a complete set of headers.
-// * PAD_LOW (0x10):
+// * PAD_LOW (0x08):
 //   Bit 5 being set indicates that the Pad Low field is present.
-// * PAD_HIGH (0x20):
+// * PAD_HIGH (0x10):
 //   Bit 6 being set indicates that the Pad High field is present. This bit MUST NOT be set unless
 //   the PAD_LOW flag is also set. Endpoints that receive a frame with PAD_HIGH set and PAD_LOW
 //   cleared MUST treat this as a connection error of type PROTOCOL_ERROR.
 
 frameTypes[0x9] = 'CONTINUATION';
 
-frameFlags.CONTINUATION = ['RESERVED1', 'RESERVED2', 'END_HEADERS', 'RESERVED8', 'PAD_LOW', 'PAD_HIGH'];
+frameFlags.CONTINUATION = ['RESERVED1', 'RESERVED2', 'END_HEADERS', 'PAD_LOW', 'PAD_HIGH'];
 
 typeSpecificAttributes.CONTINUATION = ['headers', 'data'];
 
 Serializer.CONTINUATION = function writeContinuation(frame, buffers) {
   buffers.push(frame.data);
 };
 
 Deserializer.CONTINUATION = function readContinuation(buffer, frame) {
@@ -751,33 +845,123 @@ Deserializer.CONTINUATION = function rea
   }
   if (paddingLength) {
     frame.data = buffer.slice(dataOffset, -1 * paddingLength);
   } else {
     frame.data = buffer.slice(dataOffset);
   }
 };
 
-// [Error Codes](http://tools.ietf.org/html/draft-ietf-httpbis-http2-10#section-7)
+// [ALTSVC](http://tools.ietf.org/html/draft-ietf-httpbis-http2-11#section-6.11)
+// ------------------------------------------------------------
+//
+// The ALTSVC frame (type=0xA) advertises the availability of an alternative service to the client.
+//
+// The ALTSVC frame does not define any flags.
+
+frameTypes[0xA] = 'ALTSVC';
+
+frameFlags.ALTSVC = [];
+
+//     0                   1                   2                   3
+//     0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+//    +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+//    |                          Max-Age (32)                         |
+//    +-------------------------------+----------------+--------------+
+//    |            Port (16)          |  Reserved (8)  | PID_LEN (8)  |
+//    +-------------------------------+----------------+--------------+
+//    |                        Protocol-ID (*)                        |
+//    +---------------+-----------------------------------------------+
+//    | HOST_LEN (8)  |                   Host (*)                  ...
+//    +---------------+-----------------------------------------------+
+//    |                          Origin? (*)                        ...
+//    +---------------------------------------------------------------+
+//
+// The ALTSVC frame contains the following fields:
+//
+// Max-Age: An unsigned, 32-bit integer indicating the freshness
+//    lifetime of the alternative service association, as per [ALT-SVC](http://tools.ietf.org/html/draft-ietf-httpbis-alt-svc-01)
+//    section 2.2.
+//
+// Port: An unsigned, 16-bit integer indicating the port that the
+//    alternative service is available upon.
+//
+// Reserved: For future use. Senders MUST set these bits to '0', and
+//    recipients MUST ignore them.
+//
+// PID_LEN: An unsigned, 8-bit integer indicating the length, in
+//    octets, of the Protocol-ID field.
+//
+// Protocol-ID: A sequence of bytes (length determined by PID_LEN)
+//    containing the ALPN protocol identifier of the alternative
+//    service.
+//
+// HOST_LEN: An unsigned, 8-bit integer indicating the length, in
+//    octets, of the Host field.
+//
+// Host: A sequence of characters (length determined by HOST_LEN)
+//    containing an ASCII string indicating the host that the
+//    alternative service is available upon. An internationalized
+//    domain [IDNA] MUST be expressed using A-labels.
+//
+// Origin: An optional sequence of characters (length determined by
+//    subtracting the length of all lpreceding fields from the frame
+//    length) containing ASCII serialisation of an origin ([RFC6454](http://tools.ietf.org/html/rfc6454),
+//    Section 6.2) that the alternate service is applicable to.
+
+typeSpecificAttributes.ALTSVC = ['maxAge', 'port', 'protocolID', 'host',
+                                 'origin'];
+
+Serializer.ALTSVC = function writeAltSvc(frame, buffers) {
+  var buffer = new Buffer(8);
+  buffer.writeUInt32BE(frame.maxAge, 0);
+  buffer.writeUInt16BE(frame.port, 4);
+  buffer.writeUInt8(0, 6);
+  buffer.writeUInt8(frame.protocolID.length, 7);
+  buffers.push(buffer);
+
+  buffers.push(new Buffer(frame.protocolID, 'ascii'));
+
+  buffer = new Buffer(1);
+  buffer.writeUInt8(frame.host.length, 0);
+  buffers.push(buffer);
+
+  buffers.push(new Buffer(frame.host, 'ascii'));
+
+  buffers.push(new Buffer(frame.origin, 'ascii'));
+};
+
+Deserializer.ALTSVC = function readAltSvc(buffer, frame) {
+  frame.maxAge = buffer.readUInt32BE(0);
+  frame.port = buffer.readUInt16BE(4);
+  var pidLength = buffer.readUInt8(7);
+  frame.protocolID = buffer.toString('ascii', 8, 8 + pidLength);
+  var hostLength = buffer.readUInt8(8 + pidLength);
+  frame.host = buffer.toString('ascii', 9 + pidLength, 9 + pidLength + hostLength);
+  frame.origin = buffer.toString('ascii', 9 + pidLength + hostLength);
+};
+
+// [Error Codes](http://tools.ietf.org/html/draft-ietf-httpbis-http2-11#section-7)
 // ------------------------------------------------------------
 
 var errorCodes = [
   'NO_ERROR',
   'PROTOCOL_ERROR',
   'INTERNAL_ERROR',
   'FLOW_CONTROL_ERROR',
   'SETTINGS_TIMEOUT',
   'STREAM_CLOSED',
   'FRAME_SIZE_ERROR',
   'REFUSED_STREAM',
   'CANCEL',
   'COMPRESSION_ERROR',
-  'CONNECT_ERROR'
+  'CONNECT_ERROR',
+  'ENHANCE_YOUR_CALM',
+  'INADEQUATE_SECURITY'
 ];
-errorCodes[420] = 'ENHANCE_YOUR_CALM';
 
 // Logging
 // -------
 
 // [Bunyan serializers](https://github.com/trentm/node-bunyan#serializers) to improve logging output
 // for debug messages emitted in this component.
 exports.serializers = {};
 
--- a/testing/xpcshell/node-http2/node_modules/http2-protocol/lib/index.js
+++ b/testing/xpcshell/node-http2/node_modules/http2-protocol/lib/index.js
@@ -1,9 +1,9 @@
-// [node-http2-protocol][homepage] is an implementation of the [HTTP/2 (draft 10)][http2]
+// [node-http2-protocol][homepage] is an implementation of the [HTTP/2 (draft 11)][http2]
 // framing layer for [node.js][node].
 //
 // The main building blocks are [node.js streams][node-stream] that are connected through pipes.
 //
 // The main components are:
 //
 // * [Endpoint](endpoint.html): represents an HTTP/2 endpoint (client or server). It's
 //   responsible for the the first part of the handshake process (sending/receiving the
@@ -23,26 +23,26 @@
 //
 // * [Compressor and Decompressor](compressor.html): compression and decompression of HEADER and
 //   PUSH_PROMISE frames
 //
 // * [Serializer and Deserializer](framer.html): the lowest layer in the stack that transforms
 //   between the binary and the JavaScript object representation of HTTP/2 frames
 //
 // [homepage]:            https://github.com/molnarg/node-http2
-// [http2]:               http://tools.ietf.org/html/draft-ietf-httpbis-http2-10
-// [http2-connheader]:    http://tools.ietf.org/html/draft-ietf-httpbis-http2-10#section-3.5
-// [http2-stream]:        http://tools.ietf.org/html/draft-ietf-httpbis-http2-10#section-5
-// [http2-streamstate]:   http://tools.ietf.org/html/draft-ietf-httpbis-http2-10#section-5.1
+// [http2]:               http://tools.ietf.org/html/draft-ietf-httpbis-http2-11
+// [http2-connheader]:    http://tools.ietf.org/html/draft-ietf-httpbis-http2-11#section-3.5
+// [http2-stream]:        http://tools.ietf.org/html/draft-ietf-httpbis-http2-11#section-5
+// [http2-streamstate]:   http://tools.ietf.org/html/draft-ietf-httpbis-http2-11#section-5.1
 // [node]:                http://nodejs.org/
 // [node-stream]:         http://nodejs.org/api/stream.html
 // [node-https]:          http://nodejs.org/api/https.html
 // [node-http]:           http://nodejs.org/api/http.html
 
-exports.ImplementedVersion = 'h2-10';
+exports.ImplementedVersion = 'h2-11';
 
 exports.Endpoint = require('./endpoint').Endpoint;
 
 /* Bunyan serializers exported by submodules that are worth adding when creating a logger. */
 exports.serializers = {};
 var modules = ['./framer', './compressor', './flow', './connection', './stream', './endpoint'];
 modules.map(require).forEach(function(module) {
   for (var name in module.serializers) {
--- a/testing/xpcshell/node-http2/node_modules/http2-protocol/lib/stream.js
+++ b/testing/xpcshell/node-http2/node_modules/http2-protocol/lib/stream.js
@@ -220,16 +220,18 @@ Stream.prototype._writeUpstream = functi
 
   // * If it's a control frame. Call the appropriate handler method.
   if (frame.type === 'HEADERS') {
     this._onHeaders(frame);
   } else if (frame.type === 'PUSH_PROMISE') {
     this._onPromise(frame);
   } else if (frame.type === 'PRIORITY') {
     this._onPriority(frame);
+  } else if (frame.type === 'ALTSVC') {
+    // TODO
   }
 
   // * If it's an invalid stream level frame, emit error
   else if ((frame.type !== 'DATA') &&
            (frame.type !== 'WINDOW_UPDATE') &&
            (frame.type !== 'RST_STREAM')) {
     this._log.error({ frame: frame }, 'Invalid stream level frame');
     this.emit('error', 'PROTOCOL_ERROR');
@@ -317,17 +319,17 @@ Stream.prototype._finishing = function _
     this._log.debug({ frame: lastFrame }, 'Marking last frame with END_STREAM flag.');
     lastFrame.flags.END_STREAM = true;
     this._transition(true, endFrame);
   } else {
     this._pushUpstream(endFrame);
   }
 };
 
-// [Stream States](http://tools.ietf.org/html/draft-ietf-httpbis-http2-10#section-5.1)
+// [Stream States](http://tools.ietf.org/html/draft-ietf-httpbis-http2-11#section-5.1)
 // ----------------
 //
 //                           +--------+
 //                     PP    |        |    PP
 //                  ,--------|  idle  |--------.
 //                 /         |        |         \
 //                v          +--------+          v
 //         +----------+          |           +----------+
@@ -374,27 +376,29 @@ function activeState(state) {
   return ((state === 'HALF_CLOSED_LOCAL') || (state === 'HALF_CLOSED_REMOTE') || (state === 'OPEN'));
 }
 
 // `_transition` is called every time there's an incoming or outgoing frame. It manages state
 // transitions, and detects stream errors. A stream error is always caused by a frame that is not
 // allowed in the current state.
 Stream.prototype._transition = function transition(sending, frame) {
   var receiving = !sending;
-  var error = undefined;
+  var connectionError;
+  var streamError;
 
-  var DATA = false, HEADERS = false, PRIORITY = false;
+  var DATA = false, HEADERS = false, PRIORITY = false, ALTSVC = false;
   var RST_STREAM = false, PUSH_PROMISE = false, WINDOW_UPDATE = false;
   switch(frame.type) {
     case 'DATA'         : DATA          = true; break;
     case 'HEADERS'      : HEADERS       = true; break;
     case 'PRIORITY'     : PRIORITY      = true; break;
     case 'RST_STREAM'   : RST_STREAM    = true; break;
     case 'PUSH_PROMISE' : PUSH_PROMISE  = true; break;
     case 'WINDOW_UPDATE': WINDOW_UPDATE = true; break;
+    case 'ALTSVC'       : ALTSVC        = true; break;
   }
 
   var previousState = this.state;
 
   switch (this.state) {
     // All streams start in the **idle** state. In this state, no frames have been exchanged.
     //
     // * Sending or receiving a HEADERS frame causes the stream to become "open".
@@ -405,17 +409,17 @@ Stream.prototype._transition = function 
         this._setState('OPEN');
         if (frame.flags.END_STREAM) {
           this._setState(sending ? 'HALF_CLOSED_LOCAL' : 'HALF_CLOSED_REMOTE');
         }
         this._initiated = sending;
       } else if (sending && RST_STREAM) {
         this._setState('CLOSED');
       } else {
-        error = 'PROTOCOL_ERROR';
+        connectionError = 'PROTOCOL_ERROR';
       }
       break;
 
     // A stream in the **reserved (local)** state is one that has been promised by sending a
     // PUSH_PROMISE frame.
     //
     // * The endpoint can send a HEADERS frame. This causes the stream to open in a "half closed
     //   (remote)" state.
@@ -426,17 +430,17 @@ Stream.prototype._transition = function 
     case 'RESERVED_LOCAL':
       if (sending && HEADERS) {
         this._setState('HALF_CLOSED_REMOTE');
       } else if (RST_STREAM) {
         this._setState('CLOSED');
       } else if (receiving && PRIORITY) {
         /* No state change */
       } else {
-        error = 'PROTOCOL_ERROR';
+        connectionError = 'PROTOCOL_ERROR';
       }
       break;
 
     // A stream in the **reserved (remote)** state has been reserved by a remote peer.
     //
     // * Either endpoint can send a RST_STREAM frame to cause the stream to become "closed". This
     //   releases the stream reservation.
     // * Receiving a HEADERS frame causes the stream to transition to "half closed (local)".
@@ -445,17 +449,17 @@ Stream.prototype._transition = function 
     case 'RESERVED_REMOTE':
       if (RST_STREAM) {
         this._setState('CLOSED');
       } else if (receiving && HEADERS) {
         this._setState('HALF_CLOSED_LOCAL');
       } else if (sending && PRIORITY) {
         /* No state change */
       } else {
-        error = 'PROTOCOL_ERROR';
+        connectionError = 'PROTOCOL_ERROR';
       }
       break;
 
     // The **open** state is where both peers can send frames. In this state, sending peers observe
     // advertised stream level flow control limits.
     //
     // * From this state either endpoint can send a frame with a END_STREAM flag set, which causes
     //   the stream to transition into one of the "half closed" states: an endpoint sending a
@@ -480,17 +484,17 @@ Stream.prototype._transition = function 
     // * An endpoint MAY send or receive PRIORITY frames in this state to reprioritize the stream.
     // * WINDOW_UPDATE can be sent by a peer that has sent a frame bearing the END_STREAM flag.
     case 'HALF_CLOSED_LOCAL':
       if (RST_STREAM || (receiving && frame.flags.END_STREAM)) {
         this._setState('CLOSED');
       } else if (receiving || (sending && (PRIORITY || WINDOW_UPDATE))) {
         /* No state change */
       } else {
-        error = 'PROTOCOL_ERROR';
+        connectionError = 'PROTOCOL_ERROR';
       }
       break;
 
     // A stream that is **half closed (remote)** is no longer being used by the peer to send frames.
     // In this state, an endpoint is no longer obligated to maintain a receiver flow control window
     // if it performs flow control.
     //
     // * If an endpoint receives additional frames for a stream that is in this state it MUST
@@ -500,17 +504,17 @@ Stream.prototype._transition = function 
     // * An endpoint MAY send or receive PRIORITY frames in this state to reprioritize the stream.
     // * A receiver MAY receive a WINDOW_UPDATE frame on a "half closed (remote)" stream.
     case 'HALF_CLOSED_REMOTE':
       if (RST_STREAM || (sending && frame.flags.END_STREAM)) {
         this._setState('CLOSED');
       } else if (sending || (receiving && (WINDOW_UPDATE || PRIORITY))) {
         /* No state change */
       } else {
-        error = 'PROTOCOL_ERROR';
+        connectionError = 'PROTOCOL_ERROR';
       }
       break;
 
     // The **closed** state is the terminal state.
     //
     // * An endpoint MUST NOT send frames on a closed stream. An endpoint that receives a frame
     //   after receiving a RST_STREAM or a frame containing a END_STREAM flag on that stream MUST
     //   treat that as a stream error of type STREAM_CLOSED.
@@ -527,20 +531,20 @@ Stream.prototype._transition = function 
     //   to limit the period over which it ignores frames and treat frames that arrive after this
     //   time as being in error.
     // * An endpoint might receive a PUSH_PROMISE frame after it sends RST_STREAM. PUSH_PROMISE
     //   causes a stream to become "reserved". If promised streams are not desired, a RST_STREAM
     //   can be used to close any of those streams.
     case 'CLOSED':
       if ((sending && RST_STREAM) ||
           (receiving && this._closedByUs &&
-           (this._closedWithRst || WINDOW_UPDATE || PRIORITY || RST_STREAM))) {
+           (this._closedWithRst || WINDOW_UPDATE || PRIORITY || RST_STREAM || ALTSVC))) {
         /* No state change */
       } else {
-        error = 'STREAM_CLOSED';
+        streamError = 'STREAM_CLOSED';
       }
       break;
   }
 
   // Noting that the connection was closed by the other endpoint. It may be important in edge cases.
   // For example, when the peer tries to cancel a promised stream, but we already sent every data
   // on it, then the stream is in CLOSED state, yet we want to ignore the incoming RST_STREAM.
   if ((this.state === 'CLOSED') && (previousState !== 'CLOSED')) {
@@ -549,17 +553,17 @@ Stream.prototype._transition = function 
   }
 
   // Sending/receiving a PUSH_PROMISE
   //
   // * Sending a PUSH_PROMISE frame marks the associated stream for later use. The stream state
   //   for the reserved stream transitions to "reserved (local)".
   // * Receiving a PUSH_PROMISE frame marks the associated stream as reserved by the remote peer.
   //   The state of the stream becomes "reserved (remote)".
-  if (PUSH_PROMISE && !error) {
+  if (PUSH_PROMISE && !connectionError && !streamError) {
     /* This assertion must hold, because _transition is called immediately when a frame is written
        to the stream. If it would be called when a frame gets out of the input queue, the state
        of the reserved could have been changed by then. */
     assert(frame.promised_stream.state === 'IDLE', frame.promised_stream.state);
     frame.promised_stream._setState(sending ? 'RESERVED_LOCAL' : 'RESERVED_REMOTE');
     frame.promised_stream._initiated = sending;
   }
 
@@ -571,36 +575,43 @@ Stream.prototype._transition = function 
     } else {
       frame.count_change(change);
     }
   } else if (sending) {
     frame.count_change = 0;
   }
 
   // Common error handling.
-  if (error) {
+  if (connectionError || streamError) {
     var info = {
-      error: error,
+      error: connectionError,
       frame: frame,
       state: this.state,
       closedByUs: this._closedByUs,
       closedWithRst: this._closedWithRst
     };
 
     // * When sending something invalid, throwing an exception, since it is probably a bug.
     if (sending) {
       this._log.error(info, 'Sending illegal frame.');
       throw new Error('Sending illegal frame (' + frame.type + ') in ' + this.state + ' state.');
     }
 
+    // * In case of a serious problem, emitting and error and letting someone else handle it
+    //   (e.g. closing the connection)
     // * When receiving something invalid, sending an RST_STREAM using the `reset` method.
     //   This will automatically cause a transition to the CLOSED state.
     else {
       this._log.error(info, 'Received illegal frame.');
-      this.emit('error', error);
+      if (connectionError) {
+        this.emit('connectionError', connectionError);
+      } else {
+        this.reset(streamError);
+        this.emit('error', streamError)
+      }
     }
   }
 };
 
 // Bunyan serializers
 // ------------------
 
 exports.serializers = {};
--- a/testing/xpcshell/node-http2/node_modules/http2-protocol/package.json
+++ b/testing/xpcshell/node-http2/node_modules/http2-protocol/package.json
@@ -1,11 +1,11 @@
 {
   "name": "http2-protocol",
-  "version": "0.10.0",
+  "version": "0.11.0",
   "description": "A JavaScript implementation of the HTTP/2 framing layer",
   "main": "lib/index.js",
   "engines" : {
     "node" : "0.10.x"
   },
   "devDependencies": {
     "istanbul": "*",
     "chai": "*",
@@ -29,13 +29,14 @@
     "http",
     "http2",
     "client",
     "server"
   ],
   "author": "Gábor Molnár <gabor@molnar.es> (http://gabor.molnar.es)",
   "contributors": [
     "Nick Hurley",
-    "Mike Belshe"
+    "Mike Belshe",
+    "vsemogutor"
   ],
   "license": "MIT",
   "readmeFilename": "README.md"
 }
--- a/testing/xpcshell/node-http2/node_modules/http2-protocol/test/compressor.js
+++ b/testing/xpcshell/node-http2/node_modules/http2-protocol/test/compressor.js
@@ -24,190 +24,288 @@ var test_integers = [{
 }, {
   N: 0,
   I: 1337,
   buffer: new Buffer([128 + 57, 10])
 }];
 
 var test_strings = [{
   string: 'www.foo.com',
-  buffer: new Buffer('88db6d898b5a44b74f', 'hex')
+  buffer: new Buffer('89e7cf9bfc1ad7d4db7f', 'hex')
 }, {
   string: 'éáűőúöüó€',
-  buffer: new Buffer('13C3A9C3A1C5B1C591C3BAC3B6C3BCC3B3E282AC', 'hex')
+  buffer: new Buffer('13c3a9c3a1c5b1c591c3bac3b6c3bcc3b3e282ac', 'hex')
 }];
 
 test_huffman_request = {
-  'GET': 'f77778ff',
-  'http': 'ce3177',
-  '/': '0f',
-  'www.foo.com': 'db6d898b5a44b74f',
-  'https': 'ce31743f',
-  'www.bar.com': 'db6d897a1e44b74f',
-  'no-cache': '63654a1398ff',
-  '/custom-path.css': '04eb08b7495c88e644c21f',
-  'custom-key': '4eb08b749790fa7f',
-  'custom-value': '4eb08b74979a17a8ff'
+  'GET': 'd5df47',
+  'http': 'adcebf',
+  '/': '3f',
+  'www.foo.com': 'e7cf9bfc1ad7d4db7f',
+  'https': 'adcebf1f',
+  'www.bar.com': 'e7cf9bfbd383ea6dbf',
+  'no-cache': 'b9b9949556bf',
+  '/custom-path.css': '3ab8e2e6db9af4bab7d58e3f',
+  'custom-key': '571c5cdb737b2faf',
+  'custom-value': '571c5cdb73724d9c57'
 };
 
 test_huffman_response = {
-  '302': '98a7',
-  'private': '73d5cd111f',
-  'Mon, 21 OCt 2013 20:13:21 GMT': 'ef6b3a7a0e6e8fa7647a0e534dd072fb0d37b0e6e8f777f8ff',
-  ': https://www.bar.com': 'f6746718ba1ec00db6d897a1e44b74',
-  '200': '394b',
-  'Mon, 21 OCt 2013 20:13:22 GMT': 'ef6b3a7a0e6e8fa7647a0e534dd072fb0d37b0e7e8f777f8ff',
-  'https://www.bar.com': 'ce31743d801b6db12f43c896e9',
-  'gzip': 'cbd54e',
+  '302': '4017',
+  'private': 'bf06724b97',
+  'Mon, 21 OCt 2013 20:13:21 GMT': 'd6dbb29884de3dce3100a0c4130a262136ad747f',
+  ': https://www.bar.com': '98d5b9d7e331cfcf9f37f7a707d4db7f',
+  '200': '200f',
+  'Mon, 21 OCt 2013 20:13:22 GMT': 'd6dbb29884de3dce3100a0c4130a262236ad747f',
+  'https://www.bar.com': 'adcebf198e7e7cf9bfbd383ea6db',
+  'gzip': 'abdd97ff',
   'foo=AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\
 AAAAAAAAAAAAAAAAAAAAAAAAAALASDJKHQKBZXOQWEOPIUAXQWEOIUAXLJKHQWOEIUAL\
 QWEOIUAXLQEUAXLLKJASDQWEOUIAXN1234LASDJKHQKBZXOQWEOPIUAXQWEOIUAXLJKH\
 QWOEIUALQWEOIUAXLQEUAXLLKJASDQWEOUIAXN1234LASDJKHQKBZXOQWEOPIUAXQWEO\
 IUAXLJKHQWOEIUALQWEOIUAXLQEUAXLLKJASDQWEOUIAXN1234LASDJKHQKBZXOQWEOP\
 IUAXQWEOIUAXLJKHQWOEIUALQWEOIUAXLQEUAXLLKJASDQWEOUIAXN1234ZZZZZZZZZZ\
 ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ1234 m\
-ax-age=3600; version=1': 'c5adb77efdfbf7efdfbf7efdfbf7efdfbf7efdfbf7\
-efdfbf7efdfbf7efdfbf7efdfbf7efdfbf7efdfbf7efdfbf7efdfbf7efdfbf7efdfb\
-f7efdfbf7efdfbf7efdfbfe5bfc3b7e3fdfbfedfdf5ff9fbfa7dbf5ddf4fafc3f1bf\
-f7f6fd777d3e1f8dffbf97c7fbf7fdbf5f4eef87e37fcbedfaeefa7c3f1bff7f2fb7\
-77e37fefe5f2fefe3bfc3b7edfaeefa7e3e1bff7f331e69fe5bfc3b7e3fdfbfedfdf\
-5ff9fbfa7dbf5ddf4fafc3f1bff7f6fd777d3e1f8dffbf97c7fbf7fdbf5f4eef87e3\
-7fcbedfaeefa7c3f1bff7f2fb777e37fefe5f2fefe3bfc3b7edfaeefa7e3e1bff7f3\
-31e69fe5bfc3b7e3fdfbfedfdf5ff9fbfa7dbf5ddf4fafc3f1bff7f6fd777d3e1f8d\
-ffbf97c7fbf7fdbf5f4eef87e37fcbedfaeefa7c3f1bff7f2fb777e37fefe5f2fefe\
-3bfc3b7edfaeefa7e3e1bff7f331e69fe5bfc3b7e3fdfbfedfdf5ff9fbfa7dbf5ddf\
-4fafc3f1bff7f6fd777d3e1f8dffbf97c7fbf7fdbf5f4eef87e37fcbedfaeefa7c3f\
-1bff7f2fb777e37fefe5f2fefe3bfc3b7edfaeefa7e3e1bff7f331e69ffcff3fcff3\
-fcff3fcff3fcff3fcff3fcff3fcff3fcff3fcff3fcff3fcff3fcff3fcff3fcff3fcf\
-f3fcff3fcff3fcff3fcff3fcff3fcff3fcff3fcff3fcff3fcff3fcff3fcff3fcff3f\
-cff3fcff3fcff3fcff3fcff3fcff3fcff0c79a7e8d11e72a321b66a4a5eae8e62f82\
-9acb4d',
+ax-age=3600; version=1': 'e0d6cf9f3e7cf9f3e7cf9f3e7cf9f3e7cf9f3e7cf9f3e7cf9f3e7cf9f3e7cf9f3e7cf9f3e7cf9f3e7cf9f3e7cf9f3e7cf9f3e7cf9f3e7cf9f3e7cf9f3e7cf9f3e7cff5cfb747cfe9f2fb7d3b7f7e9e3f6fcf7f8f97879e7f4fb7e7bfc7c3cf3fa7d7e7f4f97dbf3e3dfe1e79febf6fcf7f8f879e7f4fafdbbfcf3fa7d7ebf4f9e7dba3edf9eff1f3f0cfe9b049107d73edd1f3fa7cbedf4edfdfa78fdbf3dfe3e5e1e79fd3edf9eff1f0f3cfe9f5f9fd3e5f6fcf8f7f879e7fafdbf3dfe3e1e79fd3ebf6eff3cfe9f5fafd3e79f6e8fb7e7bfc7cfc33fa6c12441f5cfb747cfe9f2fb7d3b7f7e9e3f6fcf7f8f97879e7f4fb7e7bfc7c3cf3fa7d7e7f4f97dbf3e3dfe1e79febf6fcf7f8f879e7f4fafdbbfcf3fa7d7ebf4f9e7dba3edf9eff1f3f0cfe9b049107d73edd1f3fa7cbedf4edfdfa78fdbf3dfe3e5e1e79fd3edf9eff1f0f3cfe9f5f9fd3e5f6fcf8f7f879e7fafdbf3dfe3e1e79fd3ebf6eff3cfe9f5fafd3e79f6e8fb7e7bfc7cfc33fa6c12441fbfdfeff7fbfdfeff7fbfdfeff7fbfdfeff7fbfdfeff7fbfdfeff7fbfdfeff7fbfdfeff7fbfdfeff7fbfdfeff7fbfdfeff7fbfdfeff7fbfdfeff7fbfdfeff7fbfdfeff7fbfdfeff7fbfdfeff7fbfdfeff624880d6a7a664d4b9d1100761b92f0c58dba71',
   'foo=ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ\
 ZZZZZZZZZZZZZZZZZZZZZZZZZZLASDJKHQKBZXOQWEOPIUAXQWEOIUAXLJKHQWOEIUAL\
 QWEOIUAXLQEUAXLLKJASDQWEOUIAXN1234LASDJKHQKBZXOQWEOPIUAXQWEOIUAXLJKH\
 QWOEIUALQWEOIUAXLQEUAXLLKJASDQWEOUIAXN1234LASDJKHQKBZXOQWEOPIUAXQWEO\
 IUAXLJKHQWOEIUALQWEOIUAXLQEUAXLLKJASDQWEOUIAXN1234LASDJKHQKBZXOQWEOP\
 IUAXQWEOIUAXLJKHQWOEIUALQWEOIUAXLQEUAXLLKJASDQWEOUIAXN1234AAAAAAAAAA\
 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA1234 m\
-ax-age=3600; version=1': 'c5adb7fcff3fcff3fcff3fcff3fcff3fcff3fcff3f\
-cff3fcff3fcff3fcff3fcff3fcff3fcff3fcff3fcff3fcff3fcff3fcff3fcff3fcff\
-3fcff3fcff3fcff3fcff3fcff3fcff3fcff3fcff3fcff3fcff3fcff3fcff3fcff3fc\
-ff3fcff3e5bfc3b7e3fdfbfedfdf5ff9fbfa7dbf5ddf4fafc3f1bff7f6fd777d3e1f\
-8dffbf97c7fbf7fdbf5f4eef87e37fcbedfaeefa7c3f1bff7f2fb777e37fefe5f2fe\
-fe3bfc3b7edfaeefa7e3e1bff7f331e69fe5bfc3b7e3fdfbfedfdf5ff9fbfa7dbf5d\
-df4fafc3f1bff7f6fd777d3e1f8dffbf97c7fbf7fdbf5f4eef87e37fcbedfaeefa7c\
-3f1bff7f2fb777e37fefe5f2fefe3bfc3b7edfaeefa7e3e1bff7f331e69fe5bfc3b7\
-e3fdfbfedfdf5ff9fbfa7dbf5ddf4fafc3f1bff7f6fd777d3e1f8dffbf97c7fbf7fd\
-bf5f4eef87e37fcbedfaeefa7c3f1bff7f2fb777e37fefe5f2fefe3bfc3b7edfaeef\
-a7e3e1bff7f331e69fe5bfc3b7e3fdfbfedfdf5ff9fbfa7dbf5ddf4fafc3f1bff7f6\
-fd777d3e1f8dffbf97c7fbf7fdbf5f4eef87e37fcbedfaeefa7c3f1bff7f2fb777e3\
-7fefe5f2fefe3bfc3b7edfaeefa7e3e1bff7f331e69f7efdfbf7efdfbf7efdfbf7ef\
-dfbf7efdfbf7efdfbf7efdfbf7efdfbf7efdfbf7efdfbf7efdfbf7efdfbf7efdfbf7\
-efdfbf7efdfbf7efdfbf7efdfbf7efdfbcc79a7e8d11e72a321b66a4a5eae8e62f82\
-9acb4d'
+ax-age=3600; version=1': 'e0d6cffbfdfeff7fbfdfeff7fbfdfeff7fbfdfeff7fbfdfeff7fbfdfeff7fbfdfeff7fbfdfeff7fbfdfeff7fbfdfeff7fbfdfeff7fbfdfeff7fbfdfeff7fbfdfeff7fbfdfeff7fbfdfeff7fbfdfeff7fbfdfeff7f5cfb747cfe9f2fb7d3b7f7e9e3f6fcf7f8f97879e7f4fb7e7bfc7c3cf3fa7d7e7f4f97dbf3e3dfe1e79febf6fcf7f8f879e7f4fafdbbfcf3fa7d7ebf4f9e7dba3edf9eff1f3f0cfe9b049107d73edd1f3fa7cbedf4edfdfa78fdbf3dfe3e5e1e79fd3edf9eff1f0f3cfe9f5f9fd3e5f6fcf8f7f879e7fafdbf3dfe3e1e79fd3ebf6eff3cfe9f5fafd3e79f6e8fb7e7bfc7cfc33fa6c12441f5cfb747cfe9f2fb7d3b7f7e9e3f6fcf7f8f97879e7f4fb7e7bfc7c3cf3fa7d7e7f4f97dbf3e3dfe1e79febf6fcf7f8f879e7f4fafdbbfcf3fa7d7ebf4f9e7dba3edf9eff1f3f0cfe9b049107d73edd1f3fa7cbedf4edfdfa78fdbf3dfe3e5e1e79fd3edf9eff1f0f3cfe9f5f9fd3e5f6fcf8f7f879e7fafdbf3dfe3e1e79fd3ebf6eff3cfe9f5fafd3e79f6e8fb7e7bfc7cfc33fa6c124419f3e7cf9f3e7cf9f3e7cf9f3e7cf9f3e7cf9f3e7cf9f3e7cf9f3e7cf9f3e7cf9f3e7cf9f3e7cf9f3e7cf9f3e7cf9f3e7cf9f3e7cf9f3e7cf9f3e7cf9f3e7ce24880d6a7a664d4b9d1100761b92f0c58dba71'
 };
 
 var test_headers = [{
+  // literal w/index, name index
   header: {
     name: 1,
     value: 'GET',
-    index: true
+    index: true,
+    mustNeverIndex: false,
+    contextUpdate: false,
+    clearReferenceSet: false,
+    newMaxSize: 0
   },
-  buffer: new Buffer('02' + '03474554', 'hex')
+  buffer: new Buffer('42' + '03474554', 'hex')
 }, {
+  // literal w/index, name index
   header: {
     name: 6,
     value: 'http',
-    index: true
+    index: true,
+    mustNeverIndex: false,
+    contextUpdate: false,
+    clearReferenceSet: false,
+    newMaxSize: 0
   },
-  buffer: new Buffer('07' + '83ce3177', 'hex')
+  buffer: new Buffer('47' + '83ADCEBF', 'hex')
 }, {
+  // literal w/index, name index
   header: {
     name: 5,
     value: '/',
-    index: true
+    index: true,
+    mustNeverIndex: false,
+    contextUpdate: false,
+    clearReferenceSet: false,
+    newMaxSize: 0
   },
-  buffer: new Buffer('06' + '012f', 'hex')
+  buffer: new Buffer('46' + '012F', 'hex')
 }, {
+  // literal w/index, name index
   header: {
     name: 3,
     value: 'www.foo.com',
-    index: true
+    index: true,
+    mustNeverIndex: false,
+    contextUpdate: false,
+    clearReferenceSet: false,
+    newMaxSize: 0
   },
-  buffer: new Buffer('04' + '88db6d898b5a44b74f', 'hex')
+  buffer: new Buffer('44' + '89E7CF9BFC1AD7D4DB7F', 'hex')
 }, {
+  // literal w/index, name index
   header: {
     name: 2,
     value: 'https',
-    index: true
+    index: true,
+    mustNeverIndex: false,
+    contextUpdate: false,
+    clearReferenceSet: false,
+    newMaxSize: 0
   },
-  buffer: new Buffer('03' + '84ce31743f', 'hex')
+  buffer: new Buffer('43' + '84ADCEBF1F', 'hex')
 }, {
+  // literal w/index, name index
   header: {
     name: 1,
     value: 'www.bar.com',
-    index: true
+    index: true,
+    mustNeverIndex: false,
+    contextUpdate: false,
+    clearReferenceSet: false,
+    newMaxSize: 0
   },
-  buffer: new Buffer('02' + '88db6d897a1e44b74f', 'hex')
+  buffer: new Buffer('42' + '89E7CF9BFBD383EA6DBF', 'hex')
 }, {
+  // literal w/index, name index
   header: {
-    name: 28,
+    name: 29,
     value: 'no-cache',
-    index: true
+    index: true,
+    mustNeverIndex: false,
+    contextUpdate: false,
+    clearReferenceSet: false,
+    newMaxSize: 0
   },
-  buffer: new Buffer('1d' + '8663654a1398ff', 'hex')
+  buffer: new Buffer('5e' + '86B9B9949556BF', 'hex')
 }, {
+  // indexed
   header: {
     name: 3,
     value: 3,
-    index: false
+    index: false,
+    mustNeverIndex: false,
+    contextUpdate: false,
+    clearReferenceSet: false,
+    newMaxSize: 0
   },
   buffer: new Buffer('84', 'hex')
 }, {
+  // indexed
   header: {
     name: 5,
     value: 5,
-    index: false
+    index: false,
+    mustNeverIndex: false,
+    contextUpdate: false,
+    clearReferenceSet: false,
+    newMaxSize: 0
   },
   buffer: new Buffer('86', 'hex')
 }, {
+  // literal w/index, name index
   header: {
     name: 4,
     value: '/custom-path.css',
-    index: true
+    index: true,
+    mustNeverIndex: false,
+    contextUpdate: false,
+    clearReferenceSet: false,
+    newMaxSize: 0
   },
-  buffer: new Buffer('05' + '8b04eb08b7495c88e644c21f', 'hex')
+  buffer: new Buffer('45' + '8C3AB8E2E6DB9AF4BAB7D58E3F', 'hex')
 }, {
+  // literal w/index, new name & value
   header: {
     name: 'custom-key',
     value: 'custom-value',
-    index: true
+    index: true,
+    mustNeverIndex: false,
+    contextUpdate: false,
+    clearReferenceSet: false,
+    newMaxSize: 0
   },
-  buffer: new Buffer('00' + '884eb08b749790fa7f' + '894eb08b74979a17a8ff', 'hex')
+  buffer: new Buffer('40' + '88571C5CDB737B2FAF' + '89571C5CDB73724D9C57', 'hex')
 }, {
+  // indexed
   header: {
     name: 2,
     value: 2,
-    index: false
+    index: false,
+    mustNeverIndex: false,
+    contextUpdate: false,
+    clearReferenceSet: false,
+    newMaxSize: 0
   },
   buffer: new Buffer('83', 'hex')
 }, {
+  // indexed
   header: {
     name: 6,
     value: 6,
-    index: false
+    index: false,
+    mustNeverIndex: false,
+    contextUpdate: false,
+    clearReferenceSet: false,
+    newMaxSize: 0
   },
   buffer: new Buffer('87', 'hex')
 }, {
+  // Literal w/o index, name index
+  header: {
+    name: 6,
+    value: "whatever",
+    index: false,
+    mustNeverIndex: false,
+    contextUpdate: false,
+    clearReferenceSet: false,
+    newMaxSize: 0
+  },
+  buffer: new Buffer('07' + '86E75A5CBE4BC3', 'hex')
+}, {
+  // Literal w/o index, new name & value
+  header: {
+    name: "foo",
+    value: "bar",
+    index: false,
+    mustNeverIndex: false,
+    contextUpdate: false,
+    clearReferenceSet: false,
+    newMaxSize: 0
+  },
+  buffer: new Buffer('00' + '03666F6F' + '03626172', 'hex')
+}, {
+  // Literal never indexed, name index
+  header: {
+    name: 6,
+    value: "whatever",
+    index: false,
+    mustNeverIndex: true,
+    contextUpdate: false,
+    clearReferenceSet: false,
+    newMaxSize: 0
+  },
+  buffer: new Buffer('17' + '86E75A5CBE4BC3', 'hex')
+}, {
+  // Literal never indexed, new name & value
+  header: {
+    name: "foo",
+    value: "bar",
+    index: false,
+    mustNeverIndex: true,
+    contextUpdate: false,
+    clearReferenceSet: false,
+    newMaxSize: 0
+  },
+  buffer: new Buffer('10' + '03666F6F' + '03626172', 'hex')
+}, {
   header: {
     name: -1,
     value: -1,
-    index: true
+    index: false,
+    mustNeverIndex: false,
+    contextUpdate: true,
+    clearReferenceSet: true,
+    newMaxSize: 0
   },
-  buffer: new Buffer('8080', 'hex')
+  buffer: new Buffer('30', 'hex')
+}, {
+  header: {
+    name: -1,
+    value: -1,
+    index: false,
+    mustNeverIndex: false,
+    contextUpdate: true,
+    clearReferenceSet: false,
+    newMaxSize: 100
+  },
+  buffer: new Buffer('2F55', 'hex')
 }];
 
 var test_header_sets = [{
   headers: {
     ':method': 'GET',
     ':scheme': 'http',
     ':path': '/',
     ':authority': 'www.foo.com'
@@ -236,19 +334,16 @@ var test_header_sets = [{
     ':method': 'GET',
     ':scheme': 'https',
     ':path': '/custom-path.css',
     ':authority': ['www.foo.com', 'www.bar.com'],
     'custom-key': 'custom-value'
   },
   buffer: test_headers[3].buffer
 }, {
-  headers: {},
-  buffer: test_headers[13].buffer
-}, {
   headers: {
     ':status': '200',
     'user-agent': 'my-user-agent',
     'cookie': 'first; second; third; third; fourth',
     'multiple': ['first', 'second', 'third', 'third; fourth'],
     'verylong': (new Buffer(9000)).toString('hex')
   }
 }];
@@ -351,17 +446,17 @@ describe('compressor.js', function() {
         }
       });
     });
   });
   describe('Decompressor', function() {
     describe('method decompress(buffer)', function() {
       it('should return the parsed header set in { name1: value1, name2: [value2, value3], ... } format', function() {
         var decompressor = new Decompressor(util.log, 'REQUEST');
-        for (var i = 0; i < 5; i++) {
+        for (var i = 0; i < test_header_sets.length - 1; i++) {
           var header_set = test_header_sets[i];
           expect(decompressor.decompress(header_set.buffer)).to.deep.equal(header_set.headers);
         }
       });
     });
     describe('transform stream', function() {
       it('should emit an error event if a series of header frames is interleaved with other frames', function() {
         var decompressor = new Decompressor(util.log, 'REQUEST');
--- a/testing/xpcshell/node-http2/node_modules/http2-protocol/test/framer.js
+++ b/testing/xpcshell/node-http2/node_modules/http2-protocol/test/framer.js
@@ -2,71 +2,131 @@ var expect = require('chai').expect;
 var util = require('./util');
 
 var framer = require('../lib/framer');
 var Serializer = framer.Serializer;
 var Deserializer = framer.Deserializer;
 
 var frame_types = {
   DATA:          ['data'],
-  HEADERS:       ['priority', 'data'],
-  PRIORITY:      ['priority'],
+  HEADERS:       ['priority_information', 'data'],
+  PRIORITY:      ['priority_information'],
   RST_STREAM:    ['error'],
   SETTINGS:      ['settings'],
   PUSH_PROMISE:  ['promised_stream', 'data'],
   PING:          ['data'],
   GOAWAY:        ['last_stream', 'error'],
   WINDOW_UPDATE: ['window_size'],
   CONTINUATION:  ['data']
 };
 
 var test_frames = [{
   frame: {
     type: 'DATA',
     flags: { END_STREAM: false, END_SEGMENT: false, RESERVED4: false,
-             RESERVED8: false, PAD_LOW: false, PAD_HIGH: false },
+             PAD_LOW: false, PAD_HIGH: false },
     stream: 10,
 
     data: new Buffer('12345678', 'hex')
   },
   // length + type + flags + stream +   content
   buffer: new Buffer('0004' + '00' + '00' + '0000000A' +   '12345678', 'hex')
 
 }, {
   frame: {
     type: 'HEADERS',
     flags: { END_STREAM: false, END_SEGMENT: false, END_HEADERS: false,
-             PRIORITY: false, PAD_LOW: false, PAD_HIGH: false },
+             PAD_LOW: false, PAD_HIGH: false, PRIORITY_GROUP: false,
+             PRIORITY_DEPENDENCY: false },
     stream: 15,
 
     data: new Buffer('12345678', 'hex')
   },
   buffer: new Buffer('0004' + '01' + '00' + '0000000F' +   '12345678', 'hex')
 
 }, {
   frame: {
     type: 'HEADERS',
     flags: { END_STREAM: false, END_SEGMENT: false, END_HEADERS: false,
-             PRIORITY: true, PAD_LOW: false, PAD_HIGH: false },
+             PAD_LOW: false, PAD_HIGH: false, PRIORITY_GROUP: true,
+             PRIORITY_DEPENDENCY: false },
     stream: 15,
+    priorityGroup: 23,
+    groupWeight: 5,
 
-    priority: 3,
     data: new Buffer('12345678', 'hex')
   },
-  buffer: new Buffer('0008' + '01' + '08' + '0000000F' +   '00000003' + '12345678', 'hex')
+  buffer: new Buffer('0009' + '01' + '20' + '0000000F' + '00000017' + '05' + '12345678', 'hex')
+
+}, {
+  frame: {
+    type: 'HEADERS',
+    flags: { END_STREAM: false, END_SEGMENT: false, END_HEADERS: false,
+             PAD_LOW: false, PAD_HIGH: false, PRIORITY_GROUP: false,
+             PRIORITY_DEPENDENCY: true },
+    stream: 15,
+    priorityDependency: 23,
+    exclusiveDependency: false,
+
+    data: new Buffer('12345678', 'hex')
+  },
+  buffer: new Buffer('0008' + '01' + '40' + '0000000F' + '00000017' + '12345678', 'hex')
+
+}, {
+  frame: {
+    type: 'HEADERS',
+    flags: { END_STREAM: false, END_SEGMENT: false, END_HEADERS: false,
+             PAD_LOW: false, PAD_HIGH: false, PRIORITY_GROUP: false,
+             PRIORITY_DEPENDENCY: true },
+    stream: 15,
+    priorityDependency: 23,
+    exclusiveDependency: true,
+
+    data: new Buffer('12345678', 'hex')
+  },
+  buffer: new Buffer('0008' + '01' + '40' + '0000000F' + '80000017' + '12345678', 'hex')
 
 }, {
   frame: {
     type: 'PRIORITY',
-    flags: { },
+    flags: { RESERVED1: false, RESERVED2: false, RESERVED4: false,
+             RESERVED8: false, RESERVED16: false, PRIORITY_GROUP: true,
+             PRIORITY_DEPENDENCY: false },
+    stream: 10,
+
+    priorityGroup: 23,
+    groupWeight: 5
+  },
+  buffer: new Buffer('0005' + '02' + '20' + '0000000A' + '00000017' + '05', 'hex')
+
+}, {
+  frame: {
+    type: 'PRIORITY',
+    flags: { RESERVED1: false, RESERVED2: false, RESERVED4: false,
+             RESERVED8: false, RESERVED16: false, PRIORITY_GROUP: false,
+             PRIORITY_DEPENDENCY: true },
     stream: 10,
 
-    priority: 3
+    priorityDependency: 23,
+    exclusiveDependency: false
   },
-  buffer: new Buffer('0004' + '02' + '00' + '0000000A' +   '00000003', 'hex')
+  buffer: new Buffer('0004' + '02' + '40' + '0000000A' + '00000017', 'hex')
+
+}, {
+  frame: {
+    type: 'PRIORITY',
+    flags: { RESERVED1: false, RESERVED2: false, RESERVED4: false,
+             RESERVED8: false, RESERVED16: false, PRIORITY_GROUP: false,
+             PRIORITY_DEPENDENCY: true },
+    stream: 10,
+
+    priorityDependency: 23,
+    exclusiveDependency: true
+  },
+  buffer: new Buffer('0004' + '02' + '40' + '0000000A' + '80000017', 'hex')
 
 }, {
   frame: {
     type: 'RST_STREAM',
     flags: { },
     stream: 10,
 
     error: 'INTERNAL_ERROR'
@@ -89,17 +149,18 @@ var test_frames = [{
   buffer: new Buffer('0014' + '04' + '00' + '0000000A' +   '01' + '12345678' +
                                                            '02' + '00000001' +
                                                            '03' + '01234567' +
                                                            '04' + '89ABCDEF', 'hex')
 
 }, {
   frame: {
     type: 'PUSH_PROMISE',
-    flags: { RESERVED1: false, RESERVED2: false, END_PUSH_PROMISE: false },
+    flags: { RESERVED1: false, RESERVED2: false, END_PUSH_PROMISE: false,
+             PAD_LOW: false, PAD_HIGH: false },
     stream: 15,
 
     promised_stream: 3,
     data: new Buffer('12345678', 'hex')
   },
   buffer: new Buffer('0008' + '05' + '00' + '0000000F' +   '00000003' + '12345678', 'hex')
 
 }, {
@@ -131,71 +192,145 @@ var test_frames = [{
 
     window_size: 0x12345678
   },
   buffer: new Buffer('0004' + '08' + '00' + '0000000A' +   '12345678', 'hex')
 }, {
   frame: {
     type: 'CONTINUATION',
     flags: { RESERVED1: false, RESERVED2: false, END_HEADERS: true,
-             RESERVED8: false, PAD_LOW: false, PAD_HIGH: false },
+             PAD_LOW: false, PAD_HIGH: false },
     stream: 10,
 
     data: new Buffer('12345678', 'hex')
   },
   // length + type + flags + stream +   content
   buffer: new Buffer('0004' + '09' + '04' + '0000000A' +   '12345678', 'hex')
+}, {
+  frame: {
+    type: 'ALTSVC',
+    flags: { },
+    stream: 0,
+
+    maxAge: 31536000,
+    port: 4443,
+    protocolID: "h2",
+    host: "altsvc.example.com",
+    origin: ""
+  },
+  buffer: new Buffer('001D' + '0A' + '00' + '00000000' + '01E13380' + '115B' + '00' + '02' + '6832' + '12' + '616C747376632E6578616D706C652E636F6D', 'hex')
+}, {
+  frame: {
+    type: 'ALTSVC',
+    flags: { },
+    stream: 0,
+
+    maxAge: 31536000,
+    port: 4443,
+    protocolID: "h2",
+    host: "altsvc.example.com",
+    origin: "https://onlyme.example.com"
+  },
+  buffer: new Buffer('0037' + '0A' + '00' + '00000000' + '01E13380' + '115B' + '00' + '02' + '6832' + '12' + '616C747376632E6578616D706C652E636F6D' + '68747470733A2F2F6F6E6C796D652E6578616D706C652E636F6D', 'hex')
 }];
 
 var deserializer_test_frames = test_frames.slice(0);
 var padded_test_frames = [{
   frame: {
     type: 'DATA',
     flags: { END_STREAM: false, END_SEGMENT: false, RESERVED4: false,
-             RESERVED8: false, PAD_LOW: true, PAD_HIGH: false },
+             PAD_LOW: true, PAD_HIGH: false },
     stream: 10,
     data: new Buffer('12345678', 'hex')
   },
   // length + type + flags + stream + pad_low control + content + padding
-  buffer: new Buffer('000B' + '00' + '10' + '0000000A' + '06' + '12345678' + '000000000000', 'hex')
+  buffer: new Buffer('000B' + '00' + '08' + '0000000A' + '06' + '12345678' + '000000000000', 'hex')
+
+}, {
+  frame: {
+    type: 'HEADERS',
+    flags: { END_STREAM: false, END_SEGMENT: false, END_HEADERS: false,
+             PAD_LOW: true, PAD_HIGH: false, PRIORITY_GROUP: false,
+             PRIORITY_DEPENDENCY: false },
+    stream: 15,
+
+    data: new Buffer('12345678', 'hex')
+  },
+  // length + type + flags + stream + pad_low control + data + padding
+  buffer: new Buffer('000B' + '01' + '08' + '0000000F' + '06' + '12345678' + '000000000000', 'hex')
+
+}, {
+  frame: {
+    type: 'HEADERS',
+    flags: { END_STREAM: false, END_SEGMENT: false, END_HEADERS: false,
+             PAD_LOW: true, PAD_HIGH: false, PRIORITY_GROUP: true,
+             PRIORITY_DEPENDENCY: false },
+    stream: 15,
+    priorityGroup: 23,
+    groupWeight: 5,
+
+    data: new Buffer('12345678', 'hex')
+  },
+  // length + type + flags + stream + pad_low control + priority group + group weight + data + padding
+  buffer: new Buffer('0010' + '01' + '28' + '0000000F' + '06' + '00000017' + '05' + '12345678' + '000000000000', 'hex')
 
 }, {
   frame: {
     type: 'HEADERS',
     flags: { END_STREAM: false, END_SEGMENT: false, END_HEADERS: false,
-             PRIORITY: false, PAD_LOW: true, PAD_HIGH: false },
+             PAD_LOW: true, PAD_HIGH: false, PRIORITY_GROUP: false,
+             PRIORITY_DEPENDENCY: true },
     stream: 15,
+    priorityDependency: 23,
+    exclusiveDependency: false,
 
     data: new Buffer('12345678', 'hex')
   },
-  buffer: new Buffer('000B' + '01' + '10' + '0000000F' + '06' + '12345678' + '000000000000', 'hex')
+  // length + type + flags + stream + pad_low control + priority dependency + data + padding
+  buffer: new Buffer('000F' + '01' + '48' + '0000000F' + '06' + '00000017' + '12345678' + '000000000000', 'hex')
 
 }, {
   frame: {
     type: 'HEADERS',
     flags: { END_STREAM: false, END_SEGMENT: false, END_HEADERS: false,
-             PRIORITY: true, PAD_LOW: true, PAD_HIGH: false },
+             PAD_LOW: true, PAD_HIGH: false, PRIORITY_GROUP: false,
+             PRIORITY_DEPENDENCY: true },
     stream: 15,
+    priorityDependency: 23,
+    exclusiveDependency: true,
 
-    priority: 3,
     data: new Buffer('12345678', 'hex')
   },
-  buffer: new Buffer('000F' + '01' + '18' + '0000000F' + '06' + '00000003' + '12345678' + '000000000000', 'hex')
+  // length + type + flags + stream + pad_low control + priority dependency + data + padding
+  buffer: new Buffer('000F' + '01' + '48' + '0000000F' + '06' + '80000017' + '12345678' + '000000000000', 'hex')
 
 }, {
   frame: {
     type: 'CONTINUATION',
     flags: { RESERVED1: false, RESERVED2: false, END_HEADERS: true,
-             RESERVED8: false, PAD_LOW: true, PAD_HIGH: false },
+             PAD_LOW: true, PAD_HIGH: false },
     stream: 10,
 
     data: new Buffer('12345678', 'hex')
   },
-  // length + type + flags + stream +   content
-  buffer: new Buffer('000B' + '09' + '14' + '0000000A' + '06' + '12345678' + '000000000000', 'hex')
+  // length + type + flags + stream + pad_low control + data + padding
+  buffer: new Buffer('000B' + '09' + '0C' + '0000000A' + '06' + '12345678' + '000000000000', 'hex')
+}, {
+  frame: {
+    type: 'PUSH_PROMISE',
+    flags: { RESERVED1: false, RESERVED2: false, END_PUSH_PROMISE: false,
+             PAD_LOW: true, PAD_HIGH: false },
+    stream: 15,
+
+    promised_stream: 3,
+    data: new Buffer('12345678', 'hex')
+  },
+  // length + type + flags + stream + pad_low control + promised stream + data + padding
+  buffer: new Buffer('000F' + '05' + '08' + '0000000F' + '06' + '00000003' + '12345678' + '000000000000', 'hex')
+
 }];
 for (var idx = 0; idx < padded_test_frames.length; idx++) {
   deserializer_test_frames.push(padded_test_frames[idx]);
 }
 
 
 describe('framer.js', function() {
   describe('Serializer', function() {
--- a/testing/xpcshell/node-http2/node_modules/http2-protocol/test/stream.js
+++ b/testing/xpcshell/node-http2/node_modules/http2-protocol/test/stream.js
@@ -179,18 +179,21 @@ var invalid_outgoing_frames = {
 
 describe('stream.js', function() {
   describe('Stream class', function() {
     describe('._transition(sending, frame) method', function() {
       it('should emit error, and answer RST_STREAM for invalid incoming frames', function() {
         Object.keys(invalid_incoming_frames).forEach(function(state) {
           invalid_incoming_frames[state].forEach(function(invalid_frame) {
             var stream = createStream();
+            var connectionErrorHappened = false
             stream.state = state;
-            expect(stream._transition.bind(stream, false, invalid_frame)).to.throw('Uncaught, unspecified "error" event.');
+            stream.once('connectionError', function() { connectionErrorHappened = true; });
+            stream._transition(false, invalid_frame)
+            expect(connectionErrorHappened)
           });
         });
 
         // CLOSED state as a result of incoming END_STREAM (or RST_STREAM)
         var stream = createStream();
         stream.headers({});
         stream.end();
         stream.upstream.write({ type: 'HEADERS', headers:{}, flags: { END_STREAM: true }, count_change: util.noop });
--- a/testing/xpcshell/node-http2/package.json
+++ b/testing/xpcshell/node-http2/package.json
@@ -2,17 +2,17 @@
   "name": "http2",
   "version": "2.3.0",
   "description": "An HTTP/2 client and server implementation",
   "main": "lib/index.js",
   "engines" : {
     "node" : ">=0.10.19"
   },
   "dependencies": {
-    "http2-protocol": "0.10.x"
+    "http2-protocol": "0.11.x"
   },
   "devDependencies": {
     "istanbul": "*",
     "chai": "*",
     "mocha": "*",
     "docco": "*",
     "bunyan": "*"
   },
@@ -32,13 +32,14 @@
     "http",
     "http2",
     "client",
     "server"
   ],
   "author": "Gábor Molnár <gabor@molnar.es> (http://gabor.molnar.es)",
   "contributors": [
     "Nick Hurley",
-    "Mike Belshe"
+    "Mike Belshe",
+    "Yoshihiro Iwanaga"
   ],
   "license": "MIT",
   "readmeFilename": "README.md"
 }