BearND has uploaded a new change for review.

  https://gerrit.wikimedia.org/r/316422

Change subject: Update mobileapps to 13fa4b4
......................................................................

Update mobileapps to 13fa4b4

List of changes:
632e51a Add more languages to news feed
744ff8e Simplify en:TFA retrieval
5dc987e Mark reference sections with isReferenceSection flag
2c9bf67 Expose references in a new endpoint
071659b Do not relocate first paragraph in new endpoint
c597c19 Hygiene: Make adjustMemberKeys and fillInMemberKeys variadic
a33a6b4 Update to service-template-node v0.4.1
xxxxxxx Update node module dependencies

Change-Id: I507d538446d786d6e8a4c201daab85f992f76049
---
M 
node_modules/bunyan/node_modules/mv/node_modules/rimraf/node_modules/glob/node_modules/inflight/inflight.js
M 
node_modules/bunyan/node_modules/mv/node_modules/rimraf/node_modules/glob/node_modules/inflight/package.json
M node_modules/domino/lib/DOMTokenList.js
M node_modules/domino/lib/Document.js
M node_modules/domino/lib/Element.js
M node_modules/domino/lib/HTMLParser.js
M node_modules/domino/lib/impl.js
M node_modules/domino/package.json
M node_modules/domino/test/htmlwg/harness/index.js
M 
node_modules/domino/test/htmlwg/submission/Ms2ger/dom-tree-accessors/document.title-06.html
M 
node_modules/domino/test/htmlwg/submission/Ms2ger/global-attributes/document-dir.html
A node_modules/domino/test/htmlwg/submission/Ms2ger/node/Element-closest.html
M node_modules/domino/test/w3c/harness/index.js
M node_modules/domino/test/w3c/level1/html/HTMLLabelElement01.js
M node_modules/preq/index.js
M node_modules/preq/node_modules/request/node_modules/aws4/aws4.js
M node_modules/preq/node_modules/request/node_modules/aws4/package.json
M node_modules/preq/package.json
M 
node_modules/service-runner/node_modules/limitation/node_modules/kad/package.json
M src
20 files changed, 333 insertions(+), 142 deletions(-)


  git pull 
ssh://gerrit.wikimedia.org:29418/mediawiki/services/mobileapps/deploy 
refs/changes/22/316422/1

diff --git 
a/node_modules/bunyan/node_modules/mv/node_modules/rimraf/node_modules/glob/node_modules/inflight/inflight.js
 
b/node_modules/bunyan/node_modules/mv/node_modules/rimraf/node_modules/glob/node_modules/inflight/inflight.js
index 8bc96cb..48202b3 100644
--- 
a/node_modules/bunyan/node_modules/mv/node_modules/rimraf/node_modules/glob/node_modules/inflight/inflight.js
+++ 
b/node_modules/bunyan/node_modules/mv/node_modules/rimraf/node_modules/glob/node_modules/inflight/inflight.js
@@ -19,18 +19,28 @@
     var cbs = reqs[key]
     var len = cbs.length
     var args = slice(arguments)
-    for (var i = 0; i < len; i++) {
-      cbs[i].apply(null, args)
-    }
-    if (cbs.length > len) {
-      // added more in the interim.
-      // de-zalgo, just in case, but don't call again.
-      cbs.splice(0, len)
-      process.nextTick(function () {
-        RES.apply(null, args)
-      })
-    } else {
-      delete reqs[key]
+
+    // XXX It's somewhat ambiguous whether a new callback added in this
+    // pass should be queued for later execution if something in the
+    // list of callbacks throws, or if it should just be discarded.
+    // However, it's such an edge case that it hardly matters, and either
+    // choice is likely as surprising as the other.
+    // As it happens, we do go ahead and schedule it for later execution.
+    try {
+      for (var i = 0; i < len; i++) {
+        cbs[i].apply(null, args)
+      }
+    } finally {
+      if (cbs.length > len) {
+        // added more in the interim.
+        // de-zalgo, just in case, but don't call again.
+        cbs.splice(0, len)
+        process.nextTick(function () {
+          RES.apply(null, args)
+        })
+      } else {
+        delete reqs[key]
+      }
     }
   })
 }
diff --git 
a/node_modules/bunyan/node_modules/mv/node_modules/rimraf/node_modules/glob/node_modules/inflight/package.json
 
b/node_modules/bunyan/node_modules/mv/node_modules/rimraf/node_modules/glob/node_modules/inflight/package.json
index 4010d03..e1822f1 100644
--- 
a/node_modules/bunyan/node_modules/mv/node_modules/rimraf/node_modules/glob/node_modules/inflight/package.json
+++ 
b/node_modules/bunyan/node_modules/mv/node_modules/rimraf/node_modules/glob/node_modules/inflight/package.json
@@ -1,6 +1,6 @@
 {
   "name": "inflight",
-  "version": "1.0.5",
+  "version": "1.0.6",
   "description": "Add callbacks to requests in flight to avoid async 
duplication",
   "main": "inflight.js",
   "files": [
@@ -11,10 +11,10 @@
     "wrappy": "1"
   },
   "devDependencies": {
-    "tap": "^1.2.0"
+    "tap": "^7.1.2"
   },
   "scripts": {
-    "test": "tap test.js"
+    "test": "tap test.js --100"
   },
   "repository": {
     "type": "git",
@@ -30,19 +30,19 @@
   },
   "homepage": "https://github.com/isaacs/inflight";,
   "license": "ISC",
-  "gitHead": "559e37b4f6327fca797fe8d7fe8ed6d9cae08821",
-  "_id": "inflight@1.0.5",
-  "_shasum": "db3204cd5a9de2e6cd890b85c6e2f66bcf4f620a",
+  "gitHead": "a547881738c8f57b27795e584071d67cf6ac1a57",
+  "_id": "inflight@1.0.6",
+  "_shasum": "49bd6331d7d02d0c09bc910a1075ba8165b56df9",
   "_from": "inflight@>=1.0.4 <2.0.0",
-  "_npmVersion": "3.9.1",
-  "_nodeVersion": "5.10.1",
+  "_npmVersion": "3.10.7",
+  "_nodeVersion": "6.5.0",
   "_npmUser": {
-    "name": "zkat",
-    "email": "k...@sykosomatic.org"
+    "name": "isaacs",
+    "email": "i...@izs.me"
   },
   "dist": {
-    "shasum": "db3204cd5a9de2e6cd890b85c6e2f66bcf4f620a",
-    "tarball": "https://registry.npmjs.org/inflight/-/inflight-1.0.5.tgz";
+    "shasum": "49bd6331d7d02d0c09bc910a1075ba8165b56df9",
+    "tarball": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz";
   },
   "maintainers": [
     {
@@ -63,9 +63,9 @@
     }
   ],
   "_npmOperationalInternal": {
-    "host": "packages-12-west.internal.npmjs.com",
-    "tmp": "tmp/inflight-1.0.5.tgz_1463529611443_0.00041943578980863094"
+    "host": "packages-16-east.internal.npmjs.com",
+    "tmp": "tmp/inflight-1.0.6.tgz_1476330807696_0.10388551792129874"
   },
   "directories": {},
-  "_resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.5.tgz";
+  "_resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz";
 }
diff --git a/node_modules/domino/lib/DOMTokenList.js 
b/node_modules/domino/lib/DOMTokenList.js
index 7205d81..dc43076 100644
--- a/node_modules/domino/lib/DOMTokenList.js
+++ b/node_modules/domino/lib/DOMTokenList.js
@@ -19,6 +19,7 @@
   },
 
   contains: function(token) {
+    token = String(token);
     handleErrors(token);
     var list = getList(this);
     return list.indexOf(token) > -1;
diff --git a/node_modules/domino/lib/Document.js 
b/node_modules/domino/lib/Document.js
index ec3d4fb..73789a8 100644
--- a/node_modules/domino/lib/Document.js
+++ b/node_modules/domino/lib/Document.js
@@ -323,6 +323,7 @@
   }},
 
   // Just copy this method from the Element prototype
+  getElementsByName: { value: Element.prototype.getElementsByName },
   getElementsByTagName: { value: Element.prototype.getElementsByTagName },
   getElementsByTagNameNS: { value: Element.prototype.getElementsByTagNameNS },
   getElementsByClassName: { value: Element.prototype.getElementsByClassName },
@@ -355,16 +356,25 @@
        },
        set: utils.nyi
   },
+  _titleElement: {
+    get: function() {
+      // The title element of a document is the first title element in the
+      // document in tree order, if there is one, or null otherwise.
+      return this.getElementsByTagName('title').item(0) || null;
+    }
+  },
   title: {
     get: function() {
-      // Return the text of the first <title> child of the <head> element.
-      var elt = namedHTMLChild(this.head, 'title');
-      return elt && elt.textContent || '';
+      var elt = this._titleElement;
+      // The child text content of the title element, or '' if null.
+      var value = elt ? elt.textContent : '';
+      // Strip and collapse whitespace in value
+      return value.replace(/[ \t\n\r\f]+/g, ' ').trim();
     },
     set: function(value) {
+      var elt = this._titleElement;
       var head = this.head;
-      if (!head) { return; /* according to spec */ }
-      var elt = namedHTMLChild(head, 'title');
+      if (!elt && !head) { return; /* according to spec */ }
       if (!elt) {
         elt = this.createElement('title');
         head.appendChild(elt);
@@ -372,7 +382,21 @@
       elt.textContent = value;
     }
   },
-  dir:  { get: utils.nyi, set: utils.nyi },
+  dir:  {
+    get: function() {
+      var htmlElement = this.documentElement;
+      if (htmlElement && htmlElement.tagName === 'HTML') {
+        return htmlElement.dir;
+      }
+      return '';
+    },
+    set: function(value) {
+      var htmlElement = this.documentElement;
+      if (htmlElement && htmlElement.tagName === 'HTML') {
+        htmlElement.dir = value;
+      }
+    },
+  },
   // Return the first <body> child of the document element.
   // XXX For now, setting this attribute is not implemented.
   body: {
diff --git a/node_modules/domino/lib/Element.js 
b/node_modules/domino/lib/Element.js
index dbc872f..bed9387 100644
--- a/node_modules/domino/lib/Element.js
+++ b/node_modules/domino/lib/Element.js
@@ -186,7 +186,7 @@
   }},
 
   getElementsByClassName: { value: function getElementsByClassName(names){
-    names = names.trim();
+    names = String(names).trim();
     if (names === '') {
       var result = new NodeList(); // Empty node list
       return result;
@@ -196,7 +196,7 @@
   }},
 
   getElementsByName: { value: function getElementsByName(name) {
-    return new FilteredElementList(this, elementNameFilter(name));
+    return new FilteredElementList(this, elementNameFilter(String(name)));
   }},
 
   // Overwritten in the constructor if not in the HTML namespace
@@ -667,6 +667,12 @@
     return select.matches(this, selector);
   }},
 
+  closest: { value: function(selector) {
+    var el = this;
+    while (el.matches && !el.matches(selector)) el = el.parentNode;
+    return el.matches ? el : null;
+  }},
+
   querySelector: { value: function(selector) {
     return select(selector, this)[0];
   }},
diff --git a/node_modules/domino/lib/HTMLParser.js 
b/node_modules/domino/lib/HTMLParser.js
index dfd7df8..d6d072a 100644
--- a/node_modules/domino/lib/HTMLParser.js
+++ b/node_modules/domino/lib/HTMLParser.js
@@ -226,8 +226,8 @@
 formassociatedSet[NAMESPACE.HTML] = {
   __proto__: null,
   "button": true, "fieldset": true, "input": true, "keygen": true,
-  "label": true, "meter": true, "object": true, "output": true,
-  "progress": true, "select": true, "textarea": true
+  "object": true, "output": true, "select": true, "textarea": true,
+  "img": true
 };
 
 var inScopeSet = Object.create(null);
@@ -2508,7 +2508,7 @@
 
   // Insert a token, either using the current parser insertion mode
   // (for HTML stuff) or using the insertForeignToken() method.
-  var insertToken = function insertToken(t, value, arg3, arg4) {
+  var insertToken = htmlparser.insertToken = function insertToken(t, value, 
arg3, arg4) {
     flushText();
     var current = stack.top;
 
@@ -2553,28 +2553,34 @@
    */
   function insertComment(data) {
     var parent = stack.top;
-    if (parent instanceof impl.HTMLTemplateElement) {
-      parent = parent.content;
+    if (foster_parent_mode && isA(parent, tablesectionrowSet)) {
+      fosterParent(function(doc) { return doc.createComment(data); });
+    } else {
+      // "If the adjusted insertion location is inside a template element,
+      // let it instead be inside the template element's template contents"
+      if (parent instanceof impl.HTMLTemplateElement) {
+        parent = parent.content;
+      }
+      parent._appendChild(parent.ownerDocument.createComment(data));
     }
-    parent._appendChild(parent.ownerDocument.createComment(data));
   }
 
   function insertText(s) {
-    if (foster_parent_mode && isA(stack.top, tablesectionrowSet)) {
+    var parent = stack.top;
+    if (foster_parent_mode && isA(parent, tablesectionrowSet)) {
       fosterParent(function(doc) { return doc.createTextNode(s); });
-    }
-    else {
-      var lastChild = stack.top.lastChild;
+    } else {
+      // "If the adjusted insertion location is inside a template element,
+      // let it instead be inside the template element's template contents"
+      if (parent instanceof impl.HTMLTemplateElement) {
+        parent = parent.content;
+      }
+      // "If there is a Text node immediately before the adjusted insertion
+      // location, then append data to that Text node's data."
+      var lastChild = parent.lastChild;
       if (lastChild && lastChild.nodeType === Node.TEXT_NODE) {
         lastChild.appendData(s);
-      }
-      else {
-        var parent = stack.top;
-        // "If the adjusted insertion location is inside a template element,
-        // let it instead be inside the template element's template contents"
-        if (parent instanceof impl.HTMLTemplateElement) {
-          parent = parent.content;
-        }
+      } else {
         parent._appendChild(parent.ownerDocument.createTextNode(s));
       }
     }
@@ -6278,7 +6284,7 @@
       case "form":
         if (form_element_pointer || stack.contains("template")) return;
         form_element_pointer = insertHTMLElement(value, arg3);
-        stack.pop();
+        stack.popElement(form_element_pointer);
         return;
       }
       break;
diff --git a/node_modules/domino/lib/impl.js b/node_modules/domino/lib/impl.js
index 6a9005c..8d7da89 100644
--- a/node_modules/domino/lib/impl.js
+++ b/node_modules/domino/lib/impl.js
@@ -12,6 +12,7 @@
   DocumentFragment: require('./DocumentFragment'),
   DocumentType: require('./DocumentType'),
   Element: require('./Element'),
+  HTMLParser: require('./HTMLParser'),
   Node: require('./Node'),
   NodeList: require('./NodeList'),
   NodeFilter: require('./NodeFilter'),
diff --git a/node_modules/domino/package.json b/node_modules/domino/package.json
index 1633c30..bbe404a 100644
--- a/node_modules/domino/package.json
+++ b/node_modules/domino/package.json
@@ -1,6 +1,6 @@
 {
   "name": "domino",
-  "version": "1.0.25",
+  "version": "1.0.26",
   "author": {
     "name": "Felix Gnass",
     "email": "fgn...@gmail.com"
@@ -25,12 +25,12 @@
     "mocha": "^2.4.5",
     "should": "^8.3.0"
   },
-  "gitHead": "3b4c4a8e75efe2d9c55ec7eb63b940084702145a",
+  "gitHead": "54bbab1866c814c120976887c5de9b9e08a22ec8",
   "bugs": {
     "url": "https://github.com/fgnass/domino/issues";
   },
-  "_id": "domino@1.0.25",
-  "_shasum": "adcd6da0505ba5103cba64a0cb38e2bb9e3a052d",
+  "_id": "domino@1.0.26",
+  "_shasum": "a9ee43bf4c95737010cb8b828cbe2e220a6b09f1",
   "_from": "domino@>=1.0.25 <2.0.0",
   "_npmVersion": "1.4.21",
   "_npmUser": {
@@ -48,13 +48,13 @@
     }
   ],
   "dist": {
-    "shasum": "adcd6da0505ba5103cba64a0cb38e2bb9e3a052d",
-    "tarball": "https://registry.npmjs.org/domino/-/domino-1.0.25.tgz";
+    "shasum": "a9ee43bf4c95737010cb8b828cbe2e220a6b09f1",
+    "tarball": "https://registry.npmjs.org/domino/-/domino-1.0.26.tgz";
   },
   "_npmOperationalInternal": {
-    "host": "packages-16-east.internal.npmjs.com",
-    "tmp": "tmp/domino-1.0.25.tgz_1463689209321_0.8667608934920281"
+    "host": "packages-12-west.internal.npmjs.com",
+    "tmp": "tmp/domino-1.0.26.tgz_1476551288942_0.27967162313871086"
   },
   "directories": {},
-  "_resolved": "https://registry.npmjs.org/domino/-/domino-1.0.25.tgz";
+  "_resolved": "https://registry.npmjs.org/domino/-/domino-1.0.26.tgz";
 }
diff --git a/node_modules/domino/test/htmlwg/harness/index.js 
b/node_modules/domino/test/htmlwg/harness/index.js
index 59750bc..009e1bc 100644
--- a/node_modules/domino/test/htmlwg/harness/index.js
+++ b/node_modules/domino/test/htmlwg/harness/index.js
@@ -3,23 +3,65 @@
 var Path = require('path');
 var domino = require('../../../lib');
 
+// These are the tests we currently fail.
+// Some of these failures are bugs we ought to fix.
+var blacklist = [
+  /apis-in-html-documents Element\.getElementsByTagName-foreign-02/,
+  /dom-tree-accessors document\.body-getter-frameset-and-body/,
+  /dom-tree-accessors document\.body-setter-01/,
+  /dom-tree-accessors document\.embeds-document\.plugins-01/,
+  /dom-tree-accessors nameditem-01/,
+  /dom-tree-accessors document\.getElementsByName 
document\.getElementsByName-namespace/,
+  /dynamic-markup-insertion document\.close-01/,
+  /dynamic-markup-insertion document\.open-0[12]/,
+  /dynamic-markup-insertion document\.write-0[12]/,
+  /dynamic-markup-insertion document\.writeln-0[12]/,
+  /general interfaces/,
+  /global-attributes dataset/,
+  /obsolete-features requirements-for-implementations 
other-elements-attributes-and-apis document-color-0[1234]/,
+  /obsolete-features requirements-for-implementations 
other-elements-attributes-and-apis document\.all-0[12345]/,
+  /obsolete-features requirements-for-implementations 
other-elements-attributes-and-apis heading-obsolete-attributes-01/,
+  /obsolete-features requirements-for-implementations 
other-elements-attributes-and-apis script-IDL-event-htmlfor/,
+  /resource-metadata-management document-compatmode-06/,
+  /the-elements-of-html document-metadata the-link-element link-rellist/,
+  /the-elements-of-html document-metadata the-title-element title\.text-0[12]/,
+  /the-elements-of-html forms the-form-element form-elements-interfaces-01/,
+  /the-elements-of-html forms the-form-element form-elements-matches/,
+  /the-elements-of-html forms the-form-element form-elements-nameditem-0[12]/,
+  /the-elements-of-html forms the-input-element input-textselection-01/,
+  /the-elements-of-html forms the-textarea-element textarea-type/,
+  /the-elements-of-html scripting the-script-element script-languages-01/,
+  /the-elements-of-html scripting the-script-element 
script-noembed-noframes-iframe/,
+  /the-elements-of-html tabular-data the-table-element insertRow-method-0[12]/,
+  /the-elements-of-html text-level-semantics the-a-element a\.text-setter-01/,
+  /the-elements-of-html text-level-semantics the-a-element a\.text-getter-01/,
+];
+
+var onBlacklist = function(name) {
+  name = name.replace(/\//g, ' ');
+  for (var i=0; i<blacklist.length; i++) {
+    if (blacklist[i].test(name)) { return true; }
+  }
+  return false;
+};
+
 function read(file) {
   return fs.readFileSync(Path.resolve(__dirname, '..', file), 'utf8');
 }
 
 var testharness = read(__dirname + '/testharness.js');
 
-function list(dir, fn) {
+function list(base, dir, fn) {
   var result = {};
-  dir = Path.resolve(__dirname, '..', dir);
-  fs.readdirSync(dir).forEach(function(file) {
+  var fulldir = Path.resolve(__dirname, '..', base, dir);
+  fs.readdirSync(fulldir).forEach(function(file) {
     var path = Path.join(dir, file);
-    var stat = fs.statSync(path);
+    var stat = fs.statSync(Path.join(fulldir, file));
     if (stat.isDirectory()) {
-      result[file] = list(path, fn);
+      result[file] = list(base, path, fn);
     }
     else if (file.match(/\.x?html$/)) {
-      var test = fn(path);
+      var test = fn(path, Path.join(fulldir, file));
       if (test) result[file] = test;
     }
   });
@@ -27,19 +69,35 @@
 }
 
 module.exports = function(path) {
-  return list(path, function(file) {
+  return list(path, '', function(name, file) {
     var html = read(file);
     var window = domino.createWindow(html);
     window._run(testharness);
     var scripts = window.document.getElementsByTagName('script');
-    if (scripts.length) {
-      var script = scripts[scripts.length-1];
-      var code = script.textContent;
-      if (/assert/.test(code)) {
-        return function() {
-          window._run(code);
-        };
+    scripts = [].slice.call(scripts);
+
+    return function() {
+      function listenForFailures() {
+        add_result_callback(function(result) {
+          if (result.status === result.FAIL) {
+            throw new Error(result.message);
+          }
+        });
       }
-    }
+      window._run("(" + listenForFailures.toString() + ")();");
+
+      var concatenatedScripts = scripts.map(function(script) {
+        return script.textContent;
+      }).join("\n");
+
+      var go = function() {
+        window._run(concatenatedScripts);
+      };
+      if (onBlacklist(name)) {
+        assert.throws(go, 'Expected test to fail.');
+      } else {
+        go();
+      }
+    };
   });
 };
diff --git 
a/node_modules/domino/test/htmlwg/submission/Ms2ger/dom-tree-accessors/document.title-06.html
 
b/node_modules/domino/test/htmlwg/submission/Ms2ger/dom-tree-accessors/document.title-06.html
index 809ede0..8ddab73 100644
--- 
a/node_modules/domino/test/htmlwg/submission/Ms2ger/dom-tree-accessors/document.title-06.html
+++ 
b/node_modules/domino/test/htmlwg/submission/Ms2ger/dom-tree-accessors/document.title-06.html
@@ -16,9 +16,12 @@
   assert_equals(document.title, "");
   assert_true(document.documentElement.firstChild.lastChild instanceof
               HTMLTitleElement, "Need a title element.");
+  /* CSA: I believe these tests are incorrect according to the HTML5 spec;
+   * no text node should be created if the value is the empty string.
   var title = document.documentElement.firstChild.lastChild.firstChild;
   assert_true(title, "Need a node.");
   assert_true(title instanceof Text, "Should be a text node");
   assert_equals(title.value, "");
+   */
 });
 </script>
diff --git 
a/node_modules/domino/test/htmlwg/submission/Ms2ger/global-attributes/document-dir.html
 
b/node_modules/domino/test/htmlwg/submission/Ms2ger/global-attributes/document-dir.html
index 734f922..7fb592b 100644
--- 
a/node_modules/domino/test/htmlwg/submission/Ms2ger/global-attributes/document-dir.html
+++ 
b/node_modules/domino/test/htmlwg/submission/Ms2ger/global-attributes/document-dir.html
@@ -20,6 +20,9 @@
 }, "Setting the idl attribute to a garbage value")
 test(function() {
   document.dir = "";
+  /* CSA: I do not believe this test is correct; see
+   * https://github.com/whatwg/html/issues/1906
   assert_equals(document.documentElement.hasAttribute("dir"), false, 
"Attribute should be gone");
+   */
 }, "Setting the idl attribute to the empty sting")
 </script>
diff --git 
a/node_modules/domino/test/htmlwg/submission/Ms2ger/node/Element-closest.html 
b/node_modules/domino/test/htmlwg/submission/Ms2ger/node/Element-closest.html
new file mode 100644
index 0000000..1104d0c
--- /dev/null
+++ 
b/node_modules/domino/test/htmlwg/submission/Ms2ger/node/Element-closest.html
@@ -0,0 +1,77 @@
+<!DOCTYPE HTML>
+<meta charset=utf8>
+<title>Test for Element.closest</title>
+<script src="/resources/testharness.js"></script>
+<script src="/resources/testharnessreport.js"></script>
+<body id="body">
+  <div id="test8" class="div3" style="display:none">
+    <div id="test7" class="div2">
+      <div id="test6" class="div1">
+        <form id="test10" class="form2"></form>
+        <form id="test5" class="form1" name="form-a">
+          <input id="test1" class="input1" required>
+          <fieldset class="fieldset2" id="test2">
+            <select id="test3" class="select1" required>
+              <option default id="test4" value="">Test4</option>
+              <option selected id="test11">Test11</option>
+              <option id="test12">Test12</option>
+              <option id="test13">Test13</option>
+            </select>
+            <input id="test9" type="text" required>
+          </fieldset>
+        </form>
+      </div>
+    </div>
+  </div>
+  <div id=log></div>
+<script>
+  do_test("select"                     , "test12", "test3");
+  do_test("fieldset"                   , "test13", "test2");
+  do_test("div"                        , "test13", "test6");
+  do_test("body"                       , "test3" , "body");
+
+  do_test("[default]"                  , "test4" , "test4");
+  do_test("[selected]"                 , "test4" , "");
+  do_test("[selected]"                 , "test11", "test11");
+  do_test('[name="form-a"]'            , "test12", "test5");
+  do_test('form[name="form-a"]'        , "test13", "test5");
+  do_test("input[required]"            , "test9" , "test9");
+  do_test("select[required]"           , "test9" , "");
+
+  do_test("div:not(.div1)"             , "test13", "test7");
+  do_test("div.div3"                   , "test6" , "test8");
+  do_test("div#test7"                  , "test1" , "test7");
+
+  do_test(".div3 > .div2"              , "test12", "test7");
+  do_test(".div3 > .div1"              , "test12", "");
+  do_test("form > input[required]"     , "test9" , "");
+  do_test("fieldset > select[required]", "test12", "test3");
+
+  do_test("input + fieldset"           , "test6" , "");
+  do_test("form + form"                , "test3" , "test5");
+  do_test("form + form"                , "test5" , "test5");
+
+  do_test(":empty"                     , "test10", "test10");
+  do_test(":last-child"                , "test11", "test2");
+  do_test(":first-child"               , "test12", "test3");
+
+  /* TODO: Reenable these once :invalid and :scope are supported
+  
+  do_test(":invalid"                   , "test11", "test2");
+
+  do_test(":scope"                     , "test4",  "test4");
+  do_test("select > :scope"            , "test4",  "test4");
+  do_test("div > :scope"               , "test4",  "");
+  do_test(":has(> :scope)"             , "test4",  "test3");
+  */
+function do_test(aSelector, aElementId, aTargetId) {
+  test(function() {
+    var el = document.getElementById(aElementId).closest(aSelector);
+    if (el === null) {
+      assert_equals("", aTargetId, aSelector);
+    } else {
+      assert_equals(el.id, aTargetId, aSelector);
+    }
+  }, "Element.closest with context node '" + aElementId + "' and selector '" + 
aSelector + "'");
+}
+</script>
diff --git a/node_modules/domino/test/w3c/harness/index.js 
b/node_modules/domino/test/w3c/harness/index.js
index 2b99432..4c7990c 100644
--- a/node_modules/domino/test/w3c/harness/index.js
+++ b/node_modules/domino/test/w3c/harness/index.js
@@ -39,45 +39,48 @@
 
 module.exports = function(path) {
 
-  function run(file) {
+  function run(ctx, file) {
     vm.runInContext(fs.readFileSync(file, 'utf8'), ctx, file);
     return ctx;
   }
 
-  var ctx = vm.createContext(); // create new independent context
-  Object.keys(globals).forEach(function(k) {
-    ctx[k] = globals[k]; // shallow clone
-  });
+  function makeContext() {
+    var ctx = vm.createContext(); // create new independent context
+    Object.keys(globals).forEach(function(k) {
+      ctx[k] = globals[k]; // shallow clone
+    });
 
-  ctx.createConfiguredBuilder = function() {
-    return {
-      contentType: 'text/html',
-      hasFeature: function(feature, version) {
-        return impl.hasFeature(feature, version);
-      },
-      getImplementation: function() {
-        return impl;
-      },
-      setImplementationAttribute: function(attr, value) {
-        // Ignore
-      },
-      preload: function(docRef, name, href) {
-        return 1;
-      },
-      load: function(docRef, name, href) {
-        var doc = Path.resolve(__dirname, '..', path, 'files', href) + '.html';
-        var html = fs.readFileSync(doc, 'utf8');
-        return domino.createDocument(html);
-      }
+    ctx.createConfiguredBuilder = function() {
+      return {
+        contentType: 'text/html',
+        hasFeature: function(feature, version) {
+          return impl.hasFeature(feature, version);
+        },
+        getImplementation: function() {
+          return impl;
+        },
+        setImplementationAttribute: function(attr, value) {
+          // Ignore
+        },
+        preload: function(docRef, name, href) {
+          return 1;
+        },
+        load: function(docRef, name, href) {
+          var doc = Path.resolve(__dirname, '..', path, 'files', href) + 
'.html';
+          var html = fs.readFileSync(doc, 'utf8');
+          return domino.createDocument(html);
+        }
+      };
     };
-  };
-
-  run(__dirname + '/DomTestCase.js');
+    run(ctx, __dirname + '/DomTestCase.js');
+    return ctx;
+  }
 
   var tests = {};
   list(path, /(.*?)\.js$/, function(file, basename) {
     tests[basename] =  function() {
-      run(file);
+      var ctx = makeContext();
+      run(ctx, file);
       ctx.setUpPage();
       ctx.runTest();
     };
diff --git a/node_modules/domino/test/w3c/level1/html/HTMLLabelElement01.js 
b/node_modules/domino/test/w3c/level1/html/HTMLLabelElement01.js
index 927b3aa..ef4bdb5 100644
--- a/node_modules/domino/test/w3c/level1/html/HTMLLabelElement01.js
+++ b/node_modules/domino/test/w3c/level1/html/HTMLLabelElement01.js
@@ -99,13 +99,6 @@
       doc = load(docRef, "doc", "label");
       nodeList = doc.getElementsByTagName("label");
       assertSize("Asize",2,nodeList);
-testNode = nodeList.item(0);
-      fNode = testNode.form;
-
-      vform = fNode.id;
-
-      assertEquals("formLink","form1",vform);
-       
 }
 
 
diff --git a/node_modules/preq/index.js b/node_modules/preq/index.js
index ec65eed..d52350f 100644
--- a/node_modules/preq/index.js
+++ b/node_modules/preq/index.js
@@ -178,13 +178,14 @@
 
             if (body && response.headers && !self.options._encodingProvided) {
                 var contentType = response.headers['content-type'];
-                if (/^text\/|application\/json\b/.test(contentType)) {
+                // Decodes:  "text/...", "application/json...", 
"application/vnd.geo+json..."
+                if 
(/^text\/|application\/([^+;]+\+)?json\b/.test(contentType)) {
                     // Convert buffer to string
                     body = body.toString();
                     delete response.headers['content-length'];
                 }
 
-                if (/^application\/(?:problem\+)?json\b/.test(contentType)) {
+                if (/^application\/([^+;]+\+)?json\b/.test(contentType)) {
                     body = JSON.parse(body);
                 }
             }
diff --git a/node_modules/preq/node_modules/request/node_modules/aws4/aws4.js 
b/node_modules/preq/node_modules/request/node_modules/aws4/aws4.js
index cbe5dc9..a543180 100644
--- a/node_modules/preq/node_modules/request/node_modules/aws4/aws4.js
+++ b/node_modules/preq/node_modules/request/node_modules/aws4/aws4.js
@@ -52,6 +52,8 @@
   }
   if (!request.hostname && !request.host)
     request.hostname = headers.Host || headers.host
+
+  this.isCodeCommitGit = this.service === 'codecommit' && request.method === 
'GIT'
 }
 
 RequestSigner.prototype.matchHost = function(host) {
@@ -109,7 +111,7 @@
 
   } else {
 
-    if (!request.doNotModifyHeaders) {
+    if (!request.doNotModifyHeaders && !this.isCodeCommitGit) {
       if (request.body && !headers['Content-Type'] && !headers['content-type'])
         headers['Content-Type'] = 'application/x-www-form-urlencoded; 
charset=utf-8'
 
@@ -153,6 +155,9 @@
       date = new Date(headers.Date || headers.date || new Date)
 
     this.datetime = date.toISOString().replace(/[:\-]|\.\d{3}/g, '')
+
+    // Remove the trailing 'Z' on the timestamp string for CodeCommit git 
access
+    if (this.isCodeCommitGit) this.datetime = this.datetime.slice(0, -1)
   }
   return this.datetime
 }
@@ -202,8 +207,8 @@
       decodePath = this.service === 's3' || this.request.doNotEncodePath,
       decodeSlashesInPath = this.service === 's3',
       firstValOnly = this.service === 's3',
-      bodyHash = this.service === 's3' && this.request.signQuery ?
-        'UNSIGNED-PAYLOAD' : hash(this.request.body || '', 'hex')
+      bodyHash = this.service === 's3' && this.request.signQuery ? 
'UNSIGNED-PAYLOAD' :
+        (this.isCodeCommitGit ? '' : hash(this.request.body || '', 'hex'))
 
   if (query) {
     queryStr = 
encodeRfc3986(querystring.stringify(Object.keys(query).sort().reduce(function(obj,
 key) {
diff --git 
a/node_modules/preq/node_modules/request/node_modules/aws4/package.json 
b/node_modules/preq/node_modules/request/node_modules/aws4/package.json
index 2ce9a28..a009a74 100644
--- a/node_modules/preq/node_modules/request/node_modules/aws4/package.json
+++ b/node_modules/preq/node_modules/request/node_modules/aws4/package.json
@@ -1,6 +1,6 @@
 {
   "name": "aws4",
-  "version": "1.4.1",
+  "version": "1.5.0",
   "description": "Signs and prepares requests using AWS Signature Version 4",
   "author": {
     "name": "Michael Hart",
@@ -72,16 +72,16 @@
   "scripts": {
     "test": "mocha ./test/fast.js ./test/slow.js -b -t 100s -R list"
   },
-  "gitHead": "f126d3ff80be1ddde0fc6b50bb51a7f199547e81",
+  "gitHead": "ba136334ee08884c6042c8578a22e376233eef34",
   "bugs": {
     "url": "https://github.com/mhart/aws4/issues";
   },
   "homepage": "https://github.com/mhart/aws4#readme";,
-  "_id": "aws4@1.4.1",
-  "_shasum": "fde7d5292466d230e5ee0f4e038d9dfaab08fc61",
+  "_id": "aws4@1.5.0",
+  "_shasum": "0a29ffb79c31c9e712eeb087e8e7a64b4a56d755",
   "_from": "aws4@>=1.2.1 <2.0.0",
-  "_npmVersion": "2.15.4",
-  "_nodeVersion": "4.4.3",
+  "_npmVersion": "2.15.11",
+  "_nodeVersion": "4.5.0",
   "_npmUser": {
     "name": "hichaelmart",
     "email": "michael.hart...@gmail.com"
@@ -93,13 +93,13 @@
     }
   ],
   "dist": {
-    "shasum": "fde7d5292466d230e5ee0f4e038d9dfaab08fc61",
-    "tarball": "https://registry.npmjs.org/aws4/-/aws4-1.4.1.tgz";
+    "shasum": "0a29ffb79c31c9e712eeb087e8e7a64b4a56d755",
+    "tarball": "https://registry.npmjs.org/aws4/-/aws4-1.5.0.tgz";
   },
   "_npmOperationalInternal": {
-    "host": "packages-12-west.internal.npmjs.com",
-    "tmp": "tmp/aws4-1.4.1.tgz_1462643218465_0.6527479749638587"
+    "host": "packages-16-east.internal.npmjs.com",
+    "tmp": "tmp/aws4-1.5.0.tgz_1476226259635_0.2796843808609992"
   },
   "directories": {},
-  "_resolved": "https://registry.npmjs.org/aws4/-/aws4-1.4.1.tgz";
+  "_resolved": "https://registry.npmjs.org/aws4/-/aws4-1.5.0.tgz";
 }
diff --git a/node_modules/preq/package.json b/node_modules/preq/package.json
index 9f91c08..a73b6ff 100644
--- a/node_modules/preq/package.json
+++ b/node_modules/preq/package.json
@@ -1,6 +1,6 @@
 {
   "name": "preq",
-  "version": "0.4.10",
+  "version": "0.4.11",
   "description": "Yet another promising request wrapper",
   "main": "index.js",
   "scripts": {
@@ -23,22 +23,22 @@
     "url": "git://github.com/wikimedia/preq.git"
   },
   "homepage": "https://github.com/wikimedia/preq";,
-  "gitHead": "7c19ddfb354696f9ebb523f43e74616887aab96c",
+  "gitHead": "bad7241b6cd993b354491ede2a5800df9905dbc9",
   "bugs": {
     "url": "https://github.com/wikimedia/preq/issues";
   },
-  "_id": "preq@0.4.10",
-  "_shasum": "e1dd9b332ea18292ed986a00e969c507686a68e9",
+  "_id": "preq@0.4.11",
+  "_shasum": "fabc73f402507b9c654b9e9efe2ba48cc0380f12",
   "_from": "preq@>=0.4.10 <0.5.0",
-  "_npmVersion": "2.14.12",
-  "_nodeVersion": "4.3.0",
+  "_npmVersion": "2.15.9",
+  "_nodeVersion": "4.6.0",
   "_npmUser": {
     "name": "doorman",
     "email": "marko.obro...@gmail.com"
   },
   "dist": {
-    "shasum": "e1dd9b332ea18292ed986a00e969c507686a68e9",
-    "tarball": "https://registry.npmjs.org/preq/-/preq-0.4.10.tgz";
+    "shasum": "fabc73f402507b9c654b9e9efe2ba48cc0380f12",
+    "tarball": "https://registry.npmjs.org/preq/-/preq-0.4.11.tgz";
   },
   "maintainers": [
     {
@@ -52,8 +52,8 @@
   ],
   "_npmOperationalInternal": {
     "host": "packages-12-west.internal.npmjs.com",
-    "tmp": "tmp/preq-0.4.10.tgz_1466786370198_0.0399467081297189"
+    "tmp": "tmp/preq-0.4.11.tgz_1476265204748_0.12369609624147415"
   },
   "directories": {},
-  "_resolved": "https://registry.npmjs.org/preq/-/preq-0.4.10.tgz";
+  "_resolved": "https://registry.npmjs.org/preq/-/preq-0.4.11.tgz";
 }
diff --git 
a/node_modules/service-runner/node_modules/limitation/node_modules/kad/package.json
 
b/node_modules/service-runner/node_modules/limitation/node_modules/kad/package.json
index 32d2ab3..cd1abcf 100644
--- 
a/node_modules/service-runner/node_modules/limitation/node_modules/kad/package.json
+++ 
b/node_modules/service-runner/node_modules/limitation/node_modules/kad/package.json
@@ -75,7 +75,7 @@
   },
   "homepage": "https://github.com/kadtools/kad#readme";,
   "_id": "kad@1.3.6",
-  "_shasum": "db510a0958198ef15787c4904f2b0b931b557243",
+  "_shasum": "b366ce56607ecd728e61a81e56cd313bb8a80cd7",
   "_from": "git+https://github.com/gwicke/kad.git#master";,
   "_resolved": 
"git+https://github.com/gwicke/kad.git#f35971036f43814043245da82b12d035b7bbfd16";
 }
diff --git a/src b/src
index fc900fc..13fa4b4 160000
--- a/src
+++ b/src
@@ -1 +1 @@
-Subproject commit fc900fc5d4daad30d9a49a71355070894c44418e
+Subproject commit 13fa4b4302985e0a92c8392b8a94150c1dc42b56

-- 
To view, visit https://gerrit.wikimedia.org/r/316422
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: I507d538446d786d6e8a4c201daab85f992f76049
Gerrit-PatchSet: 1
Gerrit-Project: mediawiki/services/mobileapps/deploy
Gerrit-Branch: master
Gerrit-Owner: BearND <bsitzm...@wikimedia.org>

_______________________________________________
MediaWiki-commits mailing list
MediaWiki-commits@lists.wikimedia.org
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to