Bug 850430 - Optimize mozContact creation and validation code. r=gwagner
authorReuben Morais <reuben.morais@gmail.com>
Thu, 17 Oct 2013 18:29:56 -0300
changeset 166093 dad5d17328b2eecbc28e4c10b9fc6cdc30526beb
parent 166092 533d30be7e6e34e27198fd6f03b2a1e15192d245
child 166094 caa15ceeba4b4c703f8fd7717580d2e369653888
push id428
push userbbajaj@mozilla.com
push dateTue, 28 Jan 2014 00:16:25 +0000
treeherdermozilla-release@cd72a7ff3a75 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersgwagner
bugs850430
milestone27.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 850430 - Optimize mozContact creation and validation code. r=gwagner
dom/contacts/ContactManager.js
--- a/dom/contacts/ContactManager.js
+++ b/dom/contacts/ContactManager.js
@@ -24,19 +24,19 @@ XPCOMUtils.defineLazyServiceGetter(this,
                                    "nsIPermissionManager");
 
 XPCOMUtils.defineLazyServiceGetter(this, "cpmm",
                                    "@mozilla.org/childprocessmessagemanager;1",
                                    "nsIMessageSender");
 
 const CONTACTS_SENDMORE_MINIMUM = 5;
 
-function ContactAddress() { }
+function ContactAddressImpl() { }
 
-ContactAddress.prototype = {
+ContactAddressImpl.prototype = {
   // This function is meant to be called via bindings code for type checking,
   // don't call it directly. Instead, create a content object and call initialize
   // on that.
   initialize: function(aType, aStreetAddress, aLocality, aRegion, aPostalCode, aCountryName, aPref) {
     this.type = aType;
     this.streetAddress = aStreetAddress;
     this.locality = aLocality;
     this.region = aRegion;
@@ -69,19 +69,19 @@ ContactAddress.prototype = {
     return json;
   },
 
   classID: Components.ID("{9cbfa81c-bcab-4ca9-b0d2-f4318f295e33}"),
   contractID: "@mozilla.org/contactAddress;1",
   QueryInterface: XPCOMUtils.generateQI([Ci.nsISupports]),
 };
 
-function ContactField() { }
+function ContactFieldImpl() { }
 
-ContactField.prototype = {
+ContactFieldImpl.prototype = {
   // This function is meant to be called via bindings code for type checking,
   // don't call it directly. Instead, create a content object and call initialize
   // on that.
   initialize: function(aType, aValue, aPref) {
     this.type = aType;
     this.value = aValue;
     this.pref = aPref;
   },
@@ -102,19 +102,19 @@ ContactField.prototype = {
     return json;
   },
 
   classID: Components.ID("{ad19a543-69e4-44f0-adfa-37c011556bc1}"),
   contractID: "@mozilla.org/contactField;1",
   QueryInterface: XPCOMUtils.generateQI([Ci.nsISupports]),
 };
 
-function ContactTelField() { }
+function ContactTelFieldImpl() { }
 
-ContactTelField.prototype = {
+ContactTelFieldImpl.prototype = {
   // This function is meant to be called via bindings code for type checking,
   // don't call it directly. Instead, create a content object and call initialize
   // on that.
   initialize: function(aType, aValue, aCarrier, aPref) {
     this.type = aType;
     this.value = aValue;
     this.carrier = aCarrier;
     this.pref = aPref;
@@ -139,20 +139,16 @@ ContactTelField.prototype = {
   },
 
   classID: Components.ID("{4d42c5a9-ea5d-4102-80c3-40cc986367ca}"),
   contractID: "@mozilla.org/contactTelField;1",
   QueryInterface: XPCOMUtils.generateQI([Ci.nsISupports]),
 };
 
 function validateArrayField(data, createCb) {
-  function isVanillaObj(aObj) {
-    return Object.prototype.toString.call(aObj) == "[object Object]";
-  }
-
   // We use an array-like Proxy to validate data set by content, since we don't
   // have WebIDL arrays yet. See bug 851726.
 
   // ArrayPropertyExposedPropsProxy is used to return "rw" for any valid index
   // and "length" in __exposedProps__.
   const ArrayPropertyExposedPropsProxy = new Proxy({}, {
     get: function(target, name) {
       // Test for index access
@@ -179,19 +175,17 @@ function validateArrayField(data, create
       return target[name];
     }
   };
 
   if (data) {
     data = Array.isArray(data) ? data : [data];
     let filtered = [];
     for (let obj of data) {
-      if (isVanillaObj(obj)) {
-        filtered.push(createCb(obj));
-      }
+      filtered.push(createCb(obj));
     }
     if (filtered.length === 0) {
       return undefined;
     }
     return new Proxy(filtered, ArrayPropertyHandler);
   }
   return undefined;
 }
@@ -209,74 +203,79 @@ const TELFIELD_PROPERTIES = ["tel"];
 
 function Contact() { }
 
 Contact.prototype = {
   // We need to create the content interfaces in these setters, otherwise when
   // we return these objects (e.g. from a find call), the values in the array
   // will be COW's, and content cannot see the properties.
   set email(aEmail) {
-    this._email = validateArrayField(aEmail, function(email) {
-      let obj = new this._window.ContactField();
+    this._email = aEmail;
+  },
+
+  get email() {
+    this._email = validateArrayField(this._email, function(email) {
+      let obj = this._window.ContactField._create(this._window, new ContactFieldImpl());
       obj.initialize(email.type, email.value, email.pref);
       return obj;
     }.bind(this));
-  },
-
-  get email() {
     return this._email;
   },
 
   set adr(aAdr) {
-    this._adr = validateArrayField(aAdr, function(adr) {
-      let obj = new this._window.ContactAddress();
+    this._adr = aAdr;
+  },
+
+  get adr() {
+    this._adr = validateArrayField(this._adr, function(adr) {
+      let obj = this._window.ContactAddress._create(this._window, new ContactAddressImpl());
       obj.initialize(adr.type, adr.streetAddress, adr.locality,
                      adr.region, adr.postalCode, adr.countryName,
                      adr.pref);
       return obj;
     }.bind(this));
-  },
-
-  get adr() {
     return this._adr;
   },
 
   set tel(aTel) {
-    this._tel = validateArrayField(aTel, function(tel) {
-      let obj = new this._window.ContactTelField();
+    this._tel = aTel;
+  },
+
+  get tel() {
+    this._tel = validateArrayField(this._tel, function(tel) {
+      let obj = this._window.ContactTelField._create(this._window, new ContactTelFieldImpl());
       obj.initialize(tel.type, tel.value, tel.carrier, tel.pref);
       return obj;
     }.bind(this));
-  },
-
-  get tel() {
     return this._tel;
   },
 
   set impp(aImpp) {
-    this._impp = validateArrayField(aImpp, function(impp) {
-      let obj = new this._window.ContactField();
+    this._impp = aImpp;
+  },
+
+  get impp() {
+    this._impp = validateArrayField(this._impp, function(impp) {
+      let obj = this._window.ContactField._create(this._window, new ContactFieldImpl());
       obj.initialize(impp.type, impp.value, impp.pref);
       return obj;
     }.bind(this));
-  },
-
-  get impp() {
     return this._impp;
   },
 
   set url(aUrl) {
-    this._url = validateArrayField(aUrl, function(url) {
-      let obj = new this._window.ContactField();
+    this._url = aUrl;
+  },
+
+  get url() {
+    this._url = validateArrayField(this._url, function(url) {
+      let obj = this._window.ContactField._create(this._window, new ContactFieldImpl());
       obj.initialize(url.type, url.value, url.pref);
       return obj;
     }.bind(this));
-  },
-
-  get url() {
     return this._url;
   },
 
   init: function(aWindow) {
     this._window = aWindow;
   },
 
   __init: function(aProp) {
@@ -612,41 +611,41 @@ ContactManager.prototype = {
       }
     }
 
     for (let prop of ADDRESS_PROPERTIES) {
       if (aContact[prop]) {
         newContact.properties[prop] = [];
         for (let i of aContact[prop]) {
           if (i) {
-            let json = ContactAddress.prototype.toJSON.apply(i, [true]);
+            let json = ContactAddressImpl.prototype.toJSON.apply(i, [true]);
             newContact.properties[prop].push(json);
           }
         }
       }
     }
 
     for (let prop of FIELD_PROPERTIES) {
       if (aContact[prop]) {
         newContact.properties[prop] = [];
         for (let i of aContact[prop]) {
           if (i) {
-            let json = ContactField.prototype.toJSON.apply(i, [true]);
+            let json = ContactFieldImpl.prototype.toJSON.apply(i, [true]);
             newContact.properties[prop].push(json);
           }
         }
       }
     }
 
     for (let prop of TELFIELD_PROPERTIES) {
       if (aContact[prop]) {
         newContact.properties[prop] = [];
         for (let i of aContact[prop]) {
           if (i) {
-            let json = ContactTelField.prototype.toJSON.apply(i, [true]);
+            let json = ContactTelFieldImpl.prototype.toJSON.apply(i, [true]);
             newContact.properties[prop].push(json);
           }
         }
       }
     }
 
     let request = this.createRequest();
     let requestID = this.getRequestId({request: request, reason: reason});
@@ -817,10 +816,10 @@ ContactManager.prototype = {
 
   classID: Components.ID("{8beb3a66-d70a-4111-b216-b8e995ad3aff}"),
   contractID: "@mozilla.org/contactManager;1",
   QueryInterface: XPCOMUtils.generateQI([Ci.nsISupportsWeakReference,
                                          Ci.nsIDOMGlobalPropertyInitializer]),
 };
 
 this.NSGetFactory = XPCOMUtils.generateNSGetFactory([
-  Contact, ContactManager, ContactAddress, ContactField, ContactTelField
+  Contact, ContactManager, ContactFieldImpl, ContactAddressImpl, ContactTelFieldImpl
 ]);