Bug 1456843 - Compute FormLike elements lazily on <form>-less fields. r?MattN
MozReview-Commit-ID: 3blElMxkejf
--- a/toolkit/modules/FormLikeFactory.jsm
+++ b/toolkit/modules/FormLikeFactory.jsm
@@ -1,16 +1,18 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
"use strict";
var EXPORTED_SYMBOLS = ["FormLikeFactory"];
+ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
+
/**
* A factory to generate FormLike objects that represent a set of related fields
* which aren't necessarily marked up with a <form> element. FormLike's emulate
* the properties of an HTMLFormElement which are relevant to form tasks.
*/
let FormLikeFactory = {
_propsFromForm: [
"action",
@@ -68,32 +70,42 @@ let FormLikeFactory = {
}
let rootElement = this.findRootForField(aField);
if (ChromeUtils.getClassName(rootElement) === "HTMLFormElement") {
return this.createFromForm(rootElement);
}
let doc = aField.ownerDocument;
- let elements = [];
- for (let el of rootElement.querySelectorAll("input, select")) {
- // Exclude elements inside the rootElement that are already in a <form> as
- // they will be handled by their own FormLike.
- if (!el.form) {
- elements.push(el);
- }
- }
+
let formLike = {
action: doc.baseURI,
autocomplete: "on",
- elements,
ownerDocument: doc,
rootElement,
};
+ // FormLikes can be created when fields are inserted into the DOM. When
+ // many, many fields are inserted one after the other, we create many
+ // FormLikes, and computing the elements list becomes more and more
+ // expensive. Making the elements list lazy means that it'll only
+ // be computed when it's eventually needed (if ever).
+ XPCOMUtils.defineLazyGetter(formLike, "elements", function() {
+ let elements = [];
+ for (let el of this.rootElement.querySelectorAll("input, select")) {
+ // Exclude elements inside the rootElement that are already in a <form> as
+ // they will be handled by their own FormLike.
+ if (!el.form) {
+ elements.push(el);
+ }
+ }
+
+ return elements;
+ });
+
this._addToJSONProperty(formLike);
return formLike;
},
/**
* Determine the Element that encapsulates the related fields. For example, if
* a page contains a login form and a checkout form which are "submitted"
* separately, and the username field is passed in, ideally this would return