synchronous schema rollback
This commit is contained in:
parent
987f22de02
commit
4d663d2e59
@ -579,9 +579,33 @@ export class MemoryBackend implements Backend {
|
|||||||
if (!db) {
|
if (!db) {
|
||||||
throw Error("db not found");
|
throw Error("db not found");
|
||||||
}
|
}
|
||||||
|
return db.committedSchema;
|
||||||
|
}
|
||||||
|
|
||||||
|
getCurrentTransactionSchema(btx: DatabaseTransaction): Schema {
|
||||||
|
const myConn = this.connectionsByTransaction[btx.transactionCookie];
|
||||||
|
if (!myConn) {
|
||||||
|
throw Error("unknown connection");
|
||||||
|
}
|
||||||
|
const db = this.databases[myConn.dbName];
|
||||||
|
if (!db) {
|
||||||
|
throw Error("db not found");
|
||||||
|
}
|
||||||
return myConn.modifiedSchema;
|
return myConn.modifiedSchema;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getInitialTransactionSchema(btx: DatabaseTransaction): Schema {
|
||||||
|
const myConn = this.connectionsByTransaction[btx.transactionCookie];
|
||||||
|
if (!myConn) {
|
||||||
|
throw Error("unknown connection");
|
||||||
|
}
|
||||||
|
const db = this.databases[myConn.dbName];
|
||||||
|
if (!db) {
|
||||||
|
throw Error("db not found");
|
||||||
|
}
|
||||||
|
return db.committedSchema;
|
||||||
|
}
|
||||||
|
|
||||||
renameIndex(
|
renameIndex(
|
||||||
btx: DatabaseTransaction,
|
btx: DatabaseTransaction,
|
||||||
objectStoreName: string,
|
objectStoreName: string,
|
||||||
|
@ -162,6 +162,10 @@ export interface Backend {
|
|||||||
|
|
||||||
getSchema(db: DatabaseConnection): Schema;
|
getSchema(db: DatabaseConnection): Schema;
|
||||||
|
|
||||||
|
getCurrentTransactionSchema(btx: DatabaseTransaction): Schema;
|
||||||
|
|
||||||
|
getInitialTransactionSchema(btx: DatabaseTransaction): Schema;
|
||||||
|
|
||||||
renameIndex(
|
renameIndex(
|
||||||
btx: DatabaseTransaction,
|
btx: DatabaseTransaction,
|
||||||
objectStoreName: string,
|
objectStoreName: string,
|
||||||
|
@ -221,7 +221,7 @@ export class BridgeIDBCursor implements IDBCursor {
|
|||||||
resultLevel: this._keyOnly ? ResultLevel.OnlyKeys : ResultLevel.Full,
|
resultLevel: this._keyOnly ? ResultLevel.OnlyKeys : ResultLevel.Full,
|
||||||
};
|
};
|
||||||
|
|
||||||
const { btx } = this.source._confirmActiveTransaction();
|
const { btx } = this.source._confirmStartedBackendTransaction();
|
||||||
|
|
||||||
let response = await this._backend.getRecords(btx, recordGetRequest);
|
let response = await this._backend.getRecords(btx, recordGetRequest);
|
||||||
|
|
||||||
@ -305,7 +305,7 @@ export class BridgeIDBCursor implements IDBCursor {
|
|||||||
if (BridgeIDBFactory.enableTracing) {
|
if (BridgeIDBFactory.enableTracing) {
|
||||||
console.log("updating at cursor");
|
console.log("updating at cursor");
|
||||||
}
|
}
|
||||||
const { btx } = this.source._confirmActiveTransaction();
|
const { btx } = this.source._confirmStartedBackendTransaction();
|
||||||
await this._backend.storeRecord(btx, storeReq);
|
await this._backend.storeRecord(btx, storeReq);
|
||||||
};
|
};
|
||||||
return transaction._execRequestAsync({
|
return transaction._execRequestAsync({
|
||||||
@ -412,7 +412,7 @@ export class BridgeIDBCursor implements IDBCursor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const operation = async () => {
|
const operation = async () => {
|
||||||
const { btx } = this.source._confirmActiveTransaction();
|
const { btx } = this.source._confirmStartedBackendTransaction();
|
||||||
this._backend.deleteRecord(
|
this._backend.deleteRecord(
|
||||||
btx,
|
btx,
|
||||||
this._objectStoreName,
|
this._objectStoreName,
|
||||||
@ -535,13 +535,6 @@ export class BridgeIDBDatabase extends FakeEventTarget implements IDBDatabase {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Refresh the schema by querying it from the backend.
|
|
||||||
*/
|
|
||||||
_refreshSchema() {
|
|
||||||
this._schema = this._backend.getSchema(this._backendConnection);
|
|
||||||
}
|
|
||||||
|
|
||||||
constructor(backend: Backend, backendConnection: DatabaseConnection) {
|
constructor(backend: Backend, backendConnection: DatabaseConnection) {
|
||||||
super();
|
super();
|
||||||
|
|
||||||
@ -596,7 +589,7 @@ export class BridgeIDBDatabase extends FakeEventTarget implements IDBDatabase {
|
|||||||
autoIncrement,
|
autoIncrement,
|
||||||
);
|
);
|
||||||
|
|
||||||
this._schema = this._backend.getSchema(this._backendConnection);
|
this._schema = this._backend.getCurrentTransactionSchema(backendTx);
|
||||||
|
|
||||||
return transaction.objectStore(name);
|
return transaction.objectStore(name);
|
||||||
}
|
}
|
||||||
@ -616,7 +609,6 @@ export class BridgeIDBDatabase extends FakeEventTarget implements IDBDatabase {
|
|||||||
os._deleted = true;
|
os._deleted = true;
|
||||||
transaction._objectStoresCache.delete(name);
|
transaction._objectStoresCache.delete(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public _internalTransaction(
|
public _internalTransaction(
|
||||||
@ -835,6 +827,9 @@ export class BridgeIDBFactory {
|
|||||||
requestedVersion,
|
requestedVersion,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// We need to expose the new version number to the upgrade transaction.
|
||||||
|
db._schema = this.backend.getCurrentTransactionSchema(backendTransaction);
|
||||||
|
|
||||||
const transaction = db._internalTransaction(
|
const transaction = db._internalTransaction(
|
||||||
[],
|
[],
|
||||||
"versionchange",
|
"versionchange",
|
||||||
@ -911,20 +906,6 @@ export class BridgeIDBFactory {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const confirmActiveTransaction = (
|
|
||||||
index: BridgeIDBIndex,
|
|
||||||
): BridgeIDBTransaction => {
|
|
||||||
if (index._deleted || index._objectStore._deleted) {
|
|
||||||
throw new InvalidStateError();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!index._objectStore._transaction._active) {
|
|
||||||
throw new TransactionInactiveError();
|
|
||||||
}
|
|
||||||
|
|
||||||
return index._objectStore._transaction;
|
|
||||||
};
|
|
||||||
|
|
||||||
// http://www.w3.org/TR/2015/REC-IndexedDB-20150108/#idl-def-IDBIndex
|
// http://www.w3.org/TR/2015/REC-IndexedDB-20150108/#idl-def-IDBIndex
|
||||||
/** @public */
|
/** @public */
|
||||||
export class BridgeIDBIndex implements IDBIndex {
|
export class BridgeIDBIndex implements IDBIndex {
|
||||||
@ -957,8 +938,12 @@ export class BridgeIDBIndex implements IDBIndex {
|
|||||||
return this._objectStore._backend;
|
return this._objectStore._backend;
|
||||||
}
|
}
|
||||||
|
|
||||||
_confirmActiveTransaction(): { btx: DatabaseTransaction } {
|
_confirmStartedBackendTransaction(): { btx: DatabaseTransaction } {
|
||||||
return this._objectStore._confirmActiveTransaction();
|
return this._objectStore._confirmStartedBackendTransaction();
|
||||||
|
}
|
||||||
|
|
||||||
|
_confirmActiveTransaction(): void {
|
||||||
|
this._objectStore._confirmActiveTransaction();
|
||||||
}
|
}
|
||||||
|
|
||||||
private _name: string;
|
private _name: string;
|
||||||
@ -986,7 +971,7 @@ export class BridgeIDBIndex implements IDBIndex {
|
|||||||
throw new TransactionInactiveError();
|
throw new TransactionInactiveError();
|
||||||
}
|
}
|
||||||
|
|
||||||
const { btx } = this._confirmActiveTransaction();
|
const { btx } = this._confirmStartedBackendTransaction();
|
||||||
|
|
||||||
const oldName = this._name;
|
const oldName = this._name;
|
||||||
const newName = String(name);
|
const newName = String(name);
|
||||||
@ -1008,7 +993,7 @@ export class BridgeIDBIndex implements IDBIndex {
|
|||||||
range?: BridgeIDBKeyRange | IDBValidKey | null | undefined,
|
range?: BridgeIDBKeyRange | IDBValidKey | null | undefined,
|
||||||
direction: IDBCursorDirection = "next",
|
direction: IDBCursorDirection = "next",
|
||||||
) {
|
) {
|
||||||
confirmActiveTransaction(this);
|
this._confirmActiveTransaction();
|
||||||
|
|
||||||
if (range === null) {
|
if (range === null) {
|
||||||
range = undefined;
|
range = undefined;
|
||||||
@ -1047,7 +1032,7 @@ export class BridgeIDBIndex implements IDBIndex {
|
|||||||
range?: BridgeIDBKeyRange | IDBValidKey | null | undefined,
|
range?: BridgeIDBKeyRange | IDBValidKey | null | undefined,
|
||||||
direction: IDBCursorDirection = "next",
|
direction: IDBCursorDirection = "next",
|
||||||
) {
|
) {
|
||||||
confirmActiveTransaction(this);
|
this._confirmActiveTransaction();
|
||||||
|
|
||||||
if (range === null) {
|
if (range === null) {
|
||||||
range = undefined;
|
range = undefined;
|
||||||
@ -1077,7 +1062,6 @@ export class BridgeIDBIndex implements IDBIndex {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private _confirmIndexExists() {
|
private _confirmIndexExists() {
|
||||||
const storeSchema = this._schema.objectStores[this._objectStore._name];
|
const storeSchema = this._schema.objectStores[this._objectStore._name];
|
||||||
if (!storeSchema) {
|
if (!storeSchema) {
|
||||||
@ -1089,8 +1073,8 @@ export class BridgeIDBIndex implements IDBIndex {
|
|||||||
}
|
}
|
||||||
|
|
||||||
get(key: BridgeIDBKeyRange | IDBValidKey) {
|
get(key: BridgeIDBKeyRange | IDBValidKey) {
|
||||||
confirmActiveTransaction(this);
|
|
||||||
this._confirmIndexExists();
|
this._confirmIndexExists();
|
||||||
|
this._confirmActiveTransaction();
|
||||||
if (this._deleted) {
|
if (this._deleted) {
|
||||||
throw new InvalidStateError();
|
throw new InvalidStateError();
|
||||||
}
|
}
|
||||||
@ -1109,7 +1093,7 @@ export class BridgeIDBIndex implements IDBIndex {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const operation = async () => {
|
const operation = async () => {
|
||||||
const { btx } = this._confirmActiveTransaction();
|
const { btx } = this._confirmStartedBackendTransaction();
|
||||||
const result = await this._backend.getRecords(btx, getReq);
|
const result = await this._backend.getRecords(btx, getReq);
|
||||||
if (result.count == 0) {
|
if (result.count == 0) {
|
||||||
return undefined;
|
return undefined;
|
||||||
@ -1137,7 +1121,7 @@ export class BridgeIDBIndex implements IDBIndex {
|
|||||||
|
|
||||||
// http://www.w3.org/TR/2015/REC-IndexedDB-20150108/#widl-IDBIndex-getKey-IDBRequest-any-key
|
// http://www.w3.org/TR/2015/REC-IndexedDB-20150108/#widl-IDBIndex-getKey-IDBRequest-any-key
|
||||||
public getKey(key: BridgeIDBKeyRange | IDBValidKey) {
|
public getKey(key: BridgeIDBKeyRange | IDBValidKey) {
|
||||||
confirmActiveTransaction(this);
|
this._confirmActiveTransaction();
|
||||||
|
|
||||||
if (!(key instanceof BridgeIDBKeyRange)) {
|
if (!(key instanceof BridgeIDBKeyRange)) {
|
||||||
key = BridgeIDBKeyRange._valueToKeyRange(key);
|
key = BridgeIDBKeyRange._valueToKeyRange(key);
|
||||||
@ -1153,7 +1137,7 @@ export class BridgeIDBIndex implements IDBIndex {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const operation = async () => {
|
const operation = async () => {
|
||||||
const { btx } = this._confirmActiveTransaction();
|
const { btx } = this._confirmStartedBackendTransaction();
|
||||||
const result = await this._backend.getRecords(btx, getReq);
|
const result = await this._backend.getRecords(btx, getReq);
|
||||||
if (result.count == 0) {
|
if (result.count == 0) {
|
||||||
return undefined;
|
return undefined;
|
||||||
@ -1181,7 +1165,7 @@ export class BridgeIDBIndex implements IDBIndex {
|
|||||||
|
|
||||||
// http://www.w3.org/TR/2015/REC-IndexedDB-20150108/#widl-IDBIndex-count-IDBRequest-any-key
|
// http://www.w3.org/TR/2015/REC-IndexedDB-20150108/#widl-IDBIndex-count-IDBRequest-any-key
|
||||||
public count(key: BridgeIDBKeyRange | IDBValidKey | null | undefined) {
|
public count(key: BridgeIDBKeyRange | IDBValidKey | null | undefined) {
|
||||||
confirmActiveTransaction(this);
|
this._confirmActiveTransaction();
|
||||||
|
|
||||||
if (key === null) {
|
if (key === null) {
|
||||||
key = undefined;
|
key = undefined;
|
||||||
@ -1200,7 +1184,7 @@ export class BridgeIDBIndex implements IDBIndex {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const operation = async () => {
|
const operation = async () => {
|
||||||
const { btx } = this._confirmActiveTransaction();
|
const { btx } = this._confirmStartedBackendTransaction();
|
||||||
const result = await this._backend.getRecords(btx, getReq);
|
const result = await this._backend.getRecords(btx, getReq);
|
||||||
return result.count;
|
return result.count;
|
||||||
};
|
};
|
||||||
@ -1380,7 +1364,7 @@ export class BridgeIDBObjectStore implements IDBObjectStore {
|
|||||||
return this._transaction._db._backendConnection;
|
return this._transaction._db._backendConnection;
|
||||||
}
|
}
|
||||||
|
|
||||||
_confirmActiveTransaction(): { btx: DatabaseTransaction } {
|
_confirmStartedBackendTransaction(): { btx: DatabaseTransaction } {
|
||||||
const btx = this._transaction._backendTransaction;
|
const btx = this._transaction._backendTransaction;
|
||||||
if (!btx) {
|
if (!btx) {
|
||||||
throw new InvalidStateError();
|
throw new InvalidStateError();
|
||||||
@ -1388,6 +1372,22 @@ export class BridgeIDBObjectStore implements IDBObjectStore {
|
|||||||
return { btx };
|
return { btx };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Confirm that requests can currently placed against the
|
||||||
|
* transaction of this object.
|
||||||
|
*
|
||||||
|
* Note that this is independent from the state of the backend
|
||||||
|
* connection.
|
||||||
|
*/
|
||||||
|
_confirmActiveTransaction(): void {
|
||||||
|
if (!this._transaction._active) {
|
||||||
|
throw new TransactionInactiveError();
|
||||||
|
}
|
||||||
|
if (this._transaction._aborted) {
|
||||||
|
throw new TransactionInactiveError();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// http://w3c.github.io/IndexedDB/#dom-idbobjectstore-name
|
// http://w3c.github.io/IndexedDB/#dom-idbobjectstore-name
|
||||||
set name(newName: any) {
|
set name(newName: any) {
|
||||||
const transaction = this._transaction;
|
const transaction = this._transaction;
|
||||||
@ -1396,7 +1396,7 @@ export class BridgeIDBObjectStore implements IDBObjectStore {
|
|||||||
throw new InvalidStateError();
|
throw new InvalidStateError();
|
||||||
}
|
}
|
||||||
|
|
||||||
let { btx } = this._confirmActiveTransaction();
|
let { btx } = this._confirmStartedBackendTransaction();
|
||||||
|
|
||||||
newName = String(newName);
|
newName = String(newName);
|
||||||
|
|
||||||
@ -1407,12 +1407,11 @@ export class BridgeIDBObjectStore implements IDBObjectStore {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this._backend.renameObjectStore(btx, oldName, newName);
|
this._backend.renameObjectStore(btx, oldName, newName);
|
||||||
this._transaction._db._schema = this._backend.getSchema(
|
this._transaction._db._schema = this._backend.getCurrentTransactionSchema(
|
||||||
this._backendConnection,
|
btx,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public _store(value: any, key: IDBValidKey | undefined, overwrite: boolean) {
|
public _store(value: any, key: IDBValidKey | undefined, overwrite: boolean) {
|
||||||
if (BridgeIDBFactory.enableTracing) {
|
if (BridgeIDBFactory.enableTracing) {
|
||||||
console.log(`TRACE: IDBObjectStore._store`);
|
console.log(`TRACE: IDBObjectStore._store`);
|
||||||
@ -1428,16 +1427,10 @@ export class BridgeIDBObjectStore implements IDBObjectStore {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// We only call this to synchronously verify the request.
|
// We only call this to synchronously verify the request.
|
||||||
makeStoreKeyValue(
|
makeStoreKeyValue(value, key, 1, autoIncrement, keyPath);
|
||||||
value,
|
|
||||||
key,
|
|
||||||
1,
|
|
||||||
autoIncrement,
|
|
||||||
keyPath,
|
|
||||||
);
|
|
||||||
|
|
||||||
const operation = async () => {
|
const operation = async () => {
|
||||||
const { btx } = this._confirmActiveTransaction();
|
const { btx } = this._confirmStartedBackendTransaction();
|
||||||
const result = await this._backend.storeRecord(btx, {
|
const result = await this._backend.storeRecord(btx, {
|
||||||
objectStoreName: this._name,
|
objectStoreName: this._name,
|
||||||
key: key,
|
key: key,
|
||||||
@ -1457,7 +1450,9 @@ export class BridgeIDBObjectStore implements IDBObjectStore {
|
|||||||
throw new TypeError();
|
throw new TypeError();
|
||||||
}
|
}
|
||||||
if (this._deleted) {
|
if (this._deleted) {
|
||||||
throw new InvalidStateError("tried to call 'put' on a deleted object store");
|
throw new InvalidStateError(
|
||||||
|
"tried to call 'put' on a deleted object store",
|
||||||
|
);
|
||||||
}
|
}
|
||||||
return this._store(value, key, true);
|
return this._store(value, key, true);
|
||||||
}
|
}
|
||||||
@ -1477,7 +1472,9 @@ export class BridgeIDBObjectStore implements IDBObjectStore {
|
|||||||
throw new TypeError();
|
throw new TypeError();
|
||||||
}
|
}
|
||||||
if (this._deleted) {
|
if (this._deleted) {
|
||||||
throw new InvalidStateError("tried to call 'delete' on a deleted object store");
|
throw new InvalidStateError(
|
||||||
|
"tried to call 'delete' on a deleted object store",
|
||||||
|
);
|
||||||
}
|
}
|
||||||
if (this._transaction.mode === "readonly") {
|
if (this._transaction.mode === "readonly") {
|
||||||
throw new ReadOnlyError();
|
throw new ReadOnlyError();
|
||||||
@ -1492,7 +1489,7 @@ export class BridgeIDBObjectStore implements IDBObjectStore {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const operation = async () => {
|
const operation = async () => {
|
||||||
const { btx } = this._confirmActiveTransaction();
|
const { btx } = this._confirmStartedBackendTransaction();
|
||||||
return this._backend.deleteRecord(btx, this._name, keyRange);
|
return this._backend.deleteRecord(btx, this._name, keyRange);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1512,7 +1509,9 @@ export class BridgeIDBObjectStore implements IDBObjectStore {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (this._deleted) {
|
if (this._deleted) {
|
||||||
throw new InvalidStateError("tried to call 'delete' on a deleted object store");
|
throw new InvalidStateError(
|
||||||
|
"tried to call 'delete' on a deleted object store",
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
let keyRange: BridgeIDBKeyRange;
|
let keyRange: BridgeIDBKeyRange;
|
||||||
@ -1544,7 +1543,7 @@ export class BridgeIDBObjectStore implements IDBObjectStore {
|
|||||||
if (BridgeIDBFactory.enableTracing) {
|
if (BridgeIDBFactory.enableTracing) {
|
||||||
console.log("running get operation:", recordRequest);
|
console.log("running get operation:", recordRequest);
|
||||||
}
|
}
|
||||||
const { btx } = this._confirmActiveTransaction();
|
const { btx } = this._confirmStartedBackendTransaction();
|
||||||
const result = await this._backend.getRecords(btx, recordRequest);
|
const result = await this._backend.getRecords(btx, recordRequest);
|
||||||
|
|
||||||
if (BridgeIDBFactory.enableTracing) {
|
if (BridgeIDBFactory.enableTracing) {
|
||||||
@ -1599,7 +1598,9 @@ export class BridgeIDBObjectStore implements IDBObjectStore {
|
|||||||
direction: IDBCursorDirection = "next",
|
direction: IDBCursorDirection = "next",
|
||||||
) {
|
) {
|
||||||
if (this._deleted) {
|
if (this._deleted) {
|
||||||
throw new InvalidStateError("tried to call 'openCursor' on a deleted object store");
|
throw new InvalidStateError(
|
||||||
|
"tried to call 'openCursor' on a deleted object store",
|
||||||
|
);
|
||||||
}
|
}
|
||||||
if (range === null) {
|
if (range === null) {
|
||||||
range = undefined;
|
range = undefined;
|
||||||
@ -1633,7 +1634,9 @@ export class BridgeIDBObjectStore implements IDBObjectStore {
|
|||||||
direction?: IDBCursorDirection,
|
direction?: IDBCursorDirection,
|
||||||
) {
|
) {
|
||||||
if (this._deleted) {
|
if (this._deleted) {
|
||||||
throw new InvalidStateError("tried to call 'openKeyCursor' on a deleted object store");
|
throw new InvalidStateError(
|
||||||
|
"tried to call 'openKeyCursor' on a deleted object store",
|
||||||
|
);
|
||||||
}
|
}
|
||||||
if (range === null) {
|
if (range === null) {
|
||||||
range = undefined;
|
range = undefined;
|
||||||
@ -1682,7 +1685,7 @@ export class BridgeIDBObjectStore implements IDBObjectStore {
|
|||||||
throw new InvalidStateError();
|
throw new InvalidStateError();
|
||||||
}
|
}
|
||||||
|
|
||||||
const { btx } = this._confirmActiveTransaction();
|
const { btx } = this._confirmStartedBackendTransaction();
|
||||||
|
|
||||||
const multiEntry =
|
const multiEntry =
|
||||||
optionalParameters.multiEntry !== undefined
|
optionalParameters.multiEntry !== undefined
|
||||||
@ -1750,7 +1753,7 @@ export class BridgeIDBObjectStore implements IDBObjectStore {
|
|||||||
throw new InvalidStateError();
|
throw new InvalidStateError();
|
||||||
}
|
}
|
||||||
|
|
||||||
const { btx } = this._confirmActiveTransaction();
|
const { btx } = this._confirmStartedBackendTransaction();
|
||||||
|
|
||||||
const index = this._indexesCache.get(indexName);
|
const index = this._indexesCache.get(indexName);
|
||||||
if (index !== undefined) {
|
if (index !== undefined) {
|
||||||
@ -1781,7 +1784,7 @@ export class BridgeIDBObjectStore implements IDBObjectStore {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const operation = async () => {
|
const operation = async () => {
|
||||||
const { btx } = this._confirmActiveTransaction();
|
const { btx } = this._confirmStartedBackendTransaction();
|
||||||
const result = await this._backend.getRecords(btx, recordGetRequest);
|
const result = await this._backend.getRecords(btx, recordGetRequest);
|
||||||
return result.count;
|
return result.count;
|
||||||
};
|
};
|
||||||
@ -2015,14 +2018,15 @@ export class BridgeIDBTransaction
|
|||||||
this._db._upgradeTransaction = null;
|
this._db._upgradeTransaction = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Only roll back if we actually executed the scheduled operations.
|
|
||||||
const maybeBtx = this._backendTransaction;
|
const maybeBtx = this._backendTransaction;
|
||||||
if (maybeBtx) {
|
if (maybeBtx) {
|
||||||
|
this._db._schema = this._backend.getInitialTransactionSchema(maybeBtx);
|
||||||
|
// Only roll back if we actually executed the scheduled operations.
|
||||||
await this._backend.rollback(maybeBtx);
|
await this._backend.rollback(maybeBtx);
|
||||||
|
} else {
|
||||||
|
this._db._schema = this._backend.getSchema(this._db._backendConnection);
|
||||||
}
|
}
|
||||||
|
|
||||||
this._db._refreshSchema();
|
|
||||||
|
|
||||||
queueTask(() => {
|
queueTask(() => {
|
||||||
const event = new FakeEvent("abort", {
|
const event = new FakeEvent("abort", {
|
||||||
bubbles: true,
|
bubbles: true,
|
||||||
|
@ -9,7 +9,7 @@ test("WPT test abort-in-initial-upgradeneeded.htm", async (t) => {
|
|||||||
open_rq.onupgradeneeded = function (e) {
|
open_rq.onupgradeneeded = function (e) {
|
||||||
const tgt = e.target as any;
|
const tgt = e.target as any;
|
||||||
db = tgt.result;
|
db = tgt.result;
|
||||||
t.assert(db.version === 2);
|
t.deepEqual(db.version, 2);
|
||||||
var transaction = tgt.transaction;
|
var transaction = tgt.transaction;
|
||||||
transaction.oncomplete = () => t.fail("unexpected transaction.complete");
|
transaction.oncomplete = () => t.fail("unexpected transaction.complete");
|
||||||
transaction.onabort = function (e: any) {
|
transaction.onabort = function (e: any) {
|
||||||
|
@ -175,3 +175,59 @@ test("WPT idbindex_get6.htm", async (t) => {
|
|||||||
});
|
});
|
||||||
t.pass();
|
t.pass();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// IDBIndex.get() - throw TransactionInactiveError on aborted transaction
|
||||||
|
test("WPT idbindex_get7.htm", async (t) => {
|
||||||
|
await new Promise<void>((resolve, reject) => {
|
||||||
|
var db: any;
|
||||||
|
|
||||||
|
var open_rq = createdb(t);
|
||||||
|
open_rq.onupgradeneeded = function (e: any) {
|
||||||
|
const db = e.target.result as IDBDatabase;
|
||||||
|
var store = db.createObjectStore("store", { keyPath: "key" });
|
||||||
|
var index = store.createIndex("index", "indexedProperty");
|
||||||
|
store.add({ key: 1, indexedProperty: "data" });
|
||||||
|
};
|
||||||
|
open_rq.onsuccess = function (e: any) {
|
||||||
|
const db = e.target.result as IDBDatabase;
|
||||||
|
var tx = db.transaction("store");
|
||||||
|
var index = tx.objectStore("store").index("index");
|
||||||
|
tx.abort();
|
||||||
|
|
||||||
|
t.throws(
|
||||||
|
function () {
|
||||||
|
index.get("data");
|
||||||
|
},
|
||||||
|
{ name: "TransactionInactiveError" },
|
||||||
|
);
|
||||||
|
resolve();
|
||||||
|
};
|
||||||
|
});
|
||||||
|
t.pass();
|
||||||
|
});
|
||||||
|
|
||||||
|
// IDBIndex.get() - throw InvalidStateError on index deleted by aborted upgrade
|
||||||
|
test("WPT idbindex_get8.htm", async (t) => {
|
||||||
|
await new Promise<void>((resolve, reject) => {
|
||||||
|
var db: any;
|
||||||
|
|
||||||
|
var open_rq = createdb(t);
|
||||||
|
open_rq.onupgradeneeded = function (e: any) {
|
||||||
|
db = e.target.result;
|
||||||
|
var store = db.createObjectStore("store", { keyPath: "key" });
|
||||||
|
var index = store.createIndex("index", "indexedProperty");
|
||||||
|
store.add({ key: 1, indexedProperty: "data" });
|
||||||
|
|
||||||
|
e.target.transaction.abort();
|
||||||
|
|
||||||
|
t.throws(
|
||||||
|
function () {
|
||||||
|
index.get("data");
|
||||||
|
},
|
||||||
|
{ name: "InvalidStateError" },
|
||||||
|
);
|
||||||
|
resolve();
|
||||||
|
};
|
||||||
|
});
|
||||||
|
t.pass();
|
||||||
|
});
|
||||||
|
Loading…
Reference in New Issue
Block a user