Bug 1379900 - Doing elements filtering in JS to simplify XPath query in FormData::collect. r=mikedeboer
authorBeekill95 <nnn_bikiu0707@yahoo.com>
Sun, 23 Jul 2017 14:41:52 +0700
changeset 420338 a0a41228220bd600b4299758a394bcffebadc0e3
parent 420337 9b266be297891f2ee6425070e2ac336722c5b865
child 420339 a4d0803e76901864339252806a8d6960f681af97
push id7566
push usermtabara@mozilla.com
push dateWed, 02 Aug 2017 08:25:16 +0000
treeherdermozilla-beta@86913f512c3c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmikedeboer
bugs1379900
milestone56.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1379900 - Doing elements filtering in JS to simplify XPath query in FormData::collect. r=mikedeboer MozReview-Commit-ID: 7VjSkV8dlq1
toolkit/modules/sessionstore/FormData.jsm
--- a/toolkit/modules/sessionstore/FormData.jsm
+++ b/toolkit/modules/sessionstore/FormData.jsm
@@ -71,16 +71,32 @@ function isValidCCNumber(value) {
       }
     } else {
       total += currentDigit;
     }
   }
   return total % 10 == 0;
 }
 
+// For a comprehensive list of all available <INPUT> types see
+// https://dxr.mozilla.org/mozilla-central/search?q=kInputTypeTable&redirect=false
+const IGNORE_ATTRIBUTES = [
+  ["type", new Set(["password", "hidden", "button", "image", "submit", "reset"])],
+  ["autocomplete", new Set(["off"])]
+];
+function shouldIgnoreNode(node) {
+  for (let i = 0; i < IGNORE_ATTRIBUTES.length; ++i) {
+    let [attrName, attrValues] = IGNORE_ATTRIBUTES[i];
+    if (node.hasAttribute(attrName) && attrValues.has(node.getAttribute(attrName).toLowerCase())) {
+      return true;
+    }
+  }
+  return false;
+}
+
 /**
  * The public API exported by this module that allows to collect
  * and restore form data for a document and its subframes.
  */
 this.FormData = Object.freeze({
   collect(frame) {
     return FormDataInternal.collect(frame);
   },
@@ -113,37 +129,21 @@ var FormDataInternal = {
   resolveNS(aPrefix) {
     return this.namespaceURIs[aPrefix] || null;
   },
 
   /**
    * @returns an XPath query to all savable form field nodes
    */
   get restorableFormNodesXPath() {
-    // for a comprehensive list of all available <INPUT> types see
-    // https://dxr.mozilla.org/mozilla-central/search?q=kInputTypeTable&redirect=false
-    let ignoreInputs = new Map([
-      ["type", ["password", "hidden", "button", "image", "submit", "reset"]],
-      ["autocomplete", ["off"]]
-    ]);
-    // XXXzeniko work-around until lower-case has been implemented (bug 398389)
-    let toLowerCase = '"ABCDEFGHIJKLMNOPQRSTUVWXYZ", "abcdefghijklmnopqrstuvwxyz"';
-    let ignores = [];
-    for (let [attrName, attrValues] of ignoreInputs) {
-      for (let attrValue of attrValues)
-        ignores.push(`translate(@${attrName}, ${toLowerCase})='${attrValue}'`);
-    }
-    let ignore = `not(${ignores.join(" or ")})`;
-
-    let formNodesXPath = `//textarea[${ignore}]|//xhtml:textarea[${ignore}]|` +
-      `//select[${ignore}]|//xhtml:select[${ignore}]|` +
-      `//input[${ignore}]|//xhtml:input[${ignore}]`;
-
-    // Special case for about:config's search field.
-    formNodesXPath += '|/xul:window[@id="config"]//xul:textbox[@id="textbox"]';
+    let formNodesXPath = "//textarea|//xhtml:textarea|" +
+      "//select|//xhtml:select|" +
+      "//input|//xhtml:input" +
+      // Special case for about:config's search field.
+      "|/xul:window[@id='config']//xul:textbox[@id='textbox']";
 
     delete this.restorableFormNodesXPath;
     return (this.restorableFormNodesXPath = formNodesXPath);
   },
 
   /**
    * Collect form data for a given |frame| *not* including any subframes.
    *
@@ -179,16 +179,19 @@ var FormDataInternal = {
     let ret = {};
 
     // Limit the number of XPath expressions for performance reasons. See
     // bug 477564.
     const MAX_TRAVERSED_XPATHS = 100;
     let generatedCount = 0;
 
     while ((node = formNodes.iterateNext())) {
+      if (shouldIgnoreNode(node)) {
+        continue;
+      }
       let hasDefaultValue = true;
       let value;
 
       // Only generate a limited number of XPath expressions for perf reasons
       // (cf. bug 477564)
       if (!node.id && generatedCount > MAX_TRAVERSED_XPATHS) {
         continue;
       }