Permalink
Browse files

Monotonic encoding/decoding is implemented for keys. However encoding…

… is done for utf16 (JavaScript char encoding), while built-in sqlite in Web SQL Database is configured to have utf8. Next TODO is just fix encoding format. So tests fail because of it.
  • Loading branch information...
1 parent e38099f commit aca67c6c8577c038e4c96752e10550aa8cb5feae Khamza Davletov committed Jul 17, 2012
View
22 IDBCursor.js
@@ -26,7 +26,7 @@ if (window.indexedDB.polyfill)
}
var request = new util.IDBRequest(this);
var me = this;
- objectStore.transaction._enqueueRequest(function (sqlTx, nextRequestCallback)
+ objectStore.transaction._queueOperation(function (sqlTx, nextRequestCallback)
{
objectStore._insertOrReplaceRecord(
{
@@ -62,7 +62,7 @@ if (window.indexedDB.polyfill)
var request = new util.IDBRequest(this);
var me = this;
- objectStore.transaction._enqueueRequest(function (sqlTx, nextRequestCallback)
+ objectStore.transaction._queueOperation(function (sqlTx, nextRequestCallback)
{
objectStore._deleteRecord(sqlTx, me._effectiveKey,
function ()
@@ -128,20 +128,20 @@ if (window.indexedDB.polyfill)
{
var tx = me.source.transaction;
me._request.readyState = util.IDBRequest.LOADING;
- tx._enqueueRequest(function (sqlTx, nextRequestCallback)
+ tx._queueOperation(function (sqlTx, nextRequestCallback)
{
var sql = ["SELECT key, value FROM [" + me.source.name + "]"];
var where = [];
var args = [];
if (filter.lower != null)
{
where.push("(key >" + (filter.lowerOpen ? "" : "=") + " ?)");
- args.push(w_JSON.stringify(filter.lower));
+ args.push(util.encodeKey(filter.lower));
}
if (filter.upper != null)
{
where.push("(key <" + (filter.upperOpen ? "" : "=") + " ?)");
- args.push(w_JSON.stringify(filter.upper));
+ args.push(util.encodeKey(filter.upper));
}
if (where.length > 0)
{
@@ -165,7 +165,7 @@ if (window.indexedDB.polyfill)
{
var found = results.rows.item(filter.count - 1);
me._effectiveKey = found.key;
- me.key = me.primaryKey = w_JSON.parse(found.key);
+ me.key = me.primaryKey = util.decodeKey(found.key);
if (typeof me.value !== "undefined") me.value = w_JSON.parse(found.value);
me._gotValue = true;
request.result = me;
@@ -187,7 +187,7 @@ if (window.indexedDB.polyfill)
{
var tx = me.source.objectStore.transaction;
me._request.readyState = util.IDBRequest.LOADING;
- tx._enqueueRequest(function (sqlTx, nextRequestCallback)
+ tx._queueOperation(function (sqlTx, nextRequestCallback)
{
var withValue = me instanceof IDBCursorWithValue;
var desc = isDesc(me);
@@ -203,7 +203,7 @@ if (window.indexedDB.polyfill)
var where = [], args = [];
if (filter.lower != null)
{
- var strLower = w_JSON.stringify(filter.lower);
+ var strLower = util.encodeKey(filter.lower);
args.push(strLower);
if (filter.lowerOpen)
{
@@ -224,7 +224,7 @@ if (window.indexedDB.polyfill)
}
if (filter.upper != null)
{
- var strUpper = w_JSON.stringify(filter.upper);
+ var strUpper = util.encodeKey(filter.upper);
args.push(strUpper);
if (filter.upperOpen)
{
@@ -265,9 +265,9 @@ if (window.indexedDB.polyfill)
else
{
var found = results.rows.item(filter.count - 1);
- me.key = w_JSON.parse(found.key);
+ me.key = util.decodeKey(found.key);
me._effectiveKey = found.primaryKey;
- me.primaryKey = w_JSON.parse(found.primaryKey);
+ me.primaryKey = util.decodeKey(found.primaryKey);
if (typeof me.value !== "undefined") me.value = w_JSON.parse(found.value);
me._gotValue = true;
request.result = me;
View
10 IDBDatabase.js
@@ -54,9 +54,9 @@ if (window.indexedDB.polyfill)
me.objectStoreNames.push(name);
me._objectStores[name] = objectStore;
};
- tx._enqueueRequest(function (sqlTx, nextRequestCallback)
+ tx._queueOperation(function (sqlTx, nextRequestCallback)
{
- sqlTx.executeSql("DROP TABLE \"" + name + "\"", null, null, errorCallback);
+ sqlTx.executeSql("DROP TABLE [" + name + "]", null, null, errorCallback);
sqlTx.executeSql("DELETE FROM " + indexedDB.SCHEMA_TABLE + " WHERE type = 'table' AND name = ?",
[name], null, errorCallback);
@@ -147,12 +147,12 @@ if (window.indexedDB.polyfill)
util.arrayRemove(me.objectStoreNames, name);
delete me._objectStores[name];
};
- me._versionChangeTransaction._enqueueRequest(function (sqlTx, nextRequestCallback)
+ me._versionChangeTransaction._queueOperation(function (sqlTx, nextRequestCallback)
{
- sqlTx.executeSql("CREATE TABLE \"" + name + "\" (id INTEGER PRIMARY KEY AUTOINCREMENT, " +
+ sqlTx.executeSql("CREATE TABLE [" + name + "] (id INTEGER PRIMARY KEY AUTOINCREMENT, " +
"key TEXT UNIQUE, value BLOB)", [], null, errorCallback);
- sqlTx.executeSql("CREATE INDEX INDEX_" + name + "_key ON \"" + name + "\" (key)", [], null, errorCallback);
+ sqlTx.executeSql("CREATE INDEX INDEX_" + name + "_key ON [" + name + "] (key)", [], null, errorCallback);
sqlTx.executeSql("INSERT INTO " + indexedDB.SCHEMA_TABLE +
" (type, name, keyPath, autoInc) VALUES ('table', ?, ?, ?)",
View
7 IDBFactory.js
@@ -84,7 +84,7 @@ if (window.indexedDB.polyfill)
var tx = new util.IDBTransaction(connection, [], util.IDBTransaction.VERSION_CHANGE);
if (oldVersion == 0)
{
- tx._enqueueRequest(function (sqlTx, nextRequestCallback)
+ tx._queueOperation(function (sqlTx, nextRequestCallback)
{
sqlTx.executeSql("CREATE TABLE [" + indexedDB.SCHEMA_TABLE + "] (" +
"id INTEGER PRIMARY KEY AUTOINCREMENT, " +
@@ -103,7 +103,7 @@ if (window.indexedDB.polyfill)
nextRequestCallback();
});
}
- tx._enqueueRequest(function (sqlTx, nextRequestCallback)
+ tx._queueOperation(function (sqlTx, nextRequestCallback)
{
connection._loadObjectStores(sqlTx,
function ()
@@ -200,7 +200,8 @@ if (window.indexedDB.polyfill)
// IDBFactory.cmp
indexedDB.cmp = function (first, second)
{
- // TODO: Compare according to doc
+ first = util.encodeKey(first);
+ second = util.encodeKey(second);
return first > second ? 1 : (first == second ? 0 : -1);
};
View
8 IDBIndex.js
@@ -26,7 +26,7 @@ if (window.indexedDB.polyfill)
key = util.validateKeyOrRange(key);
var request = new util.IDBRequest(this);
var me = this;
- this.objectStore.transaction._enqueueRequest(function (sqlTx, nextRequestCallback)
+ this.objectStore.transaction._queueOperation(function (sqlTx, nextRequestCallback)
{
var sql = ["SELECT s.value FROM [" + util.indexTable(me) + "] AS i INNER JOIN"];
sql.push("[" + me.objectStore.name + "] AS s ON s.id = i.recordId")
@@ -65,7 +65,7 @@ if (window.indexedDB.polyfill)
key = util.validateKeyOrRange(key);
var request = new util.IDBRequest(this);
var me = this;
- this.objectStore.transaction._enqueueRequest(function (sqlTx, nextRequestCallback)
+ this.objectStore.transaction._queueOperation(function (sqlTx, nextRequestCallback)
{
var sql = ["SELECT primaryKey FROM [" + util.indexTable(me) + "]"];
var args = [];
@@ -85,7 +85,7 @@ if (window.indexedDB.polyfill)
function (_, results)
{
request.result = results.rows.length > 0 ?
- w_JSON.parse(results.rows.item(0).primaryKey) : undefined;
+ util.decodeKey(results.rows.item(0).primaryKey) : undefined;
if (request.onsuccess) request.onsuccess(util.event("success", request));
},
function (_, sqlError)
@@ -104,7 +104,7 @@ if (window.indexedDB.polyfill)
key = util.validateKeyOrRange(key);
var request = new util.IDBRequest(this);
var me = this;
- this.objectStore.transaction._enqueueRequest(function (sqlTx, nextRequestCallback)
+ this.objectStore.transaction._queueOperation(function (sqlTx, nextRequestCallback)
{
var sql = ["SELECT COUNT(recordId) AS 'count' FROM [" + util.indexTable(me) + "]"];
var args = [];
View
4 IDBKeyRange.js
@@ -64,12 +64,12 @@ if (window.indexedDB.polyfill)
if (hasLower)
{
sql.push("(? <" + (this.lowerOpen ? "" : "=") + " " + keyColumnName + ")");
- args.push(w_JSON.stringify(this.lower));
+ args.push(util.encodeKey(this.lower));
}
if (hasUpper)
{
sql.push("(" + keyColumnName + " <" + (this.upperOpen ? "" : "=") + " ?)");
- args.push(w_JSON.stringify(this.upper));
+ args.push(util.encodeKey(this.upper));
}
}
return { sql : sql.join(" AND "), args : args };
View
56 IDBObjectStore.js
@@ -28,10 +28,9 @@ if (window.indexedDB.polyfill)
{
util.IDBTransaction._assertNotReadOnly(me.transaction);
var validation = validateObjectStoreKey(me.keyPath, me.autoIncrement, value, key);
- var key = validation.key, strKey = validation.str;
var request = new util.IDBRequest(me);
- me.transaction._enqueueRequest(function (sqlTx, nextRequestCallback)
+ me.transaction._queueOperation(function (sqlTx, nextRequestCallback)
{
var context = {
request : request,
@@ -40,7 +39,7 @@ if (window.indexedDB.polyfill)
noOverwrite : noOverwrite,
value : value
};
- runStepsForStoringRecord(context, key, strKey);
+ runStepsForStoringRecord(context, validation.key, validation.encodedKey);
});
return request;
}
@@ -60,13 +59,13 @@ if (window.indexedDB.polyfill)
}
else
{
- str = w_JSON.stringify(key);
- if (util.notValidKey(str)) throw util.error("DataError");
+ encodedKey = util.encodeKey(key);
+ if (encodedKey === null) throw util.error("DataError");
}
- return { key : key, str : str };
+ return { key : key, encodedKey : encodedKey };
}
- function runStepsForStoringRecord(context, key, strKey)
+ function runStepsForStoringRecord(context, key, encodedKey)
{
var request = context.request;
var me = request.source;
@@ -85,7 +84,7 @@ if (window.indexedDB.polyfill)
if (key == null)
{
key = currentNo;
- strKey = key.toString();
+ encodedKey = key.toString();
if (me.keyPath != null)
{
assignKeyToValue(context.value, me.keyPath, key);
@@ -96,7 +95,7 @@ if (window.indexedDB.polyfill)
incrementCurrentNumber(sqlTx, me.name, Math.floor(key + 1));
}
context.sqlTx = sqlTx;
- me._insertOrReplaceRecord(context, strKey);
+ me._insertOrReplaceRecord(context, encodedKey);
},
function (_, sqlError)
{
@@ -107,7 +106,7 @@ if (window.indexedDB.polyfill)
}
else
{
- me._insertOrReplaceRecord(context, strKey);
+ me._insertOrReplaceRecord(context, encodedKey);
}
}
@@ -185,22 +184,23 @@ if (window.indexedDB.polyfill)
{
if (key.length == 0) return null;
}
- if (util.notValidKey(w_JSON.stringify(key))) return null;
+ var encodedKey = util.encodeKey(key);
+ if (encodedKey === null) return null;
if (index.multiEntry && (key instanceof Array))
{
// clean-up
- var tmp = [], str;
+ var tmp = [];
for (var i = 0; i < key.length; i++)
{
- str = w_JSON.stringify(key[i]);
- if (tmp.indexOf(str) >= 0 || util.notValidKey(str)) continue;
- tmp.push(str);
+ encodedKey = util.encodeKey(key[i]);
+ if (encodedKey === null || tmp.indexOf(encodedKey) >= 0) continue;
+ tmp.push(encodedKey);
}
if (tmp.length == 0) return null;
return tmp;
}
- return w_JSON.stringify(key);
+ return encodedKey;
}
function storeIndex(context, index, strKey, isLast)
@@ -250,7 +250,7 @@ if (window.indexedDB.polyfill)
key = util.validateKeyOrRange(key);
var request = new util.IDBRequest(this);
var me = this;
- this.transaction._enqueueRequest(function (sqlTx, nextRequestCallback)
+ this.transaction._queueOperation(function (sqlTx, nextRequestCallback)
{
me._deleteRecord(sqlTx, key,
function ()
@@ -273,7 +273,7 @@ if (window.indexedDB.polyfill)
key = util.validateKeyOrRange(key);
var request = new util.IDBRequest(this);
var me = this;
- me.transaction._enqueueRequest(function (sqlTx, nextRequestCallback)
+ me.transaction._queueOperation(function (sqlTx, nextRequestCallback)
{
var where = "", args = [];
if (key instanceof util.IDBKeyRange)
@@ -310,7 +310,7 @@ if (window.indexedDB.polyfill)
util.IDBTransaction._assertNotReadOnly(this.transaction);
var request = new util.IDBRequest(this);
var me = this;
- this.transaction._enqueueRequest(function (sqlTx, nextRequestCallback)
+ this.transaction._queueOperation(function (sqlTx, nextRequestCallback)
{
var errorCallback = function (_, sqlError)
{
@@ -391,7 +391,7 @@ if (window.indexedDB.polyfill)
me.indexNames.push(indexName);
me._indexes[indexName] = index;
};
- this.transaction._enqueueRequest(function (sqlTx, nextRequestCallback)
+ this.transaction._queueOperation(function (sqlTx, nextRequestCallback)
{
sqlTx.executeSql("DROP TABLE " + util.indexTable(me.name, indexName), null, null, errorCallback);
@@ -407,7 +407,7 @@ if (window.indexedDB.polyfill)
key = util.validateKeyOrRange(key);
var request = new util.IDBRequest(this);
var me = this;
- this.transaction._enqueueRequest(function (sqlTx, nextRequestCallback)
+ this.transaction._queueOperation(function (sqlTx, nextRequestCallback)
{
var where = "", args = [];
if (key instanceof util.IDBKeyRange)
@@ -466,12 +466,12 @@ if (window.indexedDB.polyfill)
sqlTx.executeSql("DELETE FROM [" + objectStore.name + "] " + where, args, onsuccess, onerror);
};
- IDBObjectStore.prototype._insertOrReplaceRecord = function (context, strKey)
+ IDBObjectStore.prototype._insertOrReplaceRecord = function (context, encodedKey)
{
var request = context.request;
if (!context.noOverwrite)
{
- this._deleteRecord(context.sqlTx, strKey, null,
+ this._deleteRecord(context.sqlTx, encodedKey, null,
function (_, sqlError)
{
request.error = sqlError;
@@ -480,14 +480,14 @@ if (window.indexedDB.polyfill)
});
}
var me = this;
- var strValue = w_JSON.stringify(context.value);
+ var encodedValue = w_JSON.stringify(context.value);
context.sqlTx.executeSql("INSERT INTO [" + me.name + "] (key, value) VALUES (?, ?)",
- [strKey, strValue],
+ [encodedKey, encodedValue],
function (sqlTx, results)
{
context.objectStore = me;
context.sqlTx = sqlTx;
- context.primaryKey = strKey;
+ context.primaryKey = encodedKey;
context.recordId = results.insertId;
storeIndexes(context);
},
@@ -519,13 +519,13 @@ if (window.indexedDB.polyfill)
util.arrayRemove(me.indexNames, name);
delete me._indexes[name];
};
- me.transaction._enqueueRequest(function (sqlTx, nextRequestCallback)
+ me.transaction._queueOperation(function (sqlTx, nextRequestCallback)
{
sqlTx.executeSql("CREATE TABLE " + util.indexTable(me.name, name) + " (recordId INTEGER, key TEXT" +
(unique ? " UNIQUE" : "") + ", primaryKey TEXT)", null, null, errorCallback);
sqlTx.executeSql("INSERT INTO " + indexedDB.SCHEMA_TABLE +
- " (name, type, keyPath, tableId, \"unique\", multiEntry) VALUES (?, 'index', ?, " +
+ " (name, type, keyPath, tableId, [unique], multiEntry) VALUES (?, 'index', ?, " +
"(SELECT Id FROM " + indexedDB.SCHEMA_TABLE + " WHERE type = 'table' AND name = ?), ?, ?)",
[name, w_JSON.stringify(keyPath), me.name, unique ? 1 : 0, multiEntry ? 1 : 0],
null, errorCallback);
View
4 IDBTransaction.js
@@ -83,13 +83,13 @@ if (window.indexedDB.polyfill)
IDBTransaction.prototype.abort = function ()
{
if (!this._active) throw util.error("InvalidStateError");
- this._enqueueRequest(function (sqlTx, nextRequestCallback)
+ this._queueOperation(function (sqlTx, nextRequestCallback)
{
throw util.error("AbortError");
});
};
- IDBTransaction.prototype._enqueueRequest = function (sqlTxCallback)
+ IDBTransaction.prototype._queueOperation = function (sqlTxCallback)
{
validateActive(this);
this._requests.push(sqlTxCallback);
View
62 indexedDB.init.js
@@ -1,6 +1,5 @@
(function(window, undefined)
{
-
var indexedDB = window.indexedDB = window.indexedDB || window.mozIndexedDB ||
window.webkitIndexedDB || window.msIndexedDB || { polyfill : true };
@@ -16,7 +15,7 @@
indexedDB.DB_PREFIX = "__IndexedDB__";
indexedDB.DB_DESCRIPTION = "IndexedDB ";
indexedDB.DEFAULT_DB_SIZE = 5 * 1024 * 1024;
- indexedDB.CURSOR_CHUNK_SIZE = 10;
+ //indexedDB.CURSOR_CHUNK_SIZE = 10;
// Data types
indexedDB.DOMStringList = function () { };
@@ -27,7 +26,7 @@
return this.indexOf(str) >= 0;
};
-
+ // Util
indexedDB.util = new (function ()
{
this.async = function (fn, async)
@@ -119,55 +118,44 @@
return key;
};
- this.notValidKey = function (strKey)
+ this.validateKeyOrRange = function (encodedKey)
{
- // TODO: key validation according to spec
- if (strKey === "true" || strKey === "false") return true;
-
- if ((/[,[]{.*?}[,\]]/).test(strKey) ||
- (/^{.*?}$/).test(strKey) ||
- (/[,[](true|false)[,\]]/).test(strKey)) return true;
-
- return false;
- };
-
- this.validateKeyOrRange = function (key)
- {
- if (!(key instanceof this.IDBKeyRange))
+ if (!(encodedKey instanceof this.IDBKeyRange))
{
- key = w_JSON.stringify(key);
- if (this.notValidKey(key)) throw this.error("DataError");
+ encodedKey = this.encodeKey(encodedKey);
+ if (encodedKey === null) throw this.error("DataError");
}
- return key;
+ return encodedKey;
};
this.wait = function (conditionFunc, bodyFunc, async)
{
var me = this;
this.async(function ()
- {
- if (conditionFunc()) bodyFunc();
- else
{
- w_setTimeout(function ()
+ if (conditionFunc()) bodyFunc();
+ else
{
- me.wait(conditionFunc, bodyFunc);
- }, 10);
- }
- },
- async);
- }
+ w_setTimeout(function ()
+ {
+ me.wait(conditionFunc, bodyFunc);
+ }, 10);
+ }
+ },
+ async);
+ };
});
+
// Classes
var IDBVersionChangeEvent = window.IDBVersionChangeEvent = indexedDB.util.IDBVersionChangeEvent =
function (type, target, oldVersion, newVersion)
- {
- this.type = type;
- this.target = this.currentTarget = target;
- this.oldVersion = oldVersion;
- this.newVersion = newVersion;
- };
+ {
+ this.type = type;
+ this.target = this.currentTarget = target;
+ this.oldVersion = oldVersion;
+ this.newVersion = newVersion;
+ };
var IDBDatabaseException = window.IDBDatabaseException = indexedDB.util.IDBDatabaseException =
{
@@ -185,8 +173,8 @@
VERSION_ERR : 12
};
+
// Cached
var w_setTimeout = window.setTimeout;
- var w_JSON = window.JSON;
}(window));
View
1 indexedDB.polyfill.debug.js
@@ -3,6 +3,7 @@
var files = [
"lib/jquery-1.7.2.js",
"indexedDB.init.js",
+ "key.js",
"IDBRequest.js",
"IDBFactory.js",
"IDBDatabase.js",
View
416 key.js
@@ -0,0 +1,416 @@
+/*
+ Source: http://hg.mozilla.org/mozilla-central/file/895e12563245/dom/indexedDB/Key.cpp
+ ---
+ Here's how we encode keys:
+
+ Basic strategy is the following
+
+ Numbers: 1 n n n n n n n n ("n"s are encoded 64bit float)
+ Dates: 2 n n n n n n n n ("n"s are encoded 64bit float)
+ Strings: 3 s s s ... 0 ("s"s are encoded unicode bytes)
+ Arrays: 4 i i i ... 0 ("i"s are encoded array items)
+
+
+ When encoding floats, 64bit IEEE 754 are almost sortable, except that
+ positive sort lower than negative, and negative sort descending. So we use
+ the following encoding:
+
+ value < 0 ?
+ (-to64bitInt(value)) :
+ (to64bitInt(value) | 0x8000000000000000)
+
+
+ When encoding strings, we use variable-size encoding per the following table
+
+ Chars 0 - 7E are encoded as 0xxxxxxx with 1 added
+ Chars 7F - (3FFF+7F) are encoded as 10xxxxxx xxxxxxxx with 7F subtracted
+ Chars (3FFF+80) - FFFF are encoded as 11xxxxxx xxxxxxxx xx000000
+
+ This ensures that the first byte is never encoded as 0, which means that the
+ string terminator (per basic-stategy table) sorts before any character.
+ The reason that (3FFF+80) - FFFF is encoded "shifted up" 6 bits is to maximize
+ the chance that the last character is 0. See below for why.
+
+
+ When encoding Arrays, we use an additional trick. Rather than adding a byte
+ containing the value '4' to indicate type, we instead add 4 to the next byte.
+ This is usually the byte containing the type of the first item in the array.
+ So simple examples are
+
+ ["foo"] 7 s s s 0 0 // 7 is 3 + 4
+ [1, 2] 5 n n n n n n n n 1 n n n n n n n n 0 // 5 is 1 + 4
+
+ Whe do this iteratively if the first item in the array is also an array
+
+ [["foo"]] 11 s s s 0 0 0
+
+ However, to avoid overflow in the byte, we only do this 3 times. If the first
+ item in an array is an array, and that array also has an array as first item,
+ we simply write out the total value accumulated so far and then follow the
+ "normal" rules.
+
+ [[["foo"]]] 12 3 s s s 0 0 0 0
+
+ There is another edge case that can happen though, which is that the array
+ doesn't have a first item to which we can add 4 to the type. Instead the
+ next byte would normally be the array terminator (per basic-strategy table)
+ so we simply add the 4 there.
+
+ [[]] 8 0 // 8 is 4 + 4 + 0
+ [] 4 // 4 is 4 + 0
+ [[], "foo"] 8 3 s s s 0 0 // 8 is 4 + 4 + 0
+
+ Note that the max-3-times rule kicks in before we get a chance to add to the
+ array terminator
+
+ [[[]]] 12 0 0 0 // 12 is 4 + 4 + 4
+
+ We could use a much higher number than 3 at no complexity or performance cost,
+ however it seems unlikely that it'll make a practical difference, and the low
+ limit makes testing eaiser.
+
+
+ As a final optimization we do a post-encoding step which drops all 0s at the
+ end of the encoded buffer.
+
+ "foo" // 3 s s s
+ 1 // 1 bf f0
+ ["a", "b"] // 7 s 3 s
+ [1, 2] // 5 bf f0 0 0 0 0 0 0 1 c0
+ [[]] // 8
+*/
+
+if (window.indexedDB.polyfill)
+(function(util, undefined)
+{
+ var ARRAY_TERMINATOR = { };
+ var BYTE_TERMINATOR = 0;
+ var TYPE_NUMBER = 1;
+ var TYPE_DATE = 2;
+ var TYPE_STRING = 3;
+ var TYPE_ARRAY = 4;
+ var MAX_TYPE_BYTE_SIZE = 12; // NOTE: Cannot be greater than 255
+
+ util.encodeKey = function (key)
+ {
+ var stack = [key], buffer = [], type = 0, dataType, obj, tmp;
+ while ((obj = stack.pop()) !== undefined)
+ {
+ if (type % 4 === 0 && type + TYPE_ARRAY > MAX_TYPE_BYTE_SIZE)
+ {
+ buffer.push(type);
+ type = 0;
+ }
+ dataType = typeof obj;
+ if (obj instanceof Array)
+ {
+ type += TYPE_ARRAY;
+ if (obj.length > 0)
+ {
+ stack.push(ARRAY_TERMINATOR);
+ var i = obj.length;
+ while (i--) stack.push(obj[i]);
+ continue;
+ }
+ else
+ {
+ buffer.push(type);
+ }
+ }
+ else if (dataType === "number")
+ {
+ type += TYPE_NUMBER;
+ buffer.push(type);
+ encodeNumber(buffer, obj);
+ }
+ else if (obj instanceof Date)
+ {
+ type += TYPE_DATE;
+ buffer.push(type);
+ encodeNumber(buffer, obj.valueOf());
+ }
+ else if (dataType === "string")
+ {
+ type += TYPE_STRING;
+ buffer.push(type);
+ encodeString(buffer, obj);
+ }
+ else if (obj === ARRAY_TERMINATOR)
+ {
+ buffer.push(BYTE_TERMINATOR);
+ }
+ else return null;
+ type = 0;
+ }
+ return bufferToUnicodeString(buffer);
+ };
+
+ util.decodeKey = function (encodedKey)
+ {
+ var rootArray = []; // one-element root array that contains the result
+ var parentArray = rootArray;
+ var type, arrayStack = [], depth, tmp;
+ var byteReader = new ByteReader(encodedKey);
+ while (byteReader.read() != null)
+ {
+ if (byteReader.current === 0) // end of array
+ {
+ parentArray = arrayStack.pop();
+ continue;
+ }
+ if (byteReader.current === null)
+ {
+ return rootArray[0];
+ }
+ do
+ {
+ depth = byteReader.current / 4 | 0;
+ type = byteReader.current % 4;
+ for (var i = 0; i < depth; i++)
+ {
+ tmp = [];
+ parentArray.push(tmp);
+ arrayStack.push(parentArray);
+ parentArray = tmp;
+ }
+ if (type === 0 && byteReader.current + TYPE_ARRAY > MAX_TYPE_BYTE_SIZE)
+ {
+ byteReader.read();
+ }
+ else break;
+ } while (true);
+
+ if (type === TYPE_NUMBER)
+ {
+ parentArray.push(decodeNumber(byteReader));
+ }
+ else if (type === TYPE_DATE)
+ {
+ parentArray.push(new Date(decodeNumber(byteReader)));
+ }
+ else if (type === TYPE_STRING)
+ {
+ parentArray.push(decodeString(byteReader));
+ }
+ else if (type === 0) // empty array case
+ {
+ parentArray = arrayStack.pop();
+ }
+ }
+ return rootArray[0];
+ };
+
+ // Utils
+ var p16 = 0x10000;
+ var p32 = 0x100000000;
+ var p48 = 0x1000000000000;
+ var p52 = 0x10000000000000;
+ var pNeg1074 = 5e-324; // 2^-1074);
+ var pNeg1022 = 2.2250738585072014e-308; // 2^-1022
+
+ function ieee754(number)
+ {
+ var s = 0, e = 0, m = 0;
+ if (number !== 0)
+ {
+ if (isFinite(number))
+ {
+ if (number < 0)
+ {
+ s = 1;
+ number = -number;
+ }
+ var p = 0;
+ if (number >= pNeg1022)
+ {
+ var n = number;
+ while (n < 1) { p--; n *= 2; }
+ while (n >= 2) { p++; n /= 2; }
+ e = p + 1023;
+ }
+ m = e ? Math.floor((number / Math.pow(2, p) - 1) * p52) : Math.floor(number / pNeg1074);
+ }
+ else
+ {
+ e = 0x7FF;
+ if (isNaN(number))
+ {
+ m = 2251799813685248; // QNan
+ }
+ else
+ {
+ if (number === -Infinity) s = 1;
+ }
+ }
+ }
+ return { sign : s, exponent : e, mantissa : m };
+ }
+
+ function encodeNumber(buffer, number)
+ {
+ var number = ieee754(number);
+ if (number.sign)
+ {
+ number.mantissa = p52 - 1 - number.mantissa;
+ number.exponent = 0x7FF - number.exponent;
+ }
+ var word, m = number.mantissa;
+
+ buffer.push((number.sign ? 0 : 0x80) | (number.exponent >> 4));
+ buffer.push((number.exponent & 0xF) << 4 | (0 | m / p48));
+
+ m %= p48; word = 0 | m / p32;
+ buffer.push(word >> 8, word & 0xFF);
+
+ m %= p32; word = 0 | m / p16;
+ buffer.push(word >> 8, word & 0xFF);
+
+ word = m % p16;
+ buffer.push(word >> 8, word & 0xFF);
+ }
+
+ function decodeNumber(byteReader)
+ {
+ var b = byteReader.read();
+ var sign = b >> 7 ? false : true;
+
+ var s = sign ? -1 : 1;
+
+ var e = (b & 0x7F) << 4;
+ b = byteReader.read();
+ e += b >> 4;
+ if (sign) e = 0x7FF - e;
+
+ var tmp = [sign ? (0xF - (b & 0xF)) : b & 0xF];
+ var i = 6;
+ while (i--) tmp.push(sign ? (0xFF - byteReader.read()) : byteReader.read());
+
+ var m = 0; i = 7;
+ while (i--)
+ {
+ m = m / 256 + tmp[i];
+ }
+ m /= 16;
+
+ if (m === 0 && e === 0) return 0;
+ return (m + 1) * Math.pow(2, e - 1023) * s;
+ }
+
+ var secondLayer = 0x3FFF + 0x7F;
+
+ function encodeString(buffer, string)
+ {
+ /* 3 layers:
+ Chars 0 - 7E are encoded as 0xxxxxxx with 1 added
+ Chars 7F - (3FFF+7F) are encoded as 10xxxxxx xxxxxxxx with 7F subtracted
+ Chars (3FFF+80) - FFFF are encoded as 11xxxxxx xxxxxxxx xx000000
+ */
+ for (var i = 0; i < string.length; i++)
+ {
+ var code = string.charCodeAt(i);
+ if (code <= 0x7E)
+ {
+ buffer.push(code + 1);
+ }
+ else if (code <= secondLayer)
+ {
+ code -= 0x7F;
+ buffer.push(0x80 | code >> 8, code & 0xFF);
+ }
+ else
+ {
+ buffer.push(0xC0 | code >> 10, code >> 2 | 0xFF, (code | 3) << 6);
+ }
+ }
+ buffer.push(BYTE_TERMINATOR);
+ }
+
+ function decodeString(byteReader)
+ {
+ var buffer = [], layer = 0, unicode = 0, count = 0, byte, tmp;
+ while (true)
+ {
+ byte = byteReader.read();
+ if (byte === 0 || byte == null) break;
+
+ if (layer === 0)
+ {
+ tmp = byte >> 6;
+ if (tmp < 2)
+ {
+ buffer.push(String.fromCharCode(byte - 1));
+ }
+ else // tmp equals 2 or 3
+ {
+ layer = tmp;
+ unicode = byte << 10;
+ count++;
+ }
+ }
+ else if (layer === 2)
+ {
+ buffer.push(String.fromCharCode(unicode + byte + 0x7F));
+ layer = unicode = count = 0;
+ }
+ else // layer === 3
+ {
+ if (count === 2)
+ {
+ unicode += byte << 2;
+ count++;
+ }
+ else // count === 3
+ {
+ buffer.push(String.fromCharCode(unicode | byte >> 6));
+ layer = unicode = count = 0;
+ }
+ }
+ }
+ return buffer.join("");
+ }
+
+ var ByteReader = function (string)
+ {
+ this.current = null;
+
+ var string = string;
+ var code, index = -1, high = false;
+
+ this.read = function ()
+ {
+ high = !high;
+ if (high)
+ {
+ index++;
+ code = string.charCodeAt(index);
+ }
+ if (isNaN(code))
+ {
+ this.current = null;
+ }
+ else
+ {
+ this.current = high ? code >> 8 : code & 0xFF;
+ }
+ return this.current;
+ }
+ };
+
+ function bufferToUnicodeString(buffer)
+ {
+ var index = buffer.length;
+ while (buffer[--index] === 0);
+ buffer.length = ++index;
+
+ if ((index & 1) === 1) buffer.push(0);
+ var result = [], length = buffer.length >> 1;
+
+ for (var i = 0; i < length; i++)
+ {
+ index = i << 1;
+ result.push(String.fromCharCode(buffer[index] << 8 | buffer[index + 1]));
+ }
+ return result.join("");
+ }
+
+}(window.indexedDB.util));
View
12 lib/qunit.js
@@ -1467,7 +1467,7 @@ QUnit.equiv = (function() {
*/
QUnit.jsDump = (function() {
function quote( str ) {
- return '"' + str.toString().replace( /"/g, '\\"' ) + '"';
+ return '"' + encodedKey.toString().replace( /"/g, '\\"' ) + '"';
}
function literal( o ) {
return o + "";
@@ -1824,19 +1824,19 @@ QUnit.diff = (function() {
if ( out.n.length === 0 ) {
for ( i = 0; i < out.o.length; i++ ) {
- str += "<del>" + out.o[i] + oSpace[i] + "</del>";
+ encodedKey += "<del>" + out.o[i] + oSpace[i] + "</del>";
}
}
else {
if ( out.n[0].text == null ) {
for ( n = 0; n < out.o.length && out.o[n].text == null; n++ ) {
- str += "<del>" + out.o[n] + oSpace[n] + "</del>";
+ encodedKey += "<del>" + out.o[n] + oSpace[n] + "</del>";
}
}
for ( i = 0; i < out.n.length; i++ ) {
if (out.n[i].text == null) {
- str += "<ins>" + out.n[i] + nSpace[i] + "</ins>";
+ encodedKey += "<ins>" + out.n[i] + nSpace[i] + "</ins>";
}
else {
// `pre` initialized at top of scope
@@ -1845,12 +1845,12 @@ QUnit.diff = (function() {
for ( n = out.n[i].row + 1; n < out.o.length && out.o[n].text == null; n++ ) {
pre += "<del>" + out.o[n] + oSpace[n] + "</del>";
}
- str += " " + out.n[i].text + nSpace[i] + pre;
+ encodedKey += " " + out.n[i].text + nSpace[i] + pre;
}
}
}
- return str;
+ return encodedKey;
};
}());
View
398 test/IDBFactoryTests.js
@@ -1,190 +1,214 @@
var IDBFactoryTests = new (function ()
{
- // Run
- this.run = function ()
- {
- /*
- * 1. If !version && !database => set database version to 1 (Chrome: '', Firefox: 1);
- * 2. If version && !database => set database version to 0 (Chrome: '', Firefox: version);
- * 3. If !version && database => use the current database version;
- * 4. If version && database =>
- * a. if (version < db.version) => error;
- * b. if (version > db.version) => VERSION_CHANGE;
- * c. otherwise, just open;
- */
- module("IDBFactory.open");
- _test("Create database with no version specified", testCreateDatabase);
- _test("Create database with version", testCreateDatabaseWithVersion);
- _test("Open existing database with no version specified", testOpenExistingDatabase);
- _test("Open existing database with lower version", testOpenExistingDatabaseWithLowerVersion);
- _test("Open existing database with higher version", testOpenExistingDatabaseWithHigherVersion);
- _test("Open existing database with same version", testOpenExistingDatabaseWithSameVersion);
-
- module("IDBFactory.deleteDatabase");
- };
-
- // Environment
- var env =
- {
- // Created
- db : {
- name : "TestDatabase",
- version : 20
- },
-
- // Not created
- db2 : {
- name : "TestDatabase2",
- version : 10
- }
- };
-
- // Tests
- function testCreateDatabase()
- {
- expect(8);
- var request = indexedDB.open(env.db2.name);
- notEqual(request, null, "IDBOpenDBRequest object is null.");
-
- request.onupgradeneeded = function (e)
- {
- ok(true, "Triggered onupgradeneeded.");
- var db = e.currentTarget.result;
- notEqual(db, null, "Database connection is null.");
- equal(e.oldVersion, 0, "oldVersion is 0.");
- equal(e.newVersion, 1, "newVersion is 1.");
- equal(db.version, 1, "Database version mismatch.");
- };
- request.onsuccess = function (e)
- {
- ok(true, "Triggered onsuccess.");
- equal(request.result.version, 1, "Database version mismatch.");
- request.result.close();
- start();
- };
- request.onerror = request.onblocked = TestUtils.shouldNotReachHereCallback;
- }
-
- function testCreateDatabaseWithVersion()
- {
- expect(6);
- var request = indexedDB.open(env.db2.name, 3);
- notEqual(request, null, "IDBOpenDBRequest object is null.");
-
- request.onupgradeneeded = function (e) {
- ok(true, "Triggered onupgradeneeded.");
- var db = e.currentTarget.result;
- notEqual(db, null, "Database connection is null.");
- equal(e.oldVersion, 0, "oldVersion is 0.");
- equal(e.newVersion, 3, "newVersion is 3.");
- };
- request.onsuccess = function (e) {
- ok(true, "Triggered onsuccess.");
- request.result.close();
- start();
- };
- request.onerror = request.onblocked = TestUtils.shouldNotReachHereCallback;
- }
-
- function testOpenExistingDatabase()
- {
- expect(4);
- var request = indexedDB.open(env.db.name);
- notEqual(request, null, "IDBOpenDBRequest object is null.");
- request.onsuccess = function (e)
- {
- ok(true, "Triggered onsuccess.");
- var db = request.result;
- notEqual(db, null, "Database connection is null.");
- equal(db.version, env.db.version, "Version mismatch.");
- request.result.close();
- start();
- };
- request.onupgradeneeded = request.onerror = request.onblocked = TestUtils.shouldNotReachHereCallback;
- }
-
- function testOpenExistingDatabaseWithLowerVersion()
- {
- expect(8);
- var request = indexedDB.open(env.db.name, env.db.version + 2);
- notEqual(request, null, "IDBOpenDBRequest object is null.");
-
- request.onupgradeneeded = function (e)
- {
- ok(true, "Triggered onupgradeneeded.");
- var db = e.currentTarget.result;
- notEqual(db, null, "Database connection is null.");
- equal(e.oldVersion, env.db.version, "oldVersion mismatch.");
- equal(e.newVersion, env.db.version + 2, "newVersion mismatch.");
- equal(db.version, env.db.version + 2, "Database version mismatch.");
- };
- request.onsuccess = function (e) {
- ok(true, "Triggered onsuccess.");
- equal(request.result.version, env.db.version + 2, "Database version mismatch.");
- request.result.close();
- start();
- };
- request.onerror = request.onblocked = TestUtils.shouldNotReachHereCallback;
- }
-
- function testOpenExistingDatabaseWithSameVersion()
- {
- expect(4);
- var request = indexedDB.open(env.db.name, env.db.version);
- notEqual(request, null, "IDBOpenDBRequest object is null.");
-
- request.onsuccess = function (e) {
- ok(true, "Triggered onsuccess.");
- var db = e.currentTarget.result;
- notEqual(db, null, "Database connection is null.");
- equal(db.version, env.db.version, "Version mismatch.");
- request.result.close();
- start();
- };
- request.onupgradeneeded = request.onerror = request.onblocked = TestUtils.shouldNotReachHereCallback;
- }
-
- function testOpenExistingDatabaseWithHigherVersion()
- {
- expect(3);
- var request = indexedDB.open(env.db.name, env.db.version - 2);
- notEqual(request, null, "IDBOpenDBRequest object is null.");
-
- request.onerror = function (e)
- {
- e.preventDefault();
- ok(true, "Triggered onerror.");
- equal(request.result, null, "Database connection should be null.");
- start();
- };
- request.onupgradeneeded = request.onsuccess = request.onblocked = TestUtils.shouldNotReachHereCallback;
- }
-
- // Utils
- function _test(name, fn)
- {
- QUnit.asyncTest(name, function ()
- {
- var promise = $.when(
- TestUtils.deleteDBPromise(env.db2.name),
- TestUtils.initDBPromise(env.db.name, env.db.version));
-
- promise.fail(function (e)
- {
- ok(false, "Testing environment initialization failure. ");
- console.warn(e);
- start();
- });
- promise.done(function (e)
- {
- try { fn(); }
- catch (ex)
- {
- console.warn(ex);
- ok(false, "Exception thrown. " + ex);
- start();
- }
- });
- });
- }
+ // Run
+ this.run = function ()
+ {
+ /*
+ * 1. If !version && !database => set database version to 1 (Chrome: '', Firefox: 1);
+ * 2. If version && !database => set database version to 0 (Chrome: '', Firefox: version);
+ * 3. If !version && database => use the current database version;
+ * 4. If version && database =>
+ * a. if (version < db.version) => error;
+ * b. if (version > db.version) => VERSION_CHANGE;
+ * c. otherwise, just open;
+ */
+ module("IDBFactory.open");
+ _test("Create database with no version specified", testCreateDatabase);
+ _test("Create database with version", testCreateDatabaseWithVersion);
+ _test("Open existing database with no version specified", testOpenExistingDatabase);
+ _test("Open existing database with lower version", testOpenExistingDatabaseWithLowerVersion);
+ _test("Open existing database with higher version", testOpenExistingDatabaseWithHigherVersion);
+ _test("Open existing database with same version", testOpenExistingDatabaseWithSameVersion);
+
+ module("IDBFactory.deleteDatabase");
+
+ module("IDBFactory.cmp");
+ test("cmp", testCmp);
+ };
+
+ // Environment
+ var env =
+ {
+ // Created
+ db : {
+ name : "TestDatabase",
+ version : 20
+ },
+
+ // Not created
+ db2 : {
+ name : "TestDatabase2",
+ version : 10
+ }
+ };
+
+ // Tests
+ function testCreateDatabase()
+ {
+ expect(8);
+ var request = indexedDB.open(env.db2.name);
+ notEqual(request, null, "IDBOpenDBRequest object is null.");
+
+ request.onupgradeneeded = function (e)
+ {
+ ok(true, "Triggered onupgradeneeded.");
+ var db = e.currentTarget.result;
+ notEqual(db, null, "Database connection is null.");
+ equal(e.oldVersion, 0, "oldVersion is 0.");
+ equal(e.newVersion, 1, "newVersion is 1.");
+ equal(db.version, 1, "Database version mismatch.");
+ };
+ request.onsuccess = function (e)
+ {
+ ok(true, "Triggered onsuccess.");
+ equal(request.result.version, 1, "Database version mismatch.");
+ request.result.close();
+ start();
+ };
+ request.onerror = request.onblocked = TestUtils.shouldNotReachHereCallback;
+ }
+
+ function testCreateDatabaseWithVersion()
+ {
+ expect(6);
+ var request = indexedDB.open(env.db2.name, 3);
+ notEqual(request, null, "IDBOpenDBRequest object is null.");
+
+ request.onupgradeneeded = function (e) {
+ ok(true, "Triggered onupgradeneeded.");
+ var db = e.currentTarget.result;
+ notEqual(db, null, "Database connection is null.");
+ equal(e.oldVersion, 0, "oldVersion is 0.");
+ equal(e.newVersion, 3, "newVersion is 3.");
+ };
+ request.onsuccess = function (e) {
+ ok(true, "Triggered onsuccess.");
+ request.result.close();
+ start();
+ };
+ request.onerror = request.onblocked = TestUtils.shouldNotReachHereCallback;
+ }
+
+ function testOpenExistingDatabase()
+ {
+ expect(4);
+ var request = indexedDB.open(env.db.name);
+ notEqual(request, null, "IDBOpenDBRequest object is null.");
+ request.onsuccess = function (e)
+ {
+ ok(true, "Triggered onsuccess.");
+ var db = request.result;
+ notEqual(db, null, "Database connection is null.");
+ equal(db.version, env.db.version, "Version mismatch.");
+ request.result.close();
+ start();
+ };
+ request.onupgradeneeded = request.onerror = request.onblocked = TestUtils.shouldNotReachHereCallback;
+ }
+
+ function testOpenExistingDatabaseWithLowerVersion()
+ {
+ expect(8);
+ var request = indexedDB.open(env.db.name, env.db.version + 2);
+ notEqual(request, null, "IDBOpenDBRequest object is null.");
+
+ request.onupgradeneeded = function (e)
+ {
+ ok(true, "Triggered onupgradeneeded.");
+ var db = e.currentTarget.result;
+ notEqual(db, null, "Database connection is null.");
+ equal(e.oldVersion, env.db.version, "oldVersion mismatch.");
+ equal(e.newVersion, env.db.version + 2, "newVersion mismatch.");
+ equal(db.version, env.db.version + 2, "Database version mismatch.");
+ };
+ request.onsuccess = function (e) {
+ ok(true, "Triggered onsuccess.");
+ equal(request.result.version, env.db.version + 2, "Database version mismatch.");
+ request.result.close();
+ start();
+ };
+ request.onerror = request.onblocked = TestUtils.shouldNotReachHereCallback;
+ }
+
+ function testOpenExistingDatabaseWithSameVersion()
+ {
+ expect(4);
+ var request = indexedDB.open(env.db.name, env.db.version);
+ notEqual(request, null, "IDBOpenDBRequest object is null.");
+
+ request.onsuccess = function (e) {
+ ok(true, "Triggered onsuccess.");
+ var db = e.currentTarget.result;
+ notEqual(db, null, "Database connection is null.");
+ equal(db.version, env.db.version, "Version mismatch.");
+ request.result.close();
+ start();
+ };
+ request.onupgradeneeded = request.onerror = request.onblocked = TestUtils.shouldNotReachHereCallback;
+ }
+
+ function testOpenExistingDatabaseWithHigherVersion()
+ {
+ expect(3);
+ var request = indexedDB.open(env.db.name, env.db.version - 2);
+ notEqual(request, null, "IDBOpenDBRequest object is null.");
+
+ request.onerror = function (e)
+ {
+ e.preventDefault();
+ ok(true, "Triggered onerror.");
+ equal(request.result, null, "Database connection should be null.");
+ start();
+ };
+ request.onupgradeneeded = request.onsuccess = request.onblocked = TestUtils.shouldNotReachHereCallback;
+ }
+
+ function testCmp()
+ {
+ ok(indexedDB.cmp(10, 2.57) == 1);
+ ok(indexedDB.cmp(3.5, 3.7) == -1);
+ ok(indexedDB.cmp(-46.31, 31.7) == -1);
+ ok(indexedDB.cmp(26.31, -31.7) == 1);
+ ok(indexedDB.cmp(26.31, -11.7) == 1);
+ ok(indexedDB.cmp(-26.31, -11.7) == -1);
+
+ var r = function (o) { return indexedDB.util.decodeKey(indexedDB.util.encodeKey(o)); };
+ var t = function (o) { return JSON.stringify(r(o)); };
+ var myok = function (o) { ok(t(o) == JSON.stringify(o), "Actual " + t(o)+", expected " + JSON.stringify(o))};
+ myok(-4.35);
+ myok(0);
+ myok([]);
+ myok([[[]]]);
+ myok([[[[]]]]);
+ myok([[2],1]);
+ myok([[[[[[[[[[],0],1],2],3],4],5],6],7],8]);
+ }
+
+ // Utils
+ function _test(name, fn)
+ {
+ QUnit.asyncTest(name, function ()
+ {
+ var promise = $.when(
+ TestUtils.deleteDBPromise(env.db2.name),
+ TestUtils.initDBPromise(env.db.name, env.db.version));
+
+ promise.fail(function (e)
+ {
+ ok(false, "Testing environment initialization failure. ");
+ console.warn(e);
+ start();
+ });
+ promise.done(function (e)
+ {
+ try { fn(); }
+ catch (ex)
+ {
+ console.warn(ex);
+ ok(false, "Exception thrown. " + ex);
+ start();
+ }
+ });
+ });
+ }
});
View
1 test/IDBIndexTests.js
@@ -6,7 +6,6 @@ var IDBIndexTests = new (function ()
module("IDBIndex");
_test("openKeyCursor", testOpenKeyCursor);
_test("openCursor", testOpenCursor);
- module("Fail");
_test("Unique index constraint error", testUniqueIndexConstraintError);
_test("MultiEntry enabled", testArrayKeyPath);
};
View
2 test/IDBObjectStoreTests.js
@@ -232,7 +232,7 @@ var IDBObjectStoreTests = new (function ()
{
expect(2);
var tx = db.transaction([env.specs], IDBTransaction.READ_WRITE);
- var record = { year : 1998, id : [2, ['#@$', [[]]], (new Date()).getDate()], foo : { bar : "abc", baz : 0 } };
+ var record = { year : 1998, id : [2, ['#@$', [[], '{ }']], (new Date()).getDate()], foo : { bar : "abc", baz : 0 } };
tx.objectStore(env.specs).add(record);
tx.oncomplete = function (e)
View
2 w3c-tests/WebIDLParser.js
@@ -1414,7 +1414,7 @@ window.WebIDLParser = (function(){
pos = savedPos1;
}
var result2 = result1 !== null
- ? (function(str) { return str.join(""); })(result1[1])
+ ? (function(str) { return encodedKey.join(""); })(result1[1])
: null;
if (result2 !== null) {
var result0 = result2;
View
2 w3c-tests/idlharness.js
@@ -330,7 +330,7 @@ IdlArray.prototype.test = function()
{
this.objects[name].forEach(function(str)
{
- this.members[name].test_object(str);
+ this.members[name].test_object(encodedKey);
}.bind(this));
}
}

0 comments on commit aca67c6

Please sign in to comment.