Skip to content

Commit

Permalink
INCOMPLETE: Regression in QUnit and Mocha tests "should be able to re…
Browse files Browse the repository at this point in the history
…-create an object store that was deleted")

- Fix: Distinguish deleted and pending deleted stores and indexes;
    for insertion operations, do index checks independent of
    `indexNames` in case subsequently deleted by `deleteIndex` (indexeddbshim#276)
- Testing (Grunt): Make QUnit tasks more granular
- Testing (QUnit): Avoid origin-checking
  • Loading branch information
brettz9 committed Mar 30, 2017
1 parent bf75000 commit cd81f6d
Show file tree
Hide file tree
Showing 19 changed files with 362 additions and 192 deletions.
4 changes: 3 additions & 1 deletion CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -452,6 +452,9 @@ they were actually changes since a more recent version on `master`.
(`put`, `add`) and `IDBCursor.update`)
- Fix: Avoid `eval()` in cloning (issue #211, #236)
- Fix: Support cyclic values via typeson/typeson-registry (#267)
- Fix: Distinguish deleted and pending deleted stores and indexes;
for insertion operations, do index checks independent of
`indexNames` in case subsequently deleted by `deleteIndex` (#276)
- Repo files: Rename test folders for ease in distinguishing
- Optimize: Only retrieve required SQLite columns
- Optimize: Have `IDBObjectStore` and `IDBIndex`'s `get` and
Expand Down Expand Up @@ -568,7 +571,6 @@ they were actually changes since a more recent version on `master`.

From old W3C (Node and browser), only the following are not passing:
IDBDatabase.close.js,
IDBObjectStore.createIndex.js,
TransactionBehavior.js

From new W3C (Node but potentially also browser):
Expand Down
4 changes: 2 additions & 2 deletions Gruntfile.js
Original file line number Diff line number Diff line change
Expand Up @@ -304,13 +304,13 @@ module.exports = function (grunt) {
grunt.registerTask('build', ['eslint', 'browserify', 'uglify']);

const testJobs = ['build', 'connect'];
grunt.registerTask('nodequnit', testJobs.concat('node-qunit'));
grunt.registerTask('nodequnit', 'node-qunit');
grunt.registerTask('mocha', ['mochaTest:test']); // clean:mochaTests isn't working here as locked (even with force:true on it or grunt-wait) so we do in package.json
grunt.registerTask('fake', ['mochaTest:fake']);
grunt.registerTask('mock', ['mochaTest:mock']);
grunt.registerTask('w3c-old', ['mochaTest:w3cOld']);

grunt.registerTask('phantom-qunit', testJobs.concat('qunit'));
grunt.registerTask('phantom-qunit', ['connect', 'qunit']);

if (saucekey !== null) {
testJobs.push('saucelabs-qunit');
Expand Down
84 changes: 56 additions & 28 deletions dist/indexeddbshim-UnicodeIdentifiers-node.js
Original file line number Diff line number Diff line change
Expand Up @@ -10744,10 +10744,10 @@ IDBIndex.__createInstance = function (store, indexProperties) {
var oldName = me.name;
_IDBTransaction2.default.__assertVersionChange(me.objectStore.transaction);
_IDBTransaction2.default.__assertActive(me.objectStore.transaction);
if (me.__deleted) {
if (me.__deleted || me.__pendingDelete) {
throw (0, _DOMException.createDOMException)('InvalidStateError', 'This index has been deleted');
}
if (me.objectStore.__deleted) {
if (me.objectStore.__deleted || me.objectStore.__pendingDelete) {
throw (0, _DOMException.createDOMException)('InvalidStateError', "This index's object store has been deleted");
}
if (newName === oldName) {
Expand Down Expand Up @@ -10804,9 +10804,10 @@ IDBIndex.__createIndex = function (store, index) {
var columnExists = idx && idx.__deleted;

// Add the index to the IDBObjectStore
index.__pending = true;
store.__indexes[index.name] = index;
index.__pendingCreate = true;

store.indexNames.push(index.name);
store.__indexes[index.name] = index; // We add to indexes as needs to be available, e.g., if there is a subsequent deleteIndex call

// Create the index in WebSQL
var transaction = store.transaction;
Expand Down Expand Up @@ -10852,7 +10853,8 @@ IDBIndex.__createIndex = function (store, index) {
addIndexEntry(i + 1);
}
} else {
delete index.__pending;
delete index.__pendingCreate;
delete index.__deleted;
indexValues = {};
success(store);
}
Expand Down Expand Up @@ -10881,7 +10883,7 @@ IDBIndex.__createIndex = function (store, index) {
*/
IDBIndex.__deleteIndex = function (store, index) {
// Remove the index from the IDBObjectStore
store.__indexes[index.name].__deleted = true;
index.__pendingDelete = true;
store.indexNames.splice(store.indexNames.indexOf(index.name), 1);

// Remove the index in WebSQL
Expand All @@ -10892,7 +10894,11 @@ IDBIndex.__deleteIndex = function (store, index) {
}

// Update the object store's index list
IDBIndex.__updateIndexList(store, tx, success, error);
IDBIndex.__updateIndexList(store, tx, function (store) {
delete index.__pendingDelete;
index.__deleted = true;
success(store);
}, error);
}, undefined, store);
};

Expand Down Expand Up @@ -10940,7 +10946,7 @@ IDBIndex.prototype.__fetchIndexData = function (range, opType, nullDisallowed, c
count = util.enforceRange(count, 'unsigned long');
}

if (me.__deleted) {
if (me.__deleted || me.__pendingDelete) {
throw (0, _DOMException.createDOMException)('InvalidStateError', 'This index has been deleted');
}
if (me.objectStore.__deleted) {
Expand Down Expand Up @@ -11501,7 +11507,7 @@ IDBObjectStore.__createInstance = function (storeProperties, transaction) {
},
set: function set(name) {
var me = this;
if (me.__deleted) {
if (me.__deleted || me.__pendingDelete) {
throw (0, _DOMException.createDOMException)('InvalidStateError', 'This store has been deleted');
}
_IDBTransaction2.default.__assertVersionChange(me.transaction);
Expand Down Expand Up @@ -11565,6 +11571,7 @@ IDBObjectStore.__clone = function (store, transaction) {
*/
IDBObjectStore.__createObjectStore = function (db, store) {
// Add the object store to the IDBDatabase
store.__pendingCreate = true;
db.__objectStores[store.name] = store;
db.objectStoreNames.push(store.name);

Expand All @@ -11584,6 +11591,8 @@ IDBObjectStore.__createObjectStore = function (db, store) {
tx.executeSql(sql, [], function (tx, data) {
Sca.encode(store.keyPath, function (encodedKeyPath) {
tx.executeSql('INSERT INTO __sys__ VALUES (?,?,?,?,?)', [util.escapeSQLiteStatement(store.name), encodedKeyPath, store.autoIncrement, '{}', 1], function () {
delete store.__pendingCreate;
delete store.__deleted;
success(store);
}, error);
});
Expand All @@ -11599,15 +11608,15 @@ IDBObjectStore.__createObjectStore = function (db, store) {
*/
IDBObjectStore.__deleteObjectStore = function (db, store) {
// Remove the object store from the IDBDatabase
store.__deleted = true;
store.__pendingDelete = true;
db.__objectStores[store.name] = undefined;
db.objectStoreNames.splice(db.objectStoreNames.indexOf(store.name), 1);

var storeClone = db.__versionTransaction.__storeClones[store.name];
if (storeClone) {
storeClone.__indexNames = _DOMStringList2.default.__createInstance();
storeClone.__indexes = {};
storeClone.__deleted = true;
storeClone.__pendingDelete = true;
}

// Remove the object store from WebSQL
Expand All @@ -11624,6 +11633,12 @@ IDBObjectStore.__deleteObjectStore = function (db, store) {
if (data.rows.length > 0) {
tx.executeSql('DROP TABLE ' + util.escapeStoreNameForSQL(store.name), [], function () {
tx.executeSql('DELETE FROM __sys__ WHERE "name" = ?', [util.escapeSQLiteStatement(store.name)], function () {
delete store.__pendingDelete;
store.__deleted = true;
if (storeClone) {
delete storeClone.__pendingDelete;
storeClone.__deleted = true;
}
success();
}, error);
}, error);
Expand Down Expand Up @@ -11739,18 +11754,31 @@ IDBObjectStore.prototype.__insertData = function (tx, encoded, value, clonedKeyO
// The `ConstraintError` to occur for `add` upon a duplicate will occur naturally in attempting an insert
// We process the index information first as it will stored in the same table as the store
var paramMap = {};
var indexPromises = me.indexNames.map(function (indexName) {
var indexPromises = Object.keys(
// We do not iterate `indexNames` as those can be modified synchronously (e.g.,
// `deleteIndex` could, by its synchronous removal from `indexNames`, prevent
// iteration here of an index though per IndexedDB test
// `idbobjectstore_createIndex4-deleteIndex-event_order.js`, `createIndex`
// should be allowed to first fail even in such a case).
me.__indexes).map(function (indexName) {
// While this may sometimes resolve sync and sometimes async, the
// idea is to avoid, where possible, unnecessary delays (and
// consuming code ought to only see a difference in the browser
// where we can't control the transaction timeout anyways).
return new _syncPromise2.default(function (resolve, reject) {
var index = me.__indexes[indexName];
if (index.__pending) {
// `createIndex` was called synchronously after the current insertion was added to
// the transaction queue so not yet ready to be checked (e.g., if two items with
/// the same key were added and then a unique index was created, it should not abort
// yet, as we're still handling the insertions)
if (
// `createIndex` was called synchronously after the current insertion was added to
// the transaction queue so although it was added to `__indexes`, it is not yet
// ready to be checked here for the insertion as it will be when running the
// `createIndex` operation (e.g., if two items with the same key were added and
// *then* a unique index was created, it should not continue to err and abort
// yet, as we're still handling the insertions which must be processed (e.g., to
// add duplicates which then cause a unique index to fail))
index.__pendingCreate ||
// If already deleted (and not just slated for deletion (by `__pendingDelete`
// after this add), we avoid checks
index.__deleted) {
resolve();
return;
}
Expand Down Expand Up @@ -11831,7 +11859,7 @@ IDBObjectStore.prototype.add = function (value /* , key */) {
if (arguments.length === 0) {
throw new TypeError('No value was specified');
}
if (me.__deleted) {
if (me.__deleted || me.__pendingDelete) {
throw (0, _DOMException.createDOMException)('InvalidStateError', 'This store has been deleted');
}
_IDBTransaction2.default.__assertActive(me.transaction);
Expand All @@ -11857,7 +11885,7 @@ IDBObjectStore.prototype.put = function (value /*, key */) {
if (arguments.length === 0) {
throw new TypeError('No value was specified');
}
if (me.__deleted) {
if (me.__deleted || me.__pendingDelete) {
throw (0, _DOMException.createDOMException)('InvalidStateError', 'This store has been deleted');
}
_IDBTransaction2.default.__assertActive(me.transaction);
Expand Down Expand Up @@ -11916,7 +11944,7 @@ IDBObjectStore.prototype.__get = function (query, getKey, getAll, count) {
if (count !== undefined) {
count = util.enforceRange(count, 'unsigned long');
}
if (me.__deleted) {
if (me.__deleted || me.__pendingDelete) {
throw (0, _DOMException.createDOMException)('InvalidStateError', 'This store has been deleted');
}
_IDBTransaction2.default.__assertActive(me.transaction);
Expand Down Expand Up @@ -12022,7 +12050,7 @@ IDBObjectStore.prototype['delete'] = function (query) {
throw new TypeError('A parameter was missing for `IDBObjectStore.delete`.');
}

if (me.__deleted) {
if (me.__deleted || me.__pendingDelete) {
throw (0, _DOMException.createDOMException)('InvalidStateError', 'This store has been deleted');
}
_IDBTransaction2.default.__assertActive(me.transaction);
Expand Down Expand Up @@ -12054,7 +12082,7 @@ IDBObjectStore.prototype.clear = function () {
if (!(this instanceof IDBObjectStore)) {
throw new TypeError('Illegal invocation');
}
if (me.__deleted) {
if (me.__deleted || me.__pendingDelete) {
throw (0, _DOMException.createDOMException)('InvalidStateError', 'This store has been deleted');
}
_IDBTransaction2.default.__assertActive(me.transaction);
Expand All @@ -12079,7 +12107,7 @@ IDBObjectStore.prototype.count = function () /* query */{
if (!(me instanceof IDBObjectStore)) {
throw new TypeError('Illegal invocation');
}
if (me.__deleted) {
if (me.__deleted || me.__pendingDelete) {
throw (0, _DOMException.createDOMException)('InvalidStateError', 'This store has been deleted');
}
_IDBTransaction2.default.__assertActive(me.transaction);
Expand All @@ -12098,7 +12126,7 @@ IDBObjectStore.prototype.openCursor = function () /* query, direction */{
if (!(me instanceof IDBObjectStore)) {
throw new TypeError('Illegal invocation');
}
if (me.__deleted) {
if (me.__deleted || me.__pendingDelete) {
throw (0, _DOMException.createDOMException)('InvalidStateError', 'This store has been deleted');
}
var cursor = _IDBCursor.IDBCursorWithValue.__createInstance(query, direction, me, me, 'key', 'value');
Expand All @@ -12111,7 +12139,7 @@ IDBObjectStore.prototype.openKeyCursor = function () /* query, direction */{
if (!(me instanceof IDBObjectStore)) {
throw new TypeError('Illegal invocation');
}
if (me.__deleted) {
if (me.__deleted || me.__pendingDelete) {
throw (0, _DOMException.createDOMException)('InvalidStateError', 'This store has been deleted');
}

Expand All @@ -12132,7 +12160,7 @@ IDBObjectStore.prototype.index = function (indexName) {
if (arguments.length === 0) {
throw new TypeError('No index name was specified');
}
if (me.__deleted) {
if (me.__deleted || me.__pendingDelete) {
throw (0, _DOMException.createDOMException)('InvalidStateError', 'This store has been deleted');
}
_IDBTransaction2.default.__assertNotFinished(me.transaction);
Expand Down Expand Up @@ -12178,7 +12206,7 @@ IDBObjectStore.prototype.createIndex = function (indexName, keyPath /* , optiona
throw new TypeError('No key path was specified');
}
_IDBTransaction2.default.__assertVersionChange(me.transaction);
if (me.__deleted) {
if (me.__deleted || me.__pendingDelete) {
throw (0, _DOMException.createDOMException)('InvalidStateError', 'This store has been deleted');
}
_IDBTransaction2.default.__assertActive(me.transaction);
Expand Down Expand Up @@ -12218,7 +12246,7 @@ IDBObjectStore.prototype.deleteIndex = function (name) {
throw new TypeError('No index name was specified');
}
_IDBTransaction2.default.__assertVersionChange(me.transaction);
if (me.__deleted) {
if (me.__deleted || me.__pendingDelete) {
throw (0, _DOMException.createDOMException)('InvalidStateError', 'This store has been deleted');
}
_IDBTransaction2.default.__assertActive(me.transaction);
Expand Down
4 changes: 2 additions & 2 deletions dist/indexeddbshim-UnicodeIdentifiers-node.min.js

Large diffs are not rendered by default.

Loading

0 comments on commit cd81f6d

Please sign in to comment.