/
transaction-constructor.ts
72 lines (68 loc) · 2.41 KB
/
transaction-constructor.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
import { Dexie } from '../dexie';
import { makeClassConstructor } from '../../functions/make-class-constructor';
import { Transaction } from './transaction';
import { DbSchema } from '../../public/types/db-schema';
import Events from '../../helpers/Events';
import Promise, { rejection } from '../../helpers/promise';
export interface TransactionConstructor<T extends Transaction=Transaction> {
new (
mode: IDBTransactionMode,
storeNames: string[],
dbschema: DbSchema,
chromeTransactionDurability: ChromeTransactionDurability,
parent?: Transaction) : T;
prototype: T;
}
/** Generates a Transaction constructor bound to given Dexie instance.
*
* The purpose of having dynamically created constructors, is to allow
* addons to extend classes for a certain Dexie instance without affecting
* other db instances.
*/
export function createTransactionConstructor(db: Dexie) {
return makeClassConstructor<TransactionConstructor<Transaction>>(
Transaction.prototype,
function Transaction (
this: Transaction,
mode: IDBTransactionMode,
storeNames: string[],
dbschema: DbSchema,
chromeTransactionDurability: ChromeTransactionDurability,
parent?: Transaction)
{
this.db = db;
this.mode = mode;
this.storeNames = storeNames;
this.schema = dbschema;
this.chromeTransactionDurability = chromeTransactionDurability;
this.idbtrans = null;
this.on = Events(this, "complete", "error", "abort");
this.parent = parent || null;
this.active = true;
this._reculock = 0;
this._blockedFuncs = [];
this._resolve = null;
this._reject = null;
this._waitingFor = null;
this._waitingQueue = null;
this._spinCount = 0; // Just for debugging waitFor()
this._completion = new Promise ((resolve, reject) => {
this._resolve = resolve;
this._reject = reject;
});
this._completion.then(
()=> {
this.active = false;
this.on.complete.fire();
},
e => {
var wasActive = this.active;
this.active = false;
this.on.error.fire(e);
this.parent ?
this.parent._reject(e) :
wasActive && this.idbtrans && this.idbtrans.abort();
return rejection(e); // Indicate we actually DO NOT catch this error.
});
});
}