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 479446 d3892e7f162d59d3a1732ddcec933ad074a1f209
parent 479417 7f1b358fb17dfd982c5e18c34d5735cd481c7f7c
child 544692 b77cd5c3d9af7b5e37e639b8e4f963f899c12b13
push id44262
push usermak77@bonardo.net
push dateMon, 06 Feb 2017 18:36:13 +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).fill(undefined).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).fill(undefined).map( (value, index) => index % 256 ),
       real_col: Number.NEGATIVE_INFINITY,
       numeric_col: false
     }
   ];
 
   yield c.execute(`INSERT INTO datatypes VALUES (
                      :null_col,
                      :integer_col,