Bug 1336944 - Change Sqlite.jsm to bind TypedArrays as Blobs, not common Arrays. r=gijs draft
authorMarco Bonardo <mbonardo@mozilla.com>
Mon, 06 Feb 2017 19:30:19 +0100
changeset 479956 f959f0d1094e0f2252425ac63e6975032ddb01ef
parent 479417 7f1b358fb17dfd982c5e18c34d5735cd481c7f7c
child 544828 71d56bc7fdb85d0b3e0bf72e108292c058fafa56
push id44407
push usermak77@bonardo.net
push dateTue, 07 Feb 2017 15:41:49 +0000
reviewersgijs
bugs1336944
milestone54.0a1
Bug 1336944 - Change Sqlite.jsm to bind TypedArrays as Blobs, not common Arrays. r=gijs Currently an Array is bound as a blob. Unfortunately this occupies the best javascript code path to bind an array to an IN clause in the future. We would like Arrays to bind to IN lists, while still keeping a nice interface to bind blobs. This patch makes Uint8Array bind to blob, while Array is left available for future use. MozReview-Commit-ID: 7xzumBs8JTe
browser/components/migration/tests/unit/test_Chrome_passwords.js
toolkit/modules/Sqlite.jsm
toolkit/modules/tests/xpcshell/test_sqlite.js
--- a/browser/components/migration/tests/unit/test_Chrome_passwords.js
+++ b/browser/components/migration/tests/unit/test_Chrome_passwords.js
@@ -75,17 +75,17 @@ const TEST_LOGINS = [
     timesUsed: 1,
   },
 ];
 
 var crypto = new OSCrypto();
 var dbConn;
 
 function promiseSetPassword(login) {
-  let passwordValue = crypto.stringToArray(crypto.encryptData(login.password));
+  let passwordValue = new Uint8Array(crypto.stringToArray(crypto.encryptData(login.password)));
   return dbConn.execute(`UPDATE logins
                          SET password_value = :password_value
                          WHERE rowid = :rowid
                         `, { password_value: passwordValue,
                              rowid: login.id });
 }
 
 function checkLoginsAreEqual(passwordManagerLogin, chromeLogin, id) {
--- a/toolkit/modules/Sqlite.jsm
+++ b/toolkit/modules/Sqlite.jsm
@@ -675,17 +675,18 @@ ConnectionData.prototype = Object.freeze
    * reflection.
    */
   _bindParameters(statement, params) {
     if (!params) {
       return;
     }
 
     function bindParam(obj, key, val) {
-      let isBlob = Array.isArray(val);
+      let isBlob = val && typeof val == "object" &&
+                   val.constructor.name == "Uint8Array";
       let args = [key, val].concat(isBlob ? [val.length] : []);
       let methodName =
         `bind${isBlob ? "Blob" : ""}By${typeof key == "number" ? "Index" : "Name"}`;
       obj[methodName](...args);
     }
 
     if (Array.isArray(params)) {
       // It's an array of separate params.
--- a/toolkit/modules/tests/xpcshell/test_sqlite.js
+++ b/toolkit/modules/tests/xpcshell/test_sqlite.js
@@ -1098,25 +1098,25 @@ add_task(function* test_datatypes() {
                      real_col    REAL    NOT NULL,
                      numeric_col NUMERIC NOT NULL
                    )`);
   const bindings = [
     {
       null_col: null,
       integer_col: 12345,
       text_col: "qwerty",
-      blob_col: new Array(256).fill(undefined).map( (value, index) => index % 256 ),
+      blob_col: new Uint8Array(256).map( (value, index) => index % 256 ),
       real_col: 3.14159265359,
       numeric_col: true
     },
     {
       null_col: null,
       integer_col: -12345,
       text_col: "",
-      blob_col: new Array(256 * 2).fill(undefined).map( (value, index) => index % 256 ),
+      blob_col: new Uint8Array(256 * 2).map( (value, index) => index % 256 ),
       real_col: Number.NEGATIVE_INFINITY,
       numeric_col: false
     }
   ];
 
   yield c.execute(`INSERT INTO datatypes VALUES (
                      :null_col,
                      :integer_col,