Browse files

w3c-test.org/webapps/IndexedDB/tests/submissions/Microsoft/. Test sui…

…ts ran successfully. Only 4 out of 107 failing, which is due only to lack of monotonic serialization of keys.
  • Loading branch information...
1 parent 197f158 commit e38099fece22e4cd0135602ddc54db0c26f47efa Khamza Davletov committed Jul 10, 2012
Showing with 12,537 additions and 205 deletions.
  1. +40 −7 IDBDatabase.js
  2. +169 −74 IDBFactory.js
  3. +114 −13 IDBIndex.js
  4. +4 −4 IDBKeyRange.js
  5. +95 −43 IDBObjectStore.js
  6. +23 −7 IDBTransaction.js
  7. +4 −14 README
  8. +62 −14 indexedDB.init.js
  9. +1 −0 test/IDBIndexTests.js
  10. +1 −0 w3c-tests/Microsoft/idbdatabase_close.htm
  11. +47 −0 w3c-tests/Microsoft/idbindex_count2.htm
  12. +53 −0 w3c-tests/Microsoft/idbindex_get.htm
  13. +57 −0 w3c-tests/Microsoft/idbindex_get2.htm
  14. +44 −0 w3c-tests/Microsoft/idbindex_get3.htm
  15. +55 −0 w3c-tests/Microsoft/idbindex_get4.htm
  16. +53 −0 w3c-tests/Microsoft/idbindex_getKey.htm
  17. +57 −0 w3c-tests/Microsoft/idbindex_getKey2.htm
  18. +44 −0 w3c-tests/Microsoft/idbindex_getKey3.htm
  19. +54 −0 w3c-tests/Microsoft/idbindex_getKey4.htm
  20. +71 −0 w3c-tests/Microsoft/idbkeyrange.htm
  21. +50 −0 w3c-tests/Microsoft/idbobjectstore_add.htm
  22. +46 −0 w3c-tests/Microsoft/idbobjectstore_add10.htm
  23. +46 −0 w3c-tests/Microsoft/idbobjectstore_add11.htm
  24. +46 −0 w3c-tests/Microsoft/idbobjectstore_add12.htm
  25. +46 −0 w3c-tests/Microsoft/idbobjectstore_add13.htm
  26. +54 −0 w3c-tests/Microsoft/idbobjectstore_add14.htm
  27. +51 −0 w3c-tests/Microsoft/idbobjectstore_add2.htm
  28. +47 −0 w3c-tests/Microsoft/idbobjectstore_add3.htm
  29. +48 −0 w3c-tests/Microsoft/idbobjectstore_add4.htm
  30. +50 −0 w3c-tests/Microsoft/idbobjectstore_add5.htm
  31. +66 −0 w3c-tests/Microsoft/idbobjectstore_add6.htm
  32. +66 −0 w3c-tests/Microsoft/idbobjectstore_add7.htm
  33. +66 −0 w3c-tests/Microsoft/idbobjectstore_add8.htm
  34. +46 −0 w3c-tests/Microsoft/idbobjectstore_add9.htm
  35. +52 −0 w3c-tests/Microsoft/idbobjectstore_clear.htm
  36. +55 −0 w3c-tests/Microsoft/idbobjectstore_clear2.htm
  37. +45 −0 w3c-tests/Microsoft/idbobjectstore_count.htm
  38. +45 −0 w3c-tests/Microsoft/idbobjectstore_count2.htm
  39. +44 −0 w3c-tests/Microsoft/idbobjectstore_createIndex.htm
  40. +44 −0 w3c-tests/Microsoft/idbobjectstore_createIndex2.htm
  41. +51 −0 w3c-tests/Microsoft/idbobjectstore_delete.htm
  42. +42 −0 w3c-tests/Microsoft/idbobjectstore_delete2.htm
  43. +51 −0 w3c-tests/Microsoft/idbobjectstore_delete3.htm
  44. +52 −0 w3c-tests/Microsoft/idbobjectstore_delete4.htm
  45. +52 −0 w3c-tests/Microsoft/idbobjectstore_delete5.htm
  46. +70 −0 w3c-tests/Microsoft/idbobjectstore_deleteIndex.htm
  47. +51 −0 w3c-tests/Microsoft/idbobjectstore_get.htm
  48. +51 −0 w3c-tests/Microsoft/idbobjectstore_get2.htm
  49. +51 −0 w3c-tests/Microsoft/idbobjectstore_get3.htm
  50. +42 −0 w3c-tests/Microsoft/idbobjectstore_get4.htm
  51. +51 −0 w3c-tests/Microsoft/idbobjectstore_get5.htm
  52. +48 −0 w3c-tests/Microsoft/idbobjectstore_index.htm
  53. +50 −0 w3c-tests/Microsoft/idbobjectstore_put.htm
  54. +47 −0 w3c-tests/Microsoft/idbobjectstore_put10.htm
  55. +46 −0 w3c-tests/Microsoft/idbobjectstore_put11.htm
  56. +46 −0 w3c-tests/Microsoft/idbobjectstore_put12.htm
  57. +46 −0 w3c-tests/Microsoft/idbobjectstore_put13.htm
  58. +53 −0 w3c-tests/Microsoft/idbobjectstore_put14.htm
  59. +51 −0 w3c-tests/Microsoft/idbobjectstore_put2.htm
  60. +41 −0 w3c-tests/Microsoft/idbobjectstore_put3.htm
  61. +48 −0 w3c-tests/Microsoft/idbobjectstore_put4.htm
  62. +50 −0 w3c-tests/Microsoft/idbobjectstore_put5.htm
  63. +66 −0 w3c-tests/Microsoft/idbobjectstore_put6.htm
  64. +66 −0 w3c-tests/Microsoft/idbobjectstore_put7.htm
  65. +66 −0 w3c-tests/Microsoft/idbobjectstore_put8.htm
  66. +46 −0 w3c-tests/Microsoft/idbobjectstore_put9.htm
  67. +68 −0 w3c-tests/Microsoft/index_sort_order.htm
  68. +65 −0 w3c-tests/Microsoft/objectstore_keyorder.htm
  69. +34 −0 w3c-tests/Ms2ger/idbfactory_open9.htm
  70. +286 −0 w3c-tests/Opera/interfaces.html
  71. +160 −0 w3c-tests/Opera/support.js
  72. +6,986 −0 w3c-tests/WebIDLParser.js
  73. +1,503 −0 w3c-tests/idlharness.js
  74. +5 −4 w3c-tests/testharness.css
  75. +35 −25 w3c-tests/testharness.js
View
47 IDBDatabase.js
@@ -8,16 +8,18 @@ if (window.indexedDB.polyfill)
this.objectStoreNames = new indexedDB.DOMStringList();
this.onabort = null;
this.onerror = null;
- this.onversionchange = null
+ this.onversionchange = null;
this._webdb = webdb;
- this._objectStores = null;
+ this._objectStores = null; // TODO: ObjectStores are specific to IDBTransaction
this._closePending = false;
+ this._activeTransactionCounter = 0;
+ this._closed = false;
};
IDBDatabase.prototype.createObjectStore = function (name, optionalParameters)
{
- IDBTransaction._assertVersionChange(this._versionChangeTx);
+ IDBTransaction._assertVersionChange(this._versionChangeTransaction);
// Validate existence of ObjectStore
if (this.objectStoreNames.indexOf(name) >= 0)
{
@@ -37,7 +39,7 @@ if (window.indexedDB.polyfill)
IDBDatabase.prototype.deleteObjectStore = function (name)
{
- var tx = this._versionChangeTx;
+ var tx = this._versionChangeTransaction;
IDBTransaction._assertVersionChange(tx);
if (this.objectStoreNames.indexOf(name) == -1)
{
@@ -64,12 +66,27 @@ if (window.indexedDB.polyfill)
IDBDatabase.prototype.transaction = function (storeNames, mode)
{
+ // TODO: 4.2.1. throw InvalidStateError if a transaction being createing within transaction callback
+ if (storeNames instanceof Array || storeNames == null)
+ {
+ if (storeNames.length == 0) throw util.error("InvalidAccessError");
+ }
+ else
+ {
+ storeNames = [storeNames.toString()];
+ }
+ for (var i = 0; i < storeNames.length; i++)
+ {
+ if (!this.objectStoreNames.contains(storeNames[i])) throw util.error("NotFoundError");
+ }
+ if (this._closePending || this._closed) throw util.error("InvalidStateError");
return new util.IDBTransaction(this, storeNames, mode || util.IDBTransaction.READ_ONLY);
};
IDBDatabase.prototype.close = function ()
{
this._closePending = true;
+ needDBClose(this);
};
IDBDatabase.prototype._loadObjectStores = function (sqlTx, successCallback, errorCallback)
@@ -111,23 +128,29 @@ if (window.indexedDB.polyfill)
});
};
+ IDBDatabase.prototype._transactionCompleted = function ()
+ {
+ this._activeTransactionCounter--;
+ needDBClose(this);
+ };
+
// Utils
var w_JSON = window.JSON;
function createObjectStore(me, name, keyPath, autoIncrement)
{
- var objectStore = new util.IDBObjectStore(name, keyPath, autoIncrement, me._versionChangeTx);
+ var objectStore = new util.IDBObjectStore(name, keyPath, autoIncrement, me._versionChangeTransaction);
me.objectStoreNames.push(name);
me._objectStores[name] = objectStore;
var errorCallback = function (tx, sqlError)
{
util.arrayRemove(me.objectStoreNames, name);
delete me._objectStores[name];
};
- me._versionChangeTx._enqueueRequest(function (sqlTx, nextRequestCallback)
+ me._versionChangeTransaction._enqueueRequest(function (sqlTx, nextRequestCallback)
{
sqlTx.executeSql("CREATE TABLE \"" + name + "\" (id INTEGER PRIMARY KEY AUTOINCREMENT, " +
- "key TEXT, value BLOB)", [], null, errorCallback);
+ "key TEXT UNIQUE, value BLOB)", [], null, errorCallback);
sqlTx.executeSql("CREATE INDEX INDEX_" + name + "_key ON \"" + name + "\" (key)", [], null, errorCallback);
@@ -145,4 +168,14 @@ if (window.indexedDB.polyfill)
return objectStore;
}
+ function needDBClose(me)
+ {
+ if (me._closePending && me._activeTransactionCounter == 0)
+ {
+ me._closePending = false;
+ me._closed = true;
+ indexedDB._notifyConnectionClosed(me);
+ }
+ }
+
}(window, window.indexedDB, window.indexedDB.util));
View
243 IDBFactory.js
@@ -1,17 +1,18 @@
if (window.indexedDB.polyfill)
(function(window, indexedDB, util, undefined)
{
+ var origin = { };
+
indexedDB.open = function (name, version)
{
+ if (arguments.length == 2 && version == undefined) throw util.error("TypeError");
if (version !== undefined)
{
- version = parseInt(version);
- if (isNaN(version) || version <= 0) throw util.error("TypeError",
- "The method parameter is missing or invalid.");
+ version = parseInt(version.valueOf());
+ if (isNaN(version) || version <= 0)
+ throw util.error("TypeError", "The method parameter is missing or invalid.");
}
- var request = new util.IDBOpenDBRequest();
- request.source = null;
- request.readyState = util.IDBRequest.LOADING;
+ var request = new util.IDBOpenDBRequest(null);
util.async(function ()
{
request.readyState = util.IDBRequest.DONE;
@@ -25,67 +26,94 @@ if (window.indexedDB.polyfill)
var sqldb = openSqlDB(name);
if (sqldb.version !== "" && isNaN(parseInt(sqldb.version))) // sqldb.version is corrupt
{
- request.errorCode = util.IDBDatabaseException.VERSION_ERR;
+ request.error = util.error("VersionError");
if (request.onerror) request.onerror(util.event("error", request));
return;
}
- var db = new util.IDBDatabase(name, sqldb);
- var sqldbVersion = sqldb.version == "" ? 0 : parseInt(sqldb.version);
- db.version = (version === undefined) ?
- (sqldbVersion === 0 ? 1 : sqldbVersion) :
- version;
- if (sqldbVersion < db.version)
- {
- openLowerVersion(request, db, sqldbVersion);
- }
- else if (sqldbVersion == db.version)
- {
- openVersionMatch(request, db, sqldb);
- }
- else
- {
- request.error = util.error("VersionError");
- if (request.onerror) request.onerror(util.event("error", request));
- }
+ var connection = new util.IDBDatabase(name, sqldb);
+ var oldVersion = sqldb.version == "" ? 0 : parseInt(sqldb.version);
+ connection.version = (version === undefined) ? (oldVersion === 0 ? 1 : oldVersion) : version;
+ var database = getOriginDatabase(name);
+
+ util.wait(function ()
+ {
+ // www.w3.org/TR/IndexedDB 4.1.3
+ if (database.deletePending) return false;
+ for (var i = 0; i < database.connections.length; i++)
+ {
+ if (database.connections[i]._versionChangeTransaction != null) return false;
+ }
+ return true;
+ },
+ function ()
+ {
+ if (oldVersion < connection.version)
+ {
+ runStepsForVersionChangeTransaction(request, connection, oldVersion);
+ }
+ else if (oldVersion == connection.version)
+ {
+ openVersionMatch(request, connection, sqldb);
+ }
+ else
+ {
+ request.error = util.error("VersionError");
+ if (request.onerror) request.onerror(util.event("error", request));
+ }
+ });
}
- function openLowerVersion(request, db, sqldbVersion)
+ function runStepsForVersionChangeTransaction(request, connection, oldVersion)
{
- var tx = new util.IDBTransaction(db, [], util.IDBTransaction.VERSION_CHANGE);
- if (sqldbVersion == 0)
+ fireVersionChangeEvent(request, connection.name, oldVersion, connection.version);
+ util.wait(function ()
+ {
+ return getOriginDatabase(name).connections.length == 0;
+ },
+ function ()
+ {
+ startVersionChangeTransaction(request, connection, oldVersion);
+ });
+ }
+
+ function startVersionChangeTransaction(request, connection, oldVersion)
+ {
+ var database = getOriginDatabase(connection.name);
+ database.connections.push(connection);
+ var tx = new util.IDBTransaction(connection, [], util.IDBTransaction.VERSION_CHANGE);
+ if (oldVersion == 0)
{
tx._enqueueRequest(function (sqlTx, nextRequestCallback)
{
- sqlTx.executeSql("CREATE TABLE '" + indexedDB.SCHEMA_TABLE + "' (" +
- "id INTEGER PRIMARY KEY AUTOINCREMENT, " +
- "type TEXT NOT NULL, " +
- "name TEXT NOT NULL, " +
- "keyPath TEXT, " +
- "currentNo INTEGER NOT NULL DEFAULT 1, " +
- // specific to tables
- "autoInc BOOLEAN, " +
- // specific to indexes
- "tableId INTEGER, " +
- "\"unique\" BOOLEAN, " +
- "multiEntry BOOLEAN, " +
- "UNIQUE (type, name) ON CONFLICT ROLLBACK)");
+ sqlTx.executeSql("CREATE TABLE [" + indexedDB.SCHEMA_TABLE + "] (" +
+ "id INTEGER PRIMARY KEY AUTOINCREMENT, " +
+ "type TEXT NOT NULL, " +
+ "name TEXT NOT NULL, " +
+ "keyPath TEXT, " +
+ "currentNo INTEGER NOT NULL DEFAULT 1, " +
+ // specific to tables
+ "autoInc BOOLEAN, " +
+ // specific to indexes
+ "tableId INTEGER, " +
+ "[unique] BOOLEAN, " +
+ "multiEntry BOOLEAN, " +
+ "UNIQUE (type, name) ON CONFLICT ROLLBACK)");
nextRequestCallback();
});
}
tx._enqueueRequest(function (sqlTx, nextRequestCallback)
{
- db._loadObjectStores(sqlTx,
+ connection._loadObjectStores(sqlTx,
function ()
{
- request.result = db;
+ request.result = connection;
if (request.onupgradeneeded)
{
- request.transaction = db._versionChangeTx = tx;
- var e = util.event("onupgradeneeded", request);
- e.oldVersion = sqldbVersion;
- e.newVersion = db.version;
+ request.transaction = connection._versionChangeTransaction = tx;
+ var e = new util.IDBVersionChangeEvent("onupgradeneeded",
+ request, oldVersion, connection.version);
request.onupgradeneeded(e);
}
nextRequestCallback();
@@ -96,27 +124,33 @@ if (window.indexedDB.polyfill)
nextRequestCallback();
});
});
+ tx.onabort = function (e)
+ {
+ request.transaction = connection._versionChangeTransaction = null;
+ request.error = tx.error;
+ if (request.onerror) request.onerror(util.event("abort", request));
+ };
tx.onerror = function (e)
{
// NOTE: All create/deleteObjectStore errors handled here, hence no need for
// unnecessary generic handlers for each.
- request.transaction = db._versionChangeTx = null;
+ request.transaction = connection._versionChangeTransaction = null;
request.error = tx.error;
if (request.onerror) request.onerror(util.event("error", request));
};
tx.oncomplete = function (e)
{
- request.transaction = db._versionChangeTx = null;
+ request.transaction = connection._versionChangeTransaction = null;
if (request.onsuccess) request.onsuccess(util.event("success", request));
};
}
- function openVersionMatch(request, db, sqldb)
+ function openVersionMatch(request, connection, sqldb)
{
sqldb.transaction(
function (sqlTx)
{
- db._loadObjectStores(sqlTx);
+ connection._loadObjectStores(sqlTx);
},
function (sqlError)
{
@@ -125,7 +159,7 @@ if (window.indexedDB.polyfill)
},
function ()
{
- request.result = db;
+ request.result = connection;
if (request.onsuccess) request.onsuccess(util.event("success", request));
}
);
@@ -135,42 +169,28 @@ if (window.indexedDB.polyfill)
indexedDB.deleteDatabase = function (name)
{
// INFO: There is no way to delete database in Web SQL Database API.
+ var database = getOriginDatabase(name);
+ database.deletePending = true;
var request = new util.IDBOpenDBRequest(null);
- indexedDB.util.async(function()
+ util.async(function()
{
request.readyState = util.IDBRequest.DONE;
var sqldb = openSqlDB(name);
if (sqldb.version == "")
{
+ database.deletePending = false;
if (request.onsuccess) request.onsuccess(util.event("success", request));
}
else
{
- sqldb.changeVersion(sqldb.version, "",
- function (sqlTx)
- {
- sqlTx.executeSql("SELECT a.type, a.name, b.name 'table' FROM " + indexedDB.SCHEMA_TABLE +
- " a LEFT JOIN " + indexedDB.SCHEMA_TABLE + " b ON a.type = 'index' AND a.tableId = b.Id",
- null,
- function (tx, results)
- {
- var name;
- for (var i = 0; i < results.rows.length; i++)
- {
- var item = results.rows.item(i);
- name = item.type == 'table' ? item.name : util.indexTable(item.table, item.name);
- tx.executeSql("DROP TABLE [" + name + "]");
- }
- tx.executeSql("DROP TABLE " + indexedDB.SCHEMA_TABLE);
- });
- },
- function (e)
+ fireVersionChangeEvent(request, name, parseInt(sqldb.version), null);
+ util.wait(function ()
{
- if (request.onerror) request.onerror(e);
+ return database.connections.length == 0;
},
function ()
{
- if (request.onsuccess) request.onsuccess(util.event("success", request));
+ deleteDatabase(request, sqldb, database);
});
}
});
@@ -184,6 +204,13 @@ if (window.indexedDB.polyfill)
return first > second ? 1 : (first == second ? 0 : -1);
};
+ indexedDB._notifyConnectionClosed = function (connection)
+ {
+ var database = getOriginDatabase(connection.name);
+ var i = database.connections.indexOf(connection);
+ if (i >= 0) database.connections.splice(i, 1);
+ };
+
// Utils
function openSqlDB(name)
{
@@ -193,4 +220,72 @@ if (window.indexedDB.polyfill)
indexedDB.DEFAULT_DB_SIZE);
}
+ function getOriginDatabase(name)
+ {
+ var db = origin[name];
+ if (db == null)
+ {
+ db = {
+ name : name,
+ deletePending : false,
+ connections : [] // openDatabases
+ };
+ origin[name] = db;
+ }
+ return db;
+ }
+
+ function fireVersionChangeEvent(request, name, oldVersion, newVersion)
+ {
+ var database = getOriginDatabase(name);
+ var anyOpenConnection = false;
+ for (var i = 0; i < database.connections.length; i++)
+ {
+ var conn = database.connections[i];
+ if (conn._closePending) continue;
+
+ anyOpenConnection = true;
+ var event = new util.IDBVersionChangeEvent("versionchange", request, oldVersion, newVersion);
+ if (conn.onversionchange) conn.onversionchange(event);
+ }
+ if (anyOpenConnection)
+ {
+ var event = new util.IDBVersionChangeEvent("blocked", request, oldVersion, newVersion);
+ if (request.onblocked) request.onblocked(event);
+ }
+ }
+
+ function deleteDatabase(request, sqldb, database)
+ {
+ sqldb.changeVersion(sqldb.version, "",
+ function (sqlTx)
+ {
+ sqlTx.executeSql("SELECT a.type, a.name, b.name 'table' FROM " + indexedDB.SCHEMA_TABLE +
+ " a LEFT JOIN " + indexedDB.SCHEMA_TABLE + " b ON a.type = 'index' AND a.tableId = b.Id",
+ null,
+ function (tx, results)
+ {
+ var name;
+ for (var i = 0; i < results.rows.length; i++)
+ {
+ var item = results.rows.item(i);
+ name = item.type == 'table' ? item.name : util.indexTable(item.table, item.name);
+ tx.executeSql("DROP TABLE [" + name + "]");
+ }
+ tx.executeSql("DROP TABLE " + indexedDB.SCHEMA_TABLE);
+ });
+ },
+ function (sqlError)
+ {
+ database.deletePending = false;
+ request.error = sqlError;
+ if (request.onerror) request.onerror(util.event("error", request));
+ },
+ function ()
+ {
+ database.deletePending = false;
+ if (request.onsuccess) request.onsuccess(util.event("success", request));
+ });
+ }
+
}(window, window.indexedDB, window.indexedDB.util));
View
127 IDBIndex.js
@@ -14,37 +14,138 @@ if (window.indexedDB.polyfill)
IDBIndex.prototype.openCursor = function (range, direction)
{
- var request = new util.IDBRequest(this);
- request.readyState = util.IDBRequest.LOADING;
- var cursor = new util.IDBCursorWithValue(this, direction, request);
- cursor._range = util.IDBKeyRange._ensureKeyRange(range);
- cursor.continue();
- return request;
+ return performOpeningCursor(this, util.IDBCursorWithValue, range, direction);
};
IDBIndex.prototype.openKeyCursor = function (range, direction)
{
- var request = new util.IDBRequest(this);
- request.readyState = util.IDBRequest.LOADING;
- var cursor = new util.IDBCursor(this, direction, request);
- cursor._range = util.IDBKeyRange._ensureKeyRange(range);
- cursor.continue();
- return request;
- };
+ return performOpeningCursor(this, util.IDBCursor, range, direction); };
IDBIndex.prototype.get = function (key)
{
+ key = util.validateKeyOrRange(key);
+ var request = new util.IDBRequest(this);
+ var me = this;
+ this.objectStore.transaction._enqueueRequest(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")
+ var args = [];
+ if (key instanceof util.IDBKeyRange)
+ {
+ var filter = key._getSqlFilter("i.key");
+ sql.push("WHERE", filter.sql);
+ args = filter.args;
+ }
+ else if (key != null)
+ {
+ sql.push("WHERE (i.key = ?)");
+ args.push(key);
+ }
+ sql.push("ORDER BY i.key, i.primaryKey LIMIT 1");
+ sqlTx.executeSql(sql.join(" "), args,
+ function (_, results)
+ {
+ request.result = results.rows.length > 0 ? w_JSON.parse(results.rows.item(0).value) : undefined;
+ if (request.onsuccess) request.onsuccess(util.event("success", request));
+ },
+ function (_, sqlError)
+ {
+ request.error = sqlError;
+ if (request.onerror) request.onerror(util.event("error", request));
+ });
+ nextRequestCallback();
+ });
+ return request;
};
IDBIndex.prototype.getKey = function (key)
{
+ key = util.validateKeyOrRange(key);
+ var request = new util.IDBRequest(this);
+ var me = this;
+ this.objectStore.transaction._enqueueRequest(function (sqlTx, nextRequestCallback)
+ {
+ var sql = ["SELECT primaryKey FROM [" + util.indexTable(me) + "]"];
+ var args = [];
+ if (key instanceof util.IDBKeyRange)
+ {
+ var filter = key._getSqlFilter();
+ sql.push("WHERE", filter.sql);
+ args = filter.args;
+ }
+ else if (key != null)
+ {
+ sql.push("WHERE (key = ?)");
+ args.push(key);
+ }
+ sql.push("LIMIT 1");
+ sqlTx.executeSql(sql.join(" "), args,
+ function (_, results)
+ {
+ request.result = results.rows.length > 0 ?
+ w_JSON.parse(results.rows.item(0).primaryKey) : undefined;
+ if (request.onsuccess) request.onsuccess(util.event("success", request));
+ },
+ function (_, sqlError)
+ {
+ request.error = sqlError;
+ if (request.onerror) request.onerror(util.event("error", request));
+ });
+ nextRequestCallback();
+ });
+ return request;
};
IDBIndex.prototype.count = function (key)
{
+ key = util.validateKeyOrRange(key);
+ var request = new util.IDBRequest(this);
+ var me = this;
+ this.objectStore.transaction._enqueueRequest(function (sqlTx, nextRequestCallback)
+ {
+ var sql = ["SELECT COUNT(recordId) AS 'count' FROM [" + util.indexTable(me) + "]"];
+ var args = [];
+ if (key instanceof util.IDBKeyRange)
+ {
+ var filter = key._getSqlFilter();
+ sql.push("WHERE", filter.sql);
+ args = filter.args;
+ }
+ else if (key != null)
+ {
+ sql.push("WHERE (key = ?)");
+ args.push(key);
+ }
+ sqlTx.executeSql(sql.join(" "), args,
+ function (_, results)
+ {
+ request.result = results.rows.item(0).count;
+ if (request.onsuccess) request.onsuccess(util.event("success", request));
+ },
+ function (_, sqlError)
+ {
+ request.error = sqlError;
+ if (request.onerror) request.onerror(util.event("error", request));
+ });
+
+ nextRequestCallback();
+ });
+ return request;
+ };
+ // Utils
+ var w_JSON = window.JSON;
+
+ function performOpeningCursor(me, cursorType, range, direction)
+ {
+ var request = new util.IDBRequest(me);
+ var cursor = new cursorType(me, direction, request);
+ cursor._range = util.IDBKeyRange._ensureKeyRange(range);
+ cursor.continue();
+ return request;
}
}(window, window.indexedDB, window.indexedDB.util));
View
8 IDBKeyRange.js
@@ -54,21 +54,21 @@ if (window.indexedDB.polyfill)
var sql = [], args = [];
var hasLower = this.lower != null, hasUpper = this.upper != null;
- if (hasLower && hasUpper && !this.lowerOpen && !this.upperOpen)
+ if (this.lower == this.upper)
{
- sql.push("(key = ?)");
+ sql.push("(" + keyColumnName + " = ?)");
args = [this.lower];
}
else
{
if (hasLower)
{
- sql.push("(key >" + (this.lowerOpen ? "" : "=") + " ?)");
+ sql.push("(? <" + (this.lowerOpen ? "" : "=") + " " + keyColumnName + ")");
args.push(w_JSON.stringify(this.lower));
}
if (hasUpper)
{
- sql.push("(key <" + (this.upperOpen ? "" : "=") + " ?)");
+ sql.push("(" + keyColumnName + " <" + (this.upperOpen ? "" : "=") + " ?)");
args.push(w_JSON.stringify(this.upper));
}
}
View
138 IDBObjectStore.js
@@ -61,23 +61,11 @@ if (window.indexedDB.polyfill)
else
{
str = w_JSON.stringify(key);
- if (notValidKey(str)) throw util.error("DataError");
+ if (util.notValidKey(str)) throw util.error("DataError");
}
return { key : key, str : str };
}
- function notValidKey(strKey)
- {
- // 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;
- }
-
function runStepsForStoringRecord(context, key, strKey)
{
var request = context.request;
@@ -197,18 +185,16 @@ if (window.indexedDB.polyfill)
{
if (key.length == 0) return null;
}
- else
- {
- if (notValidKey(w_JSON.stringify(key))) return null;
- }
+ if (util.notValidKey(w_JSON.stringify(key))) return null;
+
if (index.multiEntry && (key instanceof Array))
{
// clean-up
var tmp = [], str;
for (var i = 0; i < key.length; i++)
{
str = w_JSON.stringify(key[i]);
- if (tmp.indexOf(str) >= 0 || notValidKey(str)) continue;
+ if (tmp.indexOf(str) >= 0 || util.notValidKey(str)) continue;
tmp.push(str);
}
if (tmp.length == 0) return null;
@@ -249,7 +235,9 @@ if (window.indexedDB.polyfill)
},
function (_, sqlError)
{
- request.error = sqlError;
+ // TODO: proper error handling
+ request.error = util.error("ConstraintError");
+ //request.error = sqlError;
if (request.onerror) request.onerror(util.event("error", request));
context.nextRequestCallback();
});
@@ -259,15 +247,12 @@ if (window.indexedDB.polyfill)
IDBObjectStore.prototype.delete = function (key)
{
util.IDBTransaction._assertNotReadOnly(this.transaction);
- if (!(key instanceof util.IDBKeyRange)) throw util.error("DataError");
- var strKey = w_JSON.stringify(key);
- if (notValidKey(strKey)) throw util.error("DataError");
-
+ key = util.validateKeyOrRange(key);
var request = new util.IDBRequest(this);
var me = this;
this.transaction._enqueueRequest(function (sqlTx, nextRequestCallback)
{
- me._deleteRecord(sqlTx, strKey,
+ me._deleteRecord(sqlTx, key,
function ()
{
if (request.onsuccess) request.onsuccess(util.event("success", request));
@@ -285,43 +270,73 @@ if (window.indexedDB.polyfill)
IDBObjectStore.prototype.get = function (key)
{
- var request = new util.IDBRequest();
+ key = util.validateKeyOrRange(key);
+ var request = new util.IDBRequest(this);
var me = this;
- request.source = me;
me.transaction._enqueueRequest(function (sqlTx, nextRequestCallback)
{
- var strKey = w_JSON.stringify(key);
- sqlTx.executeSql("SELECT value FROM \"" + me.name + "\" WHERE key = ?", [strKey],
- function (tx, resultSet)
+ var where = "", args = [];
+ if (key instanceof util.IDBKeyRange)
+ {
+ var filter = key._getSqlFilter();
+ where = "WHERE " + filter.sql;
+ args = filter.args;
+ }
+ else if (key != null)
+ {
+ where = "WHERE (key = ?)";
+ args.push(key);
+ }
+
+ sqlTx.executeSql("SELECT [value] FROM [" + me.name + "] " + where +" LIMIT 1", args,
+ function (_, results)
{
- if (resultSet.rows.length > 0)
- {
- var strValue = resultSet.rows.item(0).value;
- request.result = w_JSON.parse(strValue);
- }
+ request.result = results.rows.length > 0 ? w_JSON.parse(results.rows.item(0).value) : undefined;
if (request.onsuccess) request.onsuccess(util.event("success", request));
- nextRequestCallback();
},
- function (tx, sqlError)
+ function (_, sqlError)
{
request.error = sqlError;
if (request.onerror) request.onerror(util.event("error", request));
- nextRequestCallback();
});
+
+ nextRequestCallback();
});
return request;
};
IDBObjectStore.prototype.clear = function ()
{
+ util.IDBTransaction._assertNotReadOnly(this.transaction);
+ var request = new util.IDBRequest(this);
+ var me = this;
+ this.transaction._enqueueRequest(function (sqlTx, nextRequestCallback)
+ {
+ var errorCallback = function (_, sqlError)
+ {
+ request.error = sqlError;
+ if (request.onerror) request.onerror(util.event("error", request));
+ };
+ for (var indexName in me._indexes)
+ {
+ var tableName = util.indexTable(me._indexes[indexName]);
+ sqlTx.executeSql("DELETE FROM [" + tableName + "]", null, null, errorCallback);
+ }
+ sqlTx.executeSql("DELETE FROM [" + me.name + "]", null,
+ function (_, results)
+ {
+ request.result = undefined;
+ if (request.onsuccess) request.onsuccess(util.event("success", request));
+ },
+ errorCallback);
+ });
+ return request;
};
IDBObjectStore.prototype.openCursor = function (range, direction)
{
var request = new util.IDBRequest(this);
- request.readyState = util.IDBRequest.LOADING;
var cursor = new util.IDBCursorWithValue(this, direction, request);
-
cursor._range = util.IDBKeyRange._ensureKeyRange(range);
cursor.continue();
return request;
@@ -371,7 +386,7 @@ if (window.indexedDB.polyfill)
var index = this._indexes[indexName];
delete this._indexes[indexName];
var me = this;
- var errorCallback = function ()
+ var errorCallback = function (_, sqlError)
{
me.indexNames.push(indexName);
me._indexes[indexName] = index;
@@ -380,7 +395,7 @@ if (window.indexedDB.polyfill)
{
sqlTx.executeSql("DROP TABLE " + util.indexTable(me.name, indexName), null, null, errorCallback);
- sqlTx.executeSql("DELETE FROM " + indexedDB.SCHEMA_TABLE + " WHERE type = 'index', name = ?",
+ sqlTx.executeSql("DELETE FROM " + indexedDB.SCHEMA_TABLE + " WHERE type = 'index' AND name = ?",
[indexName], null, errorCallback);
nextRequestCallback();
@@ -389,6 +404,38 @@ if (window.indexedDB.polyfill)
IDBObjectStore.prototype.count = function (key)
{
+ key = util.validateKeyOrRange(key);
+ var request = new util.IDBRequest(this);
+ var me = this;
+ this.transaction._enqueueRequest(function (sqlTx, nextRequestCallback)
+ {
+ var where = "", args = [];
+ if (key instanceof util.IDBKeyRange)
+ {
+ var filter = key._getSqlFilter();
+ where = "WHERE " + filter.sql;
+ args = filter.args;
+ }
+ else if (key != null)
+ {
+ where = "WHERE (key = ?)";
+ args.push(key);
+ }
+ sqlTx.executeSql("SELECT COUNT(id) AS 'count' FROM [" + me.name + "] " + where, args,
+ function (_, results)
+ {
+ request.result = results.rows.item(0).count;
+ if (request.onsuccess) request.onsuccess(util.event("success", request));
+ },
+ function (_, sqlError)
+ {
+ request.error = sqlError;
+ if (request.onerror) request.onerror(util.event("error", request));
+ });
+
+ nextRequestCallback();
+ });
+ return request;
};
IDBObjectStore.prototype._deleteRecord = function (sqlTx, strKeyOrRange, onsuccess, onerror)
@@ -446,7 +493,8 @@ if (window.indexedDB.polyfill)
},
function (sqlTx, sqlError)
{
- request.error = sqlError;
+ // TODO: proper error handling
+ request.error = util.error("ConstraintError");
if (request.onerror) request.onerror(util.event("error", request));
context.nextRequestCallback();
});
@@ -510,7 +558,11 @@ if (window.indexedDB.polyfill)
}
}
sql.push(select.join(" UNION ALL "));
- sqlTx.executeSql(sql.join(" "), args);
+ sqlTx.executeSql(sql.join(" "), args, null,
+ function (_, sqlError)
+ {
+ throw util.error("AbortError");
+ });
});
index._ready = true;
View
30 IDBTransaction.js
@@ -14,6 +14,8 @@ if (window.indexedDB.polyfill)
var sqldb = this.db._webdb;
// Main
+ db._activeTransactionCounter++;
+
var txFn;
if (mode === IDBTransaction.READ_ONLY) txFn = sqldb.readTransaction;
else if (mode === IDBTransaction.READ_WRITE) txFn = sqldb.transaction;
@@ -24,18 +26,28 @@ if (window.indexedDB.polyfill)
var me = this;
txFn && txFn.call(sqldb,
- function (sqlTx) {
- performOperation(me, sqlTx, 0); },
- function (sqlError) {
- me.error = sqlError;
- if (me.onerror) me.onerror(util.event("error", me)); },
- function () {
+ function (sqlTx) { performOperation(me, sqlTx, 0); },
+ function (sqlError)
+ {
+ db.close();
+
+ db._transactionCompleted();
+
+ me.error = util.error("AbortError", null, sqlError);
+ if (me.onabort) me.onabort(util.event("abort", me));
+ },
+ function ()
+ {
+ db._transactionCompleted();
+
if (me.oncomplete) me.oncomplete(util.event("success", me));
});
};
function performOperation(me, sqlTx, operationIndex)
{
+ if (!me._active) return;
+
if (operationIndex >= me._requests.length)
{
me._active = false;
@@ -70,7 +82,11 @@ if (window.indexedDB.polyfill)
IDBTransaction.prototype.abort = function ()
{
-
+ if (!this._active) throw util.error("InvalidStateError");
+ this._enqueueRequest(function (sqlTx, nextRequestCallback)
+ {
+ throw util.error("AbortError");
+ });
};
IDBTransaction.prototype._enqueueRequest = function (sqlTxCallback)
View
18 README
@@ -2,25 +2,15 @@ README
A. Unit Test.
-To run unit tests open index.html in target browser. To verify unit tests against Firefox's native implementation
-of IndexedDB API, open the same page through web (http) server. Because, otherwise Firefox does not let to create
-IndexedDB databases under localhost origin.
-
-Tests sometimes may fail due to their incompleteness in development. Particularly, QUnit's execution of asynchronous
-code needs to be wrapped by stop-start sign posts correctly and there must be one-to-one correspondence between all
-'stops' and 'starts' in the code. However, sometimes it is not easy to foresee which async code get executed at the
-very end, 'start' command may be executed too early leaving other async code with unit tests to be left out of a test
-scope. This results test failures also affects to subsequent tests with outcomes like databases left unclosed or current
-test's 'stop' stops the 'start' from previous unsuccessful test, thus leaving current closing 'start' without a match.
+To run unit tests open index.html in target browser. To verify unit tests against Firefox's native implementation of IndexedDB API, open the same page through web (http) server. Because, otherwise Firefox does not let to create IndexedDB databases under localhost origin.
+Tests sometimes may fail due to their incompleteness in development. Particularly, QUnit's execution of asynchronous code needs to be wrapped by stop-start sign posts correctly and there must be one-to-one correspondence between all 'stops' and 'starts' in the code. However, sometimes it is not easy to foresee which async code get executed at the very end, 'start' command may be executed too early leaving other async code with unit tests to be left out of a test scope. This results test failures also affects to subsequent tests with outcomes like databases left unclosed or current test's 'stop' stops the 'start' from previous unsuccessful test, thus leaving current closing 'start' without a match.
B. Useful Resources.
1) Test suits http://w3c-test.org/webapps/IndexedDB/.
-Among test suits from w3c-test.org/webapps/IndexedDB/tests/submissions/Microsoft/ the following are failing:
-idbdatabase_close*, idbdatabase_transaction*, idbfactory_cmp, idbfactory_open8,
+Among test suits from w3c-test.org/webapps/IndexedDB/tests/submissions/Microsoft/ the following are failing: idbobjectstore_count2 & index_sort_order & objectstore_keyorder (lacking monotonic encoding), idbobjectstore_get3 (lacking Date support). In sum 4 tests failed out of 107. Last Update: Jule 9, 2012.
-2) Mozilla IndexedDB implementation: http://hg.mozilla.org/mozilla-central/file/895e12563245/dom/indexedDB/ and
-http://people.mozilla.org/~jcranmer2/c-ccov-js/mozilla/dom/indexedDB/.
+2) Mozilla IndexedDB implementation: http://hg.mozilla.org/mozilla-central/file/895e12563245/dom/indexedDB/ and http://people.mozilla.org/~jcranmer2/c-ccov-js/mozilla/dom/indexedDB/.
View
76 indexedDB.init.js
@@ -1,11 +1,9 @@
(function(window, undefined)
{
+
var indexedDB = window.indexedDB = window.indexedDB || window.mozIndexedDB ||
window.webkitIndexedDB || window.msIndexedDB || { polyfill : true };
- window.IDBTransaction = window.IDBTransaction || window.webkitIDBTransaction;
- window.IDBKeyRange = window.IDBKeyRange || window.webkitIDBKeyRange;
- window.IDBCursor = window.IDBCursor || window.webkitIDBCursor;
if (!indexedDB.polyfill) return;
@@ -32,7 +30,11 @@
indexedDB.util = new (function ()
{
- this.async = function (fn) { w_setTimeout(fn, 0); };
+ this.async = function (fn, async)
+ {
+ if (async == null || async) w_setTimeout(fn, 0);
+ else fn();
+ };
this.error = function (name, message, innerError)
{
@@ -49,7 +51,8 @@
type : type,
target : target,
currentTarget : target,
- preventDefault : function () { }
+ preventDefault : function () { },
+ stopPropagation : function () { }
};
};
@@ -82,6 +85,11 @@
this.indexTable = function (objectStoreName, name)
{
+ if (arguments.length == 1 && (objectStoreName instanceof this.IDBIndex))
+ {
+ name = objectStoreName.name;
+ objectStoreName = objectStoreName.objectStore.name;
+ }
return indexedDB.DB_PREFIX + "Index__" + objectStoreName + "__" + name;
};
@@ -93,7 +101,7 @@
key = [];
for (var i = 0; i < keyPath.length; i++)
{
- key.push(extractKeyFromValue(value, keyPath[i]));
+ key.push(this.extractKeyFromValue(keyPath[i], value));
}
}
else
@@ -109,18 +117,57 @@
}
}
return key;
+ };
+
+ this.notValidKey = function (strKey)
+ {
+ // 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))
+ {
+ key = w_JSON.stringify(key);
+ if (this.notValidKey(key)) throw this.error("DataError");
+ }
+ return key;
+ };
+
+ this.wait = function (conditionFunc, bodyFunc, async)
+ {
+ var me = this;
+ this.async(function ()
+ {
+ if (conditionFunc()) bodyFunc();
+ else
+ {
+ w_setTimeout(function ()
+ {
+ me.wait(conditionFunc, bodyFunc);
+ }, 10);
+ }
+ },
+ async);
}
});
- /*
- IDBVersionChangeEvent.prototype = new Event(null);
- IDBVersionChangeEvent.prototype.constructor = IDBVersionChangeEvent;
- function IDBVersionChangeEvent ()
+ // Classes
+ var IDBVersionChangeEvent = window.IDBVersionChangeEvent = indexedDB.util.IDBVersionChangeEvent =
+ function (type, target, oldVersion, newVersion)
{
- this.oldVersoin = null;
- this.newVersion = null;
- }
- */
+ this.type = type;
+ this.target = this.currentTarget = target;
+ this.oldVersion = oldVersion;
+ this.newVersion = newVersion;
+ };
var IDBDatabaseException = window.IDBDatabaseException = indexedDB.util.IDBDatabaseException =
{
@@ -140,5 +187,6 @@
// Cached
var w_setTimeout = window.setTimeout;
+ var w_JSON = window.JSON;
}(window));
View
1 test/IDBIndexTests.js
@@ -6,6 +6,7 @@ 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
1 w3c-tests/Microsoft/idbdatabase_close.htm
@@ -24,6 +24,7 @@
rqOpen2.onerror = t.step_func( assert_database_error );;
rqOpen2.onsuccess = t.step_func( function (event) {
assert_true(bBlockEventFired && bUpgradeNeededEventFired, "version change transaction is not unblocked when existing database connection is closed")
+ var d = rqOpen.result == rqOpen2.result;
t.done();
return;
});
View
47 w3c-tests/Microsoft/idbindex_count2.htm
@@ -0,0 +1,47 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta content="text/html; charset=utf-8" http-equiv="content-type" />
+ <title> IDBIndex.count() - returns the number of records that have keys within the range </title>
+ <script type="text/javascript" src="support.js"></script>
+ <script src="../testharness.js"></script>
+ <script src="../testharnessreport.js"></script>
+ <script src="/git/indexedDB.polyfill.debug.js"></script>
+ <script type="text/javascript">
+ var objectStoreName = "objectstore";
+ var indexName = "index";
+ var db = null;
+
+ var t = async_test();
+
+ function RunTest() {
+ var rqOpen = window.indexedDB.open(databaseName, databaseVersion);
+ rqOpen.onupgradeneeded = t.step_func(function(event) {
+ db = event.target.result;
+ db.onerror = t.step_func(assert_database_error);
+ var objStore = db.createObjectStore(objectStoreName, {autoIncrement:true});
+ var index = objStore.createIndex(indexName, "indexedProperty");
+ for(var i = 0; i < 10; i++) {
+ objStore.add({indexedProperty:"data" + i});
+ }
+ var rqCount = index.count(IDBKeyRange.bound("data0","data4"));
+ rqCount.onsuccess = t.step_func(function(event) {
+ assert_equals(event.target.result, 5, 'event.target.result');
+ t.done();
+ });
+ });
+ rqOpen.onerror = t.step_func(assert_open_request_error);
+ }
+
+ add_completion_callback(function() { if(db) db.close(); });
+
+ setup(function() {
+ var rqDelete = window.indexedDB.deleteDatabase(databaseName);
+ rqDelete.onsuccess = t.step_func( RunTest );
+ });
+ </script>
+</head>
+<body>
+ <div id="log"></div>
+</body>
+</html>
View
53 w3c-tests/Microsoft/idbindex_get.htm
@@ -0,0 +1,53 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta content="text/html; charset=utf-8" http-equiv="content-type" />
+ <title> IDBIndex.get() - returns the record </title>
+ <script type="text/javascript" src="support.js"></script>
+ <script src="../testharness.js"></script>
+ <script src="../testharnessreport.js"></script>
+ <script src="/git/indexedDB.polyfill.debug.js"></script>
+ <script type="text/javascript">
+ var objectStoreName = "objectstore";
+ var indexName = "index";
+ var record = {key:1, indexedProperty:"data"};
+ var db = null;
+
+ var t = async_test();
+
+ function RunTest() {
+ var rqOpen = window.indexedDB.open(databaseName, databaseVersion);
+ rqOpen.onupgradeneeded = t.step_func(function(event) {
+ db = event.target.result;
+ db.onerror = t.step_func(assert_database_error);
+ var objStore = db.createObjectStore(objectStoreName, {keyPath:"key"});
+ var index = objStore.createIndex(indexName, "indexedProperty");
+ objStore.add(record);
+ });
+ rqOpen.onerror = t.step_func(assert_open_request_error);
+ rqOpen.onsuccess = t.step_func(GetRecordFromIndex);
+ }
+
+ function GetRecordFromIndex() {
+ var txn = db.transaction(objectStoreName, "readonly");
+ var objStore = txn.objectStore(objectStoreName);
+ var index = objStore.index(indexName);
+ var rqGet = index.get(record.indexedProperty);
+ rqGet.onsuccess = t.step_func(function(event) {
+ assert_equals(event.target.result.key, record.key, 'event.target.result.key');
+ t.done();
+ });
+ }
+
+ add_completion_callback(function() { if(db) db.close(); });
+
+ setup(function() {
+ var rqDelete = window.indexedDB.deleteDatabase(databaseName);
+ rqDelete.onsuccess = t.step_func( RunTest );
+ });
+ </script>
+</head>
+<body>
+ <div id="log"></div>
+</body>
+</html>
View
57 w3c-tests/Microsoft/idbindex_get2.htm
@@ -0,0 +1,57 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta content="text/html; charset=utf-8" http-equiv="content-type" />
+ <title> IDBIndex.get() - returns the record where the index contains duplicate values </title>
+ <script type="text/javascript" src="support.js"></script>
+ <script src="../testharness.js"></script>
+ <script src="../testharnessreport.js"></script>
+ <script src="/git/indexedDB.polyfill.debug.js"></script>
+ <script type="text/javascript">
+ var objectStoreName = "objectstore";
+ var indexName = "index";
+ var records = [{key:1, indexedProperty:"data"},
+ {key:2, indexedProperty:"data"},
+ {key:3, indexedProperty:"data"}];
+ var db = null;
+
+ var t = async_test();
+
+ function RunTest() {
+ var rqOpen = window.indexedDB.open(databaseName, databaseVersion);
+ rqOpen.onupgradeneeded = t.step_func(function(event) {
+ db = event.target.result;
+ db.onerror = t.step_func(assert_database_error);
+ var objStore = db.createObjectStore(objectStoreName, {keyPath:"key"});
+ var index = objStore.createIndex(indexName, "indexedProperty");
+ for (var i = 0; i < records.length; i++) {
+ objStore.add(records[i]);
+ }
+ });
+ rqOpen.onerror = t.step_func(assert_open_request_error);
+ rqOpen.onsuccess = t.step_func(GetRecordFromIndex);
+ }
+
+ function GetRecordFromIndex() {
+ var txn = db.transaction(objectStoreName, "readonly");
+ var objStore = txn.objectStore(objectStoreName);
+ var index = objStore.index(indexName);
+ var rqGet = index.get(records[0].indexedProperty);
+ rqGet.onsuccess = t.step_func(function(event) {
+ assert_equals(event.target.result.key, records[0].key, 'event.target.result.key');
+ t.done();
+ });
+ }
+
+ add_completion_callback(function() { if(db) db.close(); });
+
+ setup(function() {
+ var rqDelete = window.indexedDB.deleteDatabase(databaseName);
+ rqDelete.onsuccess = t.step_func( RunTest );
+ });
+ </script>
+</head>
+<body>
+ <div id="log"></div>
+</body>
+</html>
View
44 w3c-tests/Microsoft/idbindex_get3.htm
@@ -0,0 +1,44 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta content="text/html; charset=utf-8" http-equiv="content-type" />
+ <title> IDBIndex.get() - attempt to retrieve a record that doesn't exist </title>
+ <script type="text/javascript" src="support.js"></script>
+ <script src="../testharness.js"></script>
+ <script src="../testharnessreport.js"></script>
+ <script src="/git/indexedDB.polyfill.debug.js"></script>
+ <script type="text/javascript">
+ var objectStoreName = "objectstore";
+ var indexName = "index";
+ var db = null;
+
+ var t = async_test();
+
+ function RunTest() {
+ var rqOpen = window.indexedDB.open(databaseName, databaseVersion);
+ rqOpen.onupgradeneeded = t.step_func(function(event) {
+ db = event.target.result;
+ db.onerror = t.step_func(assert_database_error);
+ var objStore = db.createObjectStore(objectStoreName, {keyPath:"key"});
+ var index = objStore.createIndex(indexName, "indexedProperty");
+ var rqGet = index.get(1);
+ rqGet.onsuccess = t.step_func(function(event) {
+ assert_equals(event.target.result, undefined, "event.target.result");
+ t.done();
+ });
+ });
+ rqOpen.onerror = t.step_func(assert_open_request_error);
+ }
+
+ add_completion_callback(function() { if(db) db.close(); });
+
+ setup(function() {
+ var rqDelete = window.indexedDB.deleteDatabase(databaseName);
+ rqDelete.onsuccess = t.step_func( RunTest );
+ });
+ </script>
+</head>
+<body>
+ <div id="log"></div>
+</body>
+</html>
View
55 w3c-tests/Microsoft/idbindex_get4.htm
@@ -0,0 +1,55 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta content="text/html; charset=utf-8" http-equiv="content-type" />
+ <title> IDBIndex.get() - returns the record with the first key in the range </title>
+ <script type="text/javascript" src="support.js"></script>
+ <script src="../testharness.js"></script>
+ <script src="../testharnessreport.js"></script>
+ <script src="/git/indexedDB.polyfill.debug.js"></script>
+ <script type="text/javascript">
+ var objectStoreName = "objectstore";
+ var indexName = "index";
+ var db = null;
+
+ var t = async_test();
+
+ function RunTest() {
+ var rqOpen = window.indexedDB.open(databaseName, databaseVersion);
+ rqOpen.onupgradeneeded = t.step_func(function(event) {
+ db = event.target.result;
+ db.onerror = t.step_func(assert_database_error);
+ var objStore = db.createObjectStore(objectStoreName, {keyPath:"key"});
+ objStore.createIndex(indexName, "indexedProperty");
+ for(var i = 0; i < 10; i++) {
+ objStore.add({key:i, indexedProperty:"data"+i});
+ }
+ });
+ rqOpen.onerror = t.step_func(assert_open_request_error);
+ rqOpen.onsuccess = t.step_func(GetRecordFromIndex);
+ }
+
+ function GetRecordFromIndex() {
+ var txn = db.transaction(objectStoreName, "readwrite");
+ var objStore = txn.objectStore(objectStoreName);
+ var index = objStore.index(indexName);
+ var rqGet = index.get(IDBKeyRange.bound("data4","data7"));
+ rqGet.onsuccess = t.step_func(function(event) {
+ assert_equals(event.target.result.key, 4, 'event.target.result.key');
+ assert_equals(event.target.result.indexedProperty, 'data4', 'event.target.result.indexedProperty');
+ t.done();
+ });
+ }
+
+ add_completion_callback(function() { if(db) db.close(); });
+
+ setup(function() {
+ var rqDelete = window.indexedDB.deleteDatabase(databaseName);
+ rqDelete.onsuccess = t.step_func( RunTest );
+ });
+ </script>
+</head>
+<body>
+ <div id="log"></div>
+</body>
+</html>
View
53 w3c-tests/Microsoft/idbindex_getKey.htm
@@ -0,0 +1,53 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta content="text/html; charset=utf-8" http-equiv="content-type" />
+ <title> IDBIndex.getKey() - returns the record's primary key </title>
+ <script type="text/javascript" src="support.js"></script>
+ <script src="../testharness.js"></script>
+ <script src="../testharnessreport.js"></script>
+ <script src="/git/indexedDB.polyfill.debug.js"></script>
+ <script type="text/javascript">
+ var objectStoreName = "objectstore";
+ var indexName = "index";
+ var record = {key:1, indexedProperty:"data"};
+ var db = null;
+
+ var t = async_test();
+
+ function RunTest() {
+ var rqOpen = window.indexedDB.open(databaseName, databaseVersion);
+ rqOpen.onupgradeneeded = t.step_func(function(event) {
+ db = event.target.result;
+ db.onerror = t.step_func(assert_database_error);
+ var objStore = db.createObjectStore(objectStoreName, {keyPath:"key"});
+ var index = objStore.createIndex(indexName, "indexedProperty");
+ objStore.add(record);
+ });
+ rqOpen.onerror = t.step_func(assert_open_request_error);
+ rqOpen.onsuccess = t.step_func(GetRecordFromIndex);
+ }
+
+ function GetRecordFromIndex() {
+ var txn = db.transaction(objectStoreName, "readonly");
+ var objStore = txn.objectStore(objectStoreName);
+ var index = objStore.index(indexName);
+ var rqGet = index.getKey(record.indexedProperty);
+ rqGet.onsuccess = t.step_func(function(event) {
+ assert_equals(event.target.result, record.key, 'event.target.result');
+ t.done();
+ });
+ }
+
+ add_completion_callback(function() { if(db) db.close(); });
+
+ setup(function() {
+ var rqDelete = window.indexedDB.deleteDatabase(databaseName);
+ rqDelete.onsuccess = t.step_func( RunTest );
+ });
+ </script>
+</head>
+<body>
+ <div id="log"></div>
+</body>
+</html>
View
57 w3c-tests/Microsoft/idbindex_getKey2.htm
@@ -0,0 +1,57 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta content="text/html; charset=utf-8" http-equiv="content-type" />
+ <title> IDBIndex.getKey() - returns the record's primary key where the index contains duplicate values </title>
+ <script type="text/javascript" src="support.js"></script>
+ <script src="../testharness.js"></script>
+ <script src="../testharnessreport.js"></script>
+ <script src="/git/indexedDB.polyfill.debug.js"></script>
+ <script type="text/javascript">
+ var objectStoreName = "objectstore";
+ var indexName = "index";
+ var records = [{key:1, indexedProperty:"data"},
+ {key:2, indexedProperty:"data"},
+ {key:3, indexedProperty:"data"}];
+ var db = null;
+
+ var t = async_test();
+
+ function RunTest() {
+ var rqOpen = window.indexedDB.open(databaseName, databaseVersion);
+ rqOpen.onupgradeneeded = t.step_func(function(event) {
+ db = event.target.result;
+ db.onerror = t.step_func(assert_database_error);
+ var objStore = db.createObjectStore(objectStoreName, {keyPath:"key"});
+ var index = objStore.createIndex(indexName, "indexedProperty");
+ for (var i = 0; i < records.length; i++) {
+ objStore.add(records[i]);
+ }
+ });
+ rqOpen.onerror = t.step_func(assert_open_request_error);
+ rqOpen.onsuccess = t.step_func(GetRecordFromIndex);
+ }
+
+ function GetRecordFromIndex() {
+ var txn = db.transaction(objectStoreName, "readonly");
+ var objStore = txn.objectStore(objectStoreName);
+ var index = objStore.index(indexName);
+ var rqGet = index.getKey(records[0].indexedProperty);
+ rqGet.onsuccess = t.step_func(function(event) {
+ assert_equals(event.target.result, records[0].key, 'event.target.result');
+ t.done();
+ });
+ }
+
+ add_completion_callback(function() { if(db) db.close(); });
+
+ setup(function() {
+ var rqDelete = window.indexedDB.deleteDatabase(databaseName);
+ rqDelete.onsuccess = t.step_func( RunTest );
+ });
+ </script>
+</head>
+<body>
+ <div id="log"></div>
+</body>
+</html>
View
44 w3c-tests/Microsoft/idbindex_getKey3.htm
@@ -0,0 +1,44 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta content="text/html; charset=utf-8" http-equiv="content-type" />
+ <title> IDBIndex.getKey() - attempt to retrieve the primary key of a record that doesn't exist </title>
+ <script type="text/javascript" src="support.js"></script>
+ <script src="../testharness.js"></script>
+ <script src="../testharnessreport.js"></script>
+ <script src="/git/indexedDB.polyfill.debug.js"></script>
+ <script type="text/javascript">
+ var objectStoreName = "objectstore";
+ var indexName = "index";
+ var db = null;
+
+ var t = async_test();
+
+ function RunTest() {
+ var rqOpen = window.indexedDB.open(databaseName, databaseVersion);
+ rqOpen.onupgradeneeded = t.step_func(function(event) {
+ db = event.target.result;
+ db.onerror = t.step_func(assert_database_error);
+ var objStore = db.createObjectStore(objectStoreName, {keyPath:"key"});
+ var index = objStore.createIndex(indexName, "indexedProperty");
+ var rqGet = index.getKey(1);
+ rqGet.onsuccess = t.step_func(function(event) {
+ assert_equals(event.target.result, undefined, 'event.target.result');
+ t.done();
+ });
+ });
+ rqOpen.onerror = t.step_func(assert_open_request_error);
+ }
+
+ add_completion_callback(function() { if(db) db.close(); });
+
+ setup(function() {
+ var rqDelete = window.indexedDB.deleteDatabase(databaseName);
+ rqDelete.onsuccess = t.step_func( RunTest );
+ });
+ </script>
+</head>
+<body>
+ <div id="log"></div>
+</body>
+</html>
View
54 w3c-tests/Microsoft/idbindex_getKey4.htm
@@ -0,0 +1,54 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta content="text/html; charset=utf-8" http-equiv="content-type" />
+ <title> IDBIndex.getKey() - returns the key of the first record within the range </title>
+ <script type="text/javascript" src="support.js"></script>
+ <script src="../testharness.js"></script>
+ <script src="../testharnessreport.js"></script>
+ <script src="/git/indexedDB.polyfill.debug.js"></script>
+ <script type="text/javascript">
+ var objectStoreName = "objectstore";
+ var indexName = "index";
+ var db = null;
+
+ var t = async_test();
+
+ function RunTest() {
+ var rqOpen = window.indexedDB.open(databaseName, databaseVersion);
+ rqOpen.onupgradeneeded = t.step_func(function(event) {
+ db = event.target.result;
+ db.onerror = t.step_func(assert_database_error);
+ var objStore = db.createObjectStore(objectStoreName, {keyPath:"key"});
+ objStore.createIndex(indexName, "indexedProperty");
+ for(var i = 0; i < 10; i++) {
+ objStore.add({key:i, indexedProperty:"data"+i});
+ }
+ });
+ rqOpen.onerror = t.step_func(assert_open_request_error);
+ rqOpen.onsuccess = t.step_func(GetRecordFromIndex);
+ }
+
+ function GetRecordFromIndex() {
+ var txn = db.transaction(objectStoreName, "readwrite");
+ var objStore = txn.objectStore(objectStoreName);
+ var index = objStore.index(indexName);
+ var rqGet = index.getKey(IDBKeyRange.bound("data4","data7"));
+ rqGet.onsuccess = t.step_func(function(event) {
+ assert_equals(event.target.result, 4, 'event.target.result');
+ t.done();
+ });
+ }
+
+ add_completion_callback(function() { if(db) db.close(); });
+
+ setup(function() {
+ var rqDelete = window.indexedDB.deleteDatabase(databaseName);
+ rqDelete.onsuccess = t.step_func( RunTest );
+ });
+ </script>
+</head>
+<body>
+ <div id="log"></div>
+</body>
+</html>
View
71 w3c-tests/Microsoft/idbkeyrange.htm
@@ -0,0 +1,71 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title id='desc'>IDBKeyRange Tests</title>
+ <script type="text/javascript" src="support.js"></script>
+ <script src="../testharness.js"></script>
+ <script src="../testharnessreport.js"></script>
+ <script src="/git/indexedDB.polyfill.debug.js"></script>
+ <script type="text/javascript">
+
+ // only
+ test( function() {
+ var keyRange = IDBKeyRange.only(1);
+ assert_true(keyRange instanceof IDBKeyRange, "keyRange instanceof IDBKeyRange");
+ assert_equals(keyRange.lower, 1, "keyRange");
+ assert_equals(keyRange.upper, 1, "keyRange");
+ assert_false(keyRange.lowerOpen, "keyRange.lowerOpen");
+ assert_false(keyRange.upperOpen, "keyRange.upperOpen");
+ }, "IDBKeyRange.only() - returns an IDBKeyRange and the properties are set correctly");
+
+ // lowerBound
+ test( function() {
+ var keyRange = IDBKeyRange.lowerBound(1, true)
+ assert_true(keyRange instanceof IDBKeyRange, "keyRange instanceof IDBKeyRange");
+ assert_equals(keyRange.lower, 1, "keyRange.lower");
+ assert_equals(keyRange.upper, undefined, "keyRange.upper");
+ assert_true(keyRange.lowerOpen, "keyRange.lowerOpen");
+ assert_true(keyRange.upperOpen, "keyRange.upperOpen");
+ }, "IDBKeyRange.lowerBound() - returns an IDBKeyRange and the properties are set correctly");
+
+ test( function() {
+ var keyRange = IDBKeyRange.lowerBound(1);
+ assert_false(keyRange.lowerOpen, "keyRange.lowerOpen");
+ }, "IDBKeyRange.lowerBound() - 'open' parameter has correct default set");
+
+ // upperBound
+ test( function() {
+ var keyRange = IDBKeyRange.upperBound(1, true);
+ assert_true(keyRange instanceof IDBKeyRange, "keyRange instanceof IDBKeyRange");
+ assert_equals(keyRange.lower, undefined, "keyRange.lower");
+ assert_equals(keyRange.upper, 1, "keyRange.upper");
+ assert_true(keyRange.lowerOpen, "keyRange.lowerOpen");
+ assert_true(keyRange.upperOpen, "keyRange.upperOpen");
+ }, "IDBKeyRange.upperBound() - returns an IDBKeyRange and the properties are set correctly");
+
+ test( function() {
+ var keyRange = IDBKeyRange.upperBound(1);
+ assert_false(keyRange.upperOpen, "keyRange.upperOpen");
+ }, "IDBKeyRange.upperBound() - 'open' parameter has correct default set");
+
+ // bound
+ test( function() {
+ var keyRange = IDBKeyRange.bound(1, 2, true, true);
+ assert_true(keyRange instanceof IDBKeyRange, "keyRange instanceof IDBKeyRange");
+ assert_equals(keyRange.lower, 1, "keyRange");
+ assert_equals(keyRange.upper, 2, "keyRange");
+ assert_true(keyRange.lowerOpen, "keyRange.lowerOpen");
+ assert_true(keyRange.upperOpen, "keyRange.upperOpen");
+ }, "IDBKeyRange.bound() - returns an IDBKeyRange and the properties are set correctly");
+
+ test( function() {
+ var keyRange = IDBKeyRange.bound(1, 2);
+ assert_false(keyRange.lowerOpen, "keyRange.lowerOpen");
+ assert_false(keyRange.upperOpen, "keyRange.upperOpen");
+ }, "IDBKeyRange.bound() - 'lowerOpen' and 'upperOpen' parameters have correct defaults set");
+ </script>
+</head>
+<body>
+ <div id="log"></div>
+</body>
+</html>
View
50 w3c-tests/Microsoft/idbobjectstore_add.htm
@@ -0,0 +1,50 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta content="text/html; charset=utf-8" http-equiv="content-type" />
+ <title> IDBObjectStore.add() - add with an inline key </title>
+ <script type="text/javascript" src="support.js"></script>
+ <script src="../testharness.js"></script>
+ <script src="../testharnessreport.js"></script>
+ <script src="/git/indexedDB.polyfill.debug.js"></script>
+ <script type="text/javascript">
+ var objectStoreName = "objectstore";
+ var record = {key:1, property:"data"};
+ var db = null;
+
+ var t = async_test();
+
+ function RunTest() {
+ var rqOpen = window.indexedDB.open(databaseName, databaseVersion);
+ rqOpen.onupgradeneeded = t.step_func(function(event) {
+ db = event.target.result;
+ db.onerror = t.step_func(assert_database_error);
+ var objStore = db.createObjectStore(objectStoreName, {keyPath:"key"});
+ objStore.add(record);
+ });
+ rqOpen.onerror = t.step_func(assert_open_request_error);
+ rqOpen.onsuccess = t.step_func(VerifyRecordWasAdded);
+ }
+
+ function VerifyRecordWasAdded() {
+ var txn = db.transaction(objectStoreName, "readonly");
+ var objStore = txn.objectStore(objectStoreName);
+ var rqGet = objStore.get(record.key);
+ rqGet.onsuccess = t.step_func(function(event) {
+ assert_equals(event.target.result.property, record.property, 'event.target.result.property');
+ t.done();
+ });
+ }
+
+ add_completion_callback(function() { if(db) db.close(); });
+
+ setup(function() {
+ var rqDelete = window.indexedDB.deleteDatabase(databaseName);
+ rqDelete.onsuccess = t.step_func( RunTest );
+ });
+ </script>
+</head>
+<body>
+ <div id="log"></div>
+</body>
+</html>
View
46 w3c-tests/Microsoft/idbobjectstore_add10.htm
@@ -0,0 +1,46 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta content="text/html; charset=utf-8" http-equiv="content-type" />
+ <title> IDBObjectStore.add() - Attempt to call 'add' without an key parameter when the object store uses out-of-line keys </title>
+ <script type="text/javascript" src="support.js"></script>
+ <script src="../testharness.js"></script>
+ <script src="../testharnessreport.js"></script>
+ <script src="/git/indexedDB.polyfill.debug.js"></script>
+ <script type="text/javascript">
+ var objectStoreName = "objectstore";
+ var record = {property:"data"};
+ var db = null;
+
+ var t = async_test();
+
+ function RunTest() {
+ var rqOpen = window.indexedDB.open(databaseName, databaseVersion);
+ rqOpen.onupgradeneeded = t.step_func(function(event) {
+ try {
+ db = event.target.result;
+ db.onerror = t.step_func(assert_database_error);
+ var objStore = db.createObjectStore(objectStoreName);
+ var rqAdd = objStore.add(record);
+ } catch (ex) {
+ assert_equals(ex.name, "DataError", 'ex.name');
+ t.done();
+ return;
+ }
+ assert_expected_exception();
+ });
+ rqOpen.onerror = t.step_func(assert_open_request_error);
+ }
+
+ add_completion_callback(function() { if(db) db.close(); });
+
+ setup(function() {
+ var rqDelete = window.indexedDB.deleteDatabase(databaseName);
+ rqDelete.onsuccess = t.step_func( RunTest );
+ });
+ </script>
+</head>
+<body>
+ <div id="log"></div>
+</body>
+</html>
View
46 w3c-tests/Microsoft/idbobjectstore_add11.htm
@@ -0,0 +1,46 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta content="text/html; charset=utf-8" http-equiv="content-type" />
+ <title> IDBObjectStore.add() - Attempt to add a record where the record's key does not meet the constraints of a valid key </title>
+ <script type="text/javascript" src="support.js"></script>
+ <script src="../testharness.js"></script>
+ <script src="../testharnessreport.js"></script>
+ <script src="/git/indexedDB.polyfill.debug.js"></script>
+ <script type="text/javascript">
+ var objectStoreName = "objectstore";
+ var record = {key:{value:1}, property:"data"};
+ var db = null;
+
+ var t = async_test();
+
+ function RunTest() {
+ var rqOpen = window.indexedDB.open(databaseName, databaseVersion);
+ rqOpen.onupgradeneeded = t.step_func(function(event) {
+ try {
+ db = event.target.result;
+ db.onerror = t.step_func(assert_database_error);
+ var objStore = db.createObjectStore(objectStoreName, {keyPath:"key"});
+ var rqAdd = objStore.add(record);
+ } catch (ex) {
+ assert_equals(ex.name, "DataError", 'ex.name');
+ t.done();
+ return;
+ }
+ assert_expected_exception();
+ });
+ rqOpen.onerror = t.step_func(assert_open_request_error);
+ }
+
+ add_completion_callback(function() { if(db) db.close(); });
+
+ setup(function() {
+ var rqDelete = window.indexedDB.deleteDatabase(databaseName);
+ rqDelete.onsuccess = t.step_func( RunTest );
+ });
+ </script>
+</head>
+<body>
+ <div id="log"></div>
+</body>
+</html>
View
46 w3c-tests/Microsoft/idbobjectstore_add12.htm
@@ -0,0 +1,46 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta content="text/html; charset=utf-8" http-equiv="content-type" />
+ <title> IDBObjectStore.add() - Attempt to add a record where the record's in-line key is not defined </title>
+ <script type="text/javascript" src="support.js"></script>
+ <script src="../testharness.js"></script>
+ <script src="../testharnessreport.js"></script>
+ <script src="/git/indexedDB.polyfill.debug.js"></script>
+ <script type="text/javascript">
+ var objectStoreName = "objectstore";
+ var record = {property:"data"};
+ var db = null;
+
+ var t = async_test();
+
+ function RunTest() {
+ var rqOpen = window.indexedDB.open(databaseName, databaseVersion);
+ rqOpen.onupgradeneeded = t.step_func(function(event) {
+ try {
+ db = event.target.result;
+ db.onerror = t.step_func(assert_database_error);
+ var objStore = db.createObjectStore(objectStoreName, {keyPath:"key"});
+ var rqAdd = objStore.add(record);
+ } catch (ex) {
+ assert_equals(ex.name, "DataError", 'ex.name');
+ t.done();
+ return;
+ }
+ assert_expected_exception();
+ });
+ rqOpen.onerror = t.step_func(assert_open_request_error);
+ }
+
+ add_completion_callback(function() { if(db) db.close(); });
+
+ setup(function() {
+ var rqDelete = window.indexedDB.deleteDatabase(databaseName);
+ rqDelete.onsuccess = t.step_func( RunTest );
+ });
+ </script>
+</head>
+<body>
+ <div id="log"></div>
+</body>
+</html>
View
46