Bug 1392947 - (experimental) Use memoize function to help caching previous extracted label result. draft
authorRay Lin <ralin@mozilla.com>
Tue, 14 Nov 2017 11:51:56 +0800
changeset 700421 387a0cf7a377f1f6334bd89e0cef9979d6f5558a
parent 700420 0552f9fca5c1f5ea5df1adf03c3b638ee607ecea
child 740852 baa1cb70e5c82042e794dbad0b72823f8f8b95dd
push id89814
push userbmo:ralin@mozilla.com
push dateMon, 20 Nov 2017 04:12:38 +0000
bugs1392947
milestone59.0a1
Bug 1392947 - (experimental) Use memoize function to help caching previous extracted label result. MozReview-Commit-ID: J5h2MSLebkK
browser/extensions/formautofill/FormAutofillHeuristics.jsm
browser/extensions/formautofill/FormAutofillUtils.jsm
--- a/browser/extensions/formautofill/FormAutofillHeuristics.jsm
+++ b/browser/extensions/formautofill/FormAutofillHeuristics.jsm
@@ -282,17 +282,16 @@ this.LabelUtils = {
   },
 };
 
 /**
  * Returns the autocomplete information of fields according to heuristics.
  */
 this.FormAutofillHeuristics = {
   RULES: null,
-  extractedLabelStrings: new WeakMap(),
 
   /**
    * Try to find a contiguous sub-array within an array.
    *
    * @param {Array} array
    * @param {Array} subArray
    *
    * @returns {boolean}
@@ -738,32 +737,30 @@ this.FormAutofillHeuristics = {
 
   /**
    * Extract all the signature strings of an element.
    *
    * @param {HTMLElement} element
    * @returns {ElementStrings}
    */
   _getElementStrings(element) {
-    const extractedLabelStrings = this.extractedLabelStrings;
+    return {
+      extractLabelStrings: FormAutofillUtils.memoize((elem) => {
+        const labels = LabelUtils.findLabelElements(elem);
+        const labelStrings = [];
+        for (let label of labels) {
+          labelStrings.push(...LabelUtils.extractLabelStrings(label));
+        }
+        return labelStrings;
+      }),
 
-    return {
       * [Symbol.iterator]() {
         yield element.id;
         yield element.name;
-
-        if (!extractedLabelStrings.has(element)) {
-          const labels = LabelUtils.findLabelElements(element);
-          const labelStrings = [];
-          for (let label of labels) {
-            labelStrings.push(...LabelUtils.extractLabelStrings(label));
-          }
-          extractedLabelStrings.set(element, labelStrings);
-        }
-        yield *extractedLabelStrings.get(element);
+        yield *this.extractLabelStrings(element);
       },
     };
   },
 
   /**
    * Find the first matched field name of the element wih given regex list.
    *
    * @param {HTMLElement} element
--- a/browser/extensions/formautofill/FormAutofillUtils.jsm
+++ b/browser/extensions/formautofill/FormAutofillUtils.jsm
@@ -590,16 +590,41 @@ this.FormAutofillUtils = {
   localizeMarkup(bundleURI, root) {
     const bundle = Services.strings.createBundle(bundleURI);
     let elements = root.querySelectorAll("[data-localization]");
     for (let element of elements) {
       element.textContent = bundle.GetStringFromName(element.getAttribute("data-localization"));
       element.removeAttribute("data-localization");
     }
   },
+
+  memoize(fn) {
+    if (fn.length != 1) {
+      // TODO: implement variadic version for non-unary function.
+      throw new Error("only unary function is accepted");
+    }
+    return this.monadicMemoize(fn);
+  },
+
+  monadicMemoize(fn) {
+    let objectCache = new WeakMap();
+    let primitiveCache = new Map();
+
+    return arg => {
+      const cache = (arg == null || (typeof arg !== "function" && typeof arg !== "object")) ?
+                    primitiveCache :
+                    objectCache;
+      const result = cache.get(arg) || fn(arg);
+      if (!cache.has(arg)) {
+        cache.set(arg, result);
+      }
+
+      return result;
+    };
+  },
 };
 
 XPCOMUtils.defineLazyGetter(this.FormAutofillUtils, "DEFAULT_COUNTRY_CODE", () => {
   return Services.prefs.getCharPref("browser.search.countryCode", "US");
 });
 
 this.log = null;
 this.FormAutofillUtils.defineLazyLogGetter(this, this.EXPORTED_SYMBOLS[0]);