[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[GNUnet-SVN] [taler-wallet-webex] 02/03: memidb work in progress
From: |
gnunet |
Subject: |
[GNUnet-SVN] [taler-wallet-webex] 02/03: memidb work in progress |
Date: |
Sun, 04 Jun 2017 17:56:59 +0200 |
This is an automated email from the git hooks/post-receive script.
dold pushed a commit to branch master
in repository wallet-webex.
commit e0e496b87837080b98caa002725768a497836c9f
Author: Florian Dold <address@hidden>
AuthorDate: Sun Jun 4 01:14:05 2017 +0200
memidb work in progress
---
node_modules/nyc/node_modules/yargs/package.json | 138 +++++++--
package.json | 1 +
src/memidb-test.ts | 114 ++++++++
src/memidb.ts | 352 ++++++++++++++++++++---
tsconfig.json | 1 +
yarn.lock | 4 +
6 files changed, 545 insertions(+), 65 deletions(-)
diff --git a/node_modules/nyc/node_modules/yargs/package.json
b/node_modules/nyc/node_modules/yargs/package.json
index a396ea7b..42fa3bd3 100644
--- a/node_modules/nyc/node_modules/yargs/package.json
+++ b/node_modules/nyc/node_modules/yargs/package.json
@@ -1,16 +1,57 @@
{
- "name": "yargs",
- "version": "7.1.0",
- "description": "yargs the modern, pirate-themed, successor to optimist.",
- "main": "./index.js",
- "files": [
- "index.js",
- "yargs.js",
- "lib",
- "locales",
- "completion.sh.hbs",
- "LICENSE"
+ "_args": [
+ [
+ {
+ "raw": "address@hidden",
+ "scope": null,
+ "escapedName": "yargs",
+ "name": "yargs",
+ "rawSpec": "^7.1.0",
+ "spec": ">=7.1.0 <8.0.0",
+ "type": "range"
+ },
+ "/Users/benjamincoe/oss/nyc"
+ ]
+ ],
+ "_from": "yargs@>=7.1.0 <8.0.0",
+ "_id": "address@hidden",
+ "_inCache": true,
+ "_location": "/yargs",
+ "_nodeVersion": "6.9.5",
+ "_npmOperationalInternal": {
+ "host": "packages-12-west.internal.npmjs.com",
+ "tmp": "tmp/yargs-7.1.0.tgz_1492119927787_0.18849953636527061"
+ },
+ "_npmUser": {
+ "name": "bcoe",
+ "email": "address@hidden"
+ },
+ "_npmVersion": "4.5.0",
+ "_phantomChildren": {
+ "string-width": "1.0.2",
+ "strip-ansi": "3.0.1",
+ "wrap-ansi": "2.1.0"
+ },
+ "_requested": {
+ "raw": "address@hidden",
+ "scope": null,
+ "escapedName": "yargs",
+ "name": "yargs",
+ "rawSpec": "^7.1.0",
+ "spec": ">=7.1.0 <8.0.0",
+ "type": "range"
+ },
+ "_requiredBy": [
+ "/"
],
+ "_resolved": "https://registry.npmjs.org/yargs/-/yargs-7.1.0.tgz",
+ "_shasum": "6ba318eb16961727f5d284f8ea003e8d6154d0c8",
+ "_shrinkwrap": null,
+ "_spec": "address@hidden",
+ "_where": "/Users/benjamincoe/oss/nyc",
+ "bugs": {
+ "url": "https://github.com/yargs/yargs/issues"
+ },
"dependencies": {
"camelcase": "^3.0.0",
"cliui": "^3.2.0",
@@ -26,6 +67,7 @@
"y18n": "^3.2.1",
"yargs-parser": "^5.0.0"
},
+ "description": "yargs the modern, pirate-themed, successor to optimist.",
"devDependencies": {
"chai": "^3.4.1",
"chalk": "^1.1.3",
@@ -41,22 +83,31 @@
"standard-version": "^3.0.0",
"which": "^1.2.9"
},
- "scripts": {
- "pretest": "standard",
- "test": "nyc --cache mocha --require ./test/before.js --timeout=8000
--check-leaks",
- "coverage": "nyc report --reporter=text-lcov | coveralls",
- "release": "standard-version"
+ "directories": {},
+ "dist": {
+ "shasum": "6ba318eb16961727f5d284f8ea003e8d6154d0c8",
+ "tarball": "https://registry.npmjs.org/yargs/-/yargs-7.1.0.tgz"
},
- "repository": {
- "type": "git",
- "url": "http://github.com/yargs/yargs.git"
+ "engine": {
+ "node": ">=0.10"
},
- "homepage": "http://yargs.js.org/",
- "standard": {
+ "files": [
+ "index.js",
+ "yargs.js",
+ "lib",
+ "locales",
+ "completion.sh.hbs",
+ "LICENSE"
+ ],
+ "gitHead": "e7359d632595c3a5fcfd691994859b66e8943c85",
+ "greenkeeper": {
"ignore": [
- "**/example/**"
+ "string-width",
+ "read-pkg-up",
+ "camelcase"
]
},
+ "homepage": "http://yargs.js.org/",
"keywords": [
"argument",
"args",
@@ -67,14 +118,43 @@
"command"
],
"license": "MIT",
- "engine": {
- "node": ">=0.10"
+ "main": "./index.js",
+ "maintainers": [
+ {
+ "name": "bcoe",
+ "email": "address@hidden"
+ },
+ {
+ "name": "chevex",
+ "email": "address@hidden"
+ },
+ {
+ "name": "nexdrew",
+ "email": "address@hidden"
+ },
+ {
+ "name": "nylen",
+ "email": "address@hidden"
+ }
+ ],
+ "name": "yargs",
+ "optionalDependencies": {},
+ "readme": " yargs\n========\n\nYargs be a node.js library fer hearties
tryin' ter parse optstrings.\n\nWith yargs, ye be havin' a map that leads
straight to yer treasure! Treasure of course, being a simple option
hash.\n\n[![Build Status][travis-image]][travis-url]\n[![Coverage
Status][coveralls-image]][coveralls-url]\n[![NPM
version][npm-image]][npm-url]\n[![Windows
Tests][windows-image]][windows-url]\n[![js-standard-style][standard-image]][standard-url]\n[![Conventional
Commits][con [...]
+ "readmeFilename": "README.md",
+ "repository": {
+ "type": "git",
+ "url": "git+ssh://address@hidden/yargs/yargs.git"
},
- "greenkeeper": {
+ "scripts": {
+ "coverage": "nyc report --reporter=text-lcov | coveralls",
+ "pretest": "standard",
+ "release": "standard-version",
+ "test": "nyc --cache mocha --require ./test/before.js --timeout=8000
--check-leaks"
+ },
+ "standard": {
"ignore": [
- "string-width",
- "read-pkg-up",
- "camelcase"
+ "**/example/**"
]
- }
+ },
+ "version": "7.1.0"
}
diff --git a/package.json b/package.json
index 0bf0ae3c..b4b79b6a 100644
--- a/package.json
+++ b/package.json
@@ -47,6 +47,7 @@
"pogen": "file:tooling/pogen/",
"react": "^15.5.4",
"react-dom": "^15.5.4",
+ "structured-clone": "^0.2.2",
"through2": "^2.0.1",
"ts-loader": "^2.0.3",
"tslint": "^5.3.2",
diff --git a/src/memidb-test.ts b/src/memidb-test.ts
new file mode 100644
index 00000000..8f8498a6
--- /dev/null
+++ b/src/memidb-test.ts
@@ -0,0 +1,114 @@
+/*
+ This file is part of TALER
+ (C) 2017 Inria and GNUnet e.V.
+
+ TALER is free software; you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation; either version 3, or (at your option) any later version.
+
+ TALER is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
+ A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along with
+ TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
+ */
+
+import {test} from "ava";
+import * as memidb from "./memidb";
+
+test.cb("db open", (t) => {
+ let ncb = 0;
+ const idb = new memidb.MemoryIDBFactory();
+ const req = idb.open("testdb");
+ let called = false;
+ req.onupgradeneeded = (evt) => {
+ ncb += 1;
+ called = true;
+ t.is(req.result, evt.target);
+ t.is(evt.oldVersion, 0);
+ t.is(evt.newVersion, 1);
+ t.truthy(req.result);
+ t.pass();
+ }
+ req.onsuccess = (evt) => {
+ t.is(ncb, 1);
+ t.is(req.result, evt.target);
+ t.truthy(req.result);
+ t.end();
+ }
+});
+
+test.cb("store creation", (t) => {
+ const idb = new memidb.MemoryIDBFactory();
+ const req = idb.open("testdb");
+ req.onupgradeneeded = (evt) => {
+ const db: IDBDatabase = req.result;
+
+ const store1 = db.createObjectStore("b-store");
+ t.is(store1.name, "b-store");
+ t.deepEqual(Array.from(db.objectStoreNames), ["b-store"]);
+
+ const store2 = db.createObjectStore("a-store");
+ t.is(store2.name, "a-store");
+ t.deepEqual(Array.from(db.objectStoreNames), ["a-store", "b-store"]);
+
+ const store3 = db.createObjectStore("c-store");
+ t.is(store3.name, "c-store");
+ t.deepEqual(Array.from(db.objectStoreNames), ["a-store", "b-store",
"c-store"]);
+ t.pass();
+ }
+ req.onsuccess = (evt) => {
+ t.end();
+ }
+});
+
+
+test.cb("put and get", (t) => {
+ const idb = new memidb.MemoryIDBFactory();
+ const req = idb.open("testdb");
+ req.onupgradeneeded = (evt) => {
+ const db: IDBDatabase = req.result;
+ const store1 = db.createObjectStore("mystore");
+ store1.put({answer: 42}, "a");
+ }
+ req.onsuccess = (evt) => {
+ t.end()
+ }
+});
+
+
+test("key path evaluation", (t) => {
+ const obj = {
+ a: {
+ b: {
+ c: 42,
+ },
+ },
+ b: "hello",
+ "": "spam",
+ arr: ["foo", "bar"],
+ }
+ t.deepEqual(memidb.evaluateKeyPath(obj, ""), obj);
+ t.deepEqual(memidb.evaluateKeyPath(obj, "a.b.c"), 42);
+ t.deepEqual(memidb.evaluateKeyPath(obj, "a.b"), {c: 42});
+ t.deepEqual(memidb.evaluateKeyPath(obj, "foo"), undefined);
+ t.deepEqual(memidb.evaluateKeyPath(obj, ["a.b.c", "foo"]), undefined);
+ t.deepEqual(memidb.evaluateKeyPath(obj, ["a.b.c", "b"]), [42, "hello"]);
+ t.deepEqual(memidb.evaluateKeyPath(obj, "arr.0"), "foo");
+ t.deepEqual(memidb.evaluateKeyPath(obj, "."), "spam");
+});
+
+test("key path evaluation with replacement", (t) => {
+ const obj: any = {
+ a: {
+ b: {
+ c: 42,
+ },
+ },
+ }
+ memidb.evaluateKeyPath(obj, "a.b.c", 24);
+ t.is(obj.a.b.c, 24);
+ memidb.evaluateKeyPath(obj, "a.b", 24);
+ t.is(obj.a.b, 24);
+});
diff --git a/src/memidb.ts b/src/memidb.ts
index 36607d71..14a1efbe 100644
--- a/src/memidb.ts
+++ b/src/memidb.ts
@@ -29,20 +29,25 @@
const structuredClone = require("structured-clone");
-const structuredSerialize = require("structured-clone").serialize;
-interface StoredObject {
- key: any;
- object: string;
-}
-
interface Store {
name: string;
- keyPath: string | string[];
+ keyPath?: string | string[];
keyGenerator: number;
autoIncrement: boolean;
- objects: { [strKey: string]: StoredObject };
+ objects: { [primaryKey: string]: any };
+ indices: { [indexName: string]: Index };
+}
+
+interface Index {
+ multiEntry: boolean;
+ unique: boolean;
+
+ /**
+ * Map the index's key to the primary key.
+ */
+ map: { [indexKey: string]: string[] };
}
@@ -80,11 +85,80 @@ class MyDomStringList extends Array<string> implements
DOMStringList {
}
-function callEventHandler(h: EventListenerOrEventListenerObject, evt: Event,
target: any) {
- if ("handleEvent" in h) {
- (h as EventListenerObject).handleEvent(evt);
- } else {
- (h as EventListener).call(target, evt);
+class MyKeyRange implements IDBKeyRange {
+ static only(value: any): IDBKeyRange {
+ return new MyKeyRange(value, value, false, false);
+ }
+
+ static bound(lower: any, upper: any, lowerOpen: boolean = false, upperOpen:
boolean = false) {
+ return new MyKeyRange(lower, upper, lowerOpen, upperOpen);
+ }
+
+ static lowerBound(lower: any, lowerOpen: boolean = false) {
+ return new MyKeyRange(lower, undefined, lowerOpen, true);
+ }
+
+ static upperBound(upper: any, upperOpen: boolean = false) {
+ return new MyKeyRange(undefined, upper, true, upperOpen);
+ }
+
+ constructor(public lower: any, public upper: any, public lowerOpen: boolean,
public upperOpen: boolean) {
+ }
+}
+
+
+/**
+ * Type guard for an IDBKeyRange.
+ */
+export function isKeyRange(obj: any): obj is IDBKeyRange {
+ return (typeof obj === "object" &&
+ "lower" in obj && "upper" in obj &&
+ "lowerOpen" in obj && "upperOpen" in obj);
+}
+
+
+class IndexHandle implements IDBIndex {
+
+ _unique: boolean;
+ _multiEntry: boolean;
+
+ get keyPath(): string | string[] {
+ throw Error("not implemented");
+ }
+
+ get name () {
+ return this.indexName;
+ }
+
+ get unique() {
+ return this._unique;
+ }
+
+ get multiEntry() {
+ return this._multiEntry;
+ }
+
+ constructor(public objectStore: MyObjectStore, public indexName: string) {
+ }
+
+ count(key?: IDBKeyRange | IDBValidKey): IDBRequest {
+ throw Error("not implemented");
+ }
+
+ get(key: IDBKeyRange | IDBValidKey): IDBRequest {
+ throw Error("not implemented");
+ }
+
+ getKey(key: IDBKeyRange | IDBValidKey): IDBRequest {
+ throw Error("not implemented");
+ }
+
+ openCursor(range?: IDBKeyRange | IDBValidKey, direction?:
IDBCursorDirection): IDBRequest {
+ throw Error("not implemented");
+ }
+
+ openKeyCursor(range?: IDBKeyRange | IDBValidKey, direction?:
IDBCursorDirection): IDBRequest {
+ throw Error("not implemented");
}
}
@@ -92,9 +166,10 @@ class MyRequest implements IDBRequest {
onerror: (this: IDBRequest, ev: Event) => any;
onsuccess: (this: IDBRequest, ev: Event) => any;
- successHandlers: Array<(this: IDBRequest, ev: Event) => any>;
+ successHandlers: Array<(this: IDBRequest, ev: Event) => any> = [];
done: boolean = false;
+ _result: any;
constructor(public _transaction: Transaction, public runner: () => void) {
}
@@ -113,7 +188,7 @@ class MyRequest implements IDBRequest {
}
get result(): any {
- return null;
+ return this._result;
}
get source() {
@@ -188,17 +263,78 @@ class OpenDBRequest extends MyRequest implements
IDBOpenDBRequest {
}
}
+function follow(x: any, s: string, replacement?: any): any {
+ if (s === "") {
+ return x;
+ }
+ const ptIdx = s.indexOf(".");
+ if (ptIdx < 0) {
+ const v = x[s];
+ if (replacement !== undefined) {
+ x[s] = replacement;
+ }
+ return v;
+ } else {
+ const identifier = s.substring(0, ptIdx);
+ const rest = s.substring(ptIdx + 1);
+ return follow(x[identifier], rest, replacement);
+ }
+}
+
+export function evaluateKeyPath(x: any, path: string | string[], replacement?:
any): any {
+ if (typeof path === "string") {
+ return follow(x, path, replacement);
+ } else if (Array.isArray(path)) {
+ const res: any[] = [];
+ for (let s of path) {
+ let c = follow(x, s, replacement);
+ if (c === undefined) {
+ return undefined;
+ }
+ res.push(c);
+ }
+ return res;
+ } else {
+ throw Error("invalid key path, must be string or array of strings");
+ }
+}
+
+function stringifyKey(key: any) {
+ return JSON.stringify(key);
+}
+
+export function isValidKey(key: any, memo: any[] = []) {
+ if (typeof key === "string" || typeof key === "number" || key instanceof
Date) {
+ return true;
+ }
+ if (Array.isArray(key)) {
+ for (const element of key) {
+ if (!isValidKey(element, memo.concat([key]))) {
+ return false;
+ }
+ }
+ return true;
+ }
+ return false;
+}
class MyObjectStore implements IDBObjectStore {
+
+ _keyPath: string | string[] | undefined;
+ _autoIncrement: boolean;
+
get indexNames() {
return new DOMStringList();
}
- constructor(public transaction: Transaction, public dbName: string, public
storeName: string) {
+ constructor(public transaction: Transaction, public storeName: string) {
+ this._keyPath =
this.transaction.transactionDbData.stores[this.storeName].keyPath as (string |
string[]);
+ this._autoIncrement =
this.transaction.transactionDbData.stores[this.storeName].autoIncrement;
}
- get keyPath() {
- return this.transaction.db.dbData.stores[this.storeName].keyPath;
+ get keyPath(): string | string[] {
+ // TypeScript definitions are wrong here and don't permit a null keyPath
+ return this._keyPath as (string | string[]);
}
get name() {
@@ -206,15 +342,77 @@ class MyObjectStore implements IDBObjectStore {
}
get autoIncrement() {
- return this.transaction.db.dbData.stores[this.storeName].autoIncrement;
+ return this._autoIncrement;
}
- add(value: any, key?: any): IDBRequest {
- throw Error("not implemented");
+ storeImpl(originalValue: any, key: any|undefined, allowExisting: boolean) {
+ if (this.transaction.mode === "readonly") {
+ throw Error();
+ }
+ if (!this.transaction.active) {
+ throw Error();
+ }
+ if
(!this.transaction.transactionDbData.stores.hasOwnProperty(this.storeName)) {
+ throw Error("object store was deleted");
+ }
+
+ const store = this.transaction.transactionDbData.stores[this.storeName];
+
+ const value = structuredClone(originalValue);
+
+ if (this.keyPath) {
+ // we're dealine with in-line keys
+ if (key) {
+ throw Error("keys not allowed with in-line keys");
+ }
+ key = evaluateKeyPath(value, this.keyPath);
+ if (!key && !this.autoIncrement) {
+ throw Error("key path must evaluate to key for in-line stores without
autoIncrement");
+ }
+ if (this.autoIncrement) {
+ if (key && typeof key === "number") {
+ store.keyGenerator = key + 1;
+ } else {
+ key = store.keyGenerator;
+ store.keyGenerator += 1;
+ evaluateKeyPath(value, this.keyPath, key);
+ }
+ }
+ } else {
+ // we're dealing with out-of-line keys
+ if (!key && !this.autoIncrement) {
+ throw Error("key must be provided for out-of-line stores without
autoIncrement");
+ }
+ key = this.transaction.transactionDbData.stores
+ if (this.autoIncrement) {
+ if (key && typeof key === "number") {
+ store.keyGenerator = key + 1;
+ } else {
+ key = store.keyGenerator;
+ store.keyGenerator += 1;
+ }
+ }
+ }
+
+ const stringKey = stringifyKey(key);
+
+ if (store.objects.hasOwnProperty(stringKey) && !allowExisting) {
+ throw Error("key already exists");
+ }
+
+ store.objects[stringKey] = value;
+
+ const req = new MyRequest(this.transaction, () => {
+ });
+ return req;
}
put(value: any, key?: any): IDBRequest {
- throw Error("not implemented");
+ return this.storeImpl(value, key, true);
+ }
+
+ add(value: any, key?: any): IDBRequest {
+ return this.storeImpl(value, key, false);
}
delete(key: any): IDBRequest {
@@ -242,7 +440,7 @@ class MyObjectStore implements IDBObjectStore {
}
index(indexName: string): IDBIndex {
- throw Error("not implemented");
+ return new IndexHandle(this, indexName);
}
openCursor(range?: IDBKeyRange | IDBValidKey, direction?:
IDBCursorDirection): IDBRequest {
@@ -257,19 +455,31 @@ class Db implements IDBDatabase {
onerror: (this: IDBDatabase, ev: Event) => any;
onversionchange: (ev: IDBVersionChangeEvent) => any;
+ _storeNames: string[] = [];
+
constructor(private _name: string, private _version: number, private
factory: MemoryIDBFactory) {
+ for (let storeName in this.dbData.stores) {
+ if (this.dbData.stores.hasOwnProperty(storeName)) {
+ this._storeNames.push(storeName);
+ }
+ }
+ this._storeNames.sort();
}
- get dbData() {
+ get dbData(): Database {
return this.factory.data[this._name];
}
+ set dbData(data) {
+ this.factory.data[this._name] = data;
+ }
+
get name() {
return this._name;
}
get objectStoreNames() {
- return new MyDomStringList();
+ return new MyDomStringList(...this._storeNames);
}
get version() {
@@ -284,11 +494,44 @@ class Db implements IDBDatabase {
if (tx.mode !== "versionchange") {
throw Error("invalid mode");
}
- throw Error("not implemented");
+
+ const td = tx.transactionDbData;
+ if (td.stores[name]) {
+ throw Error("object store already exists");
+ }
+
+ td.stores[name] = {
+ autoIncrement: !!(optionalParameters &&
optionalParameters.autoIncrement),
+ indices: {},
+ keyGenerator: 1,
+ name,
+ objects: [],
+ };
+
+ this._storeNames.push(name);
+ this._storeNames.sort();
+
+ return new MyObjectStore(tx, name);
}
deleteObjectStore(name: string): void {
- throw Error("not implemented");
+ let tx = this.factory.getTransaction();
+ if (tx.mode !== "versionchange") {
+ throw Error("invalid mode");
+ }
+
+ const td = tx.transactionDbData;
+ if (td.stores[name]) {
+ throw Error("object store does not exists");
+ }
+
+ const idx = this._storeNames.indexOf(name);
+ if (idx < 0) {
+ throw Error();
+ }
+ this._storeNames.splice(idx, 1);
+
+ delete td.stores[name];
}
transaction(storeNames: string | string[], mode: IDBTransactionMode =
"readonly"): IDBTransaction {
@@ -342,11 +585,30 @@ class Transaction implements IDBTransaction {
return this._mode;
}
+ get active(): boolean {
+ return this.state === TransactionState.Running || this.state ===
TransactionState.Created;
+ }
+
start() {
if (this.state != TransactionState.Created) {
throw Error();
}
+ this.state = TransactionState.Running;
this._transactionDbData = structuredClone(this.dbHandle.dbData);
+ if (!this._transactionDbData) {
+ throw Error();
+ }
+ }
+
+ commit() {
+ if (this.state != TransactionState.Running) {
+ throw Error();
+ }
+ if (!this._transactionDbData) {
+ throw Error();
+ }
+ this.state = TransactionState.Commited;
+ this.dbHandle.dbData = this._transactionDbData;
}
get error(): DOMException {
@@ -373,7 +635,7 @@ class Transaction implements IDBTransaction {
}
objectStore(storeName: string): IDBObjectStore {
- return new MyObjectStore(this, this.dbName, storeName);
+ return new MyObjectStore(this, storeName);
}
dispatchEvent(evt: Event): boolean {
@@ -425,8 +687,9 @@ class MyEvent implements Event {
_timeStamp: number = 0;
_type: string;
- constructor(typeArg: string) {
+ constructor(typeArg: string, target: any) {
this._type = typeArg;
+ this._target = target;
}
get eventPhase() {
@@ -519,10 +782,10 @@ class MyEvent implements Event {
class VersionChangeEvent extends MyEvent {
_newVersion: number|null;
_oldVersion: number;
- constructor(oldVersion: number, newVersion?: number) {
- super("VersionChange");
+ constructor(oldVersion: number, newVersion: number|null, target: any) {
+ super("VersionChange", target);
this._oldVersion = oldVersion;
- this._newVersion = newVersion || null;
+ this._newVersion = newVersion;
}
get newVersion() {
@@ -535,7 +798,7 @@ class VersionChangeEvent extends MyEvent {
}
-class MemoryIDBFactory implements IDBFactory {
+export class MemoryIDBFactory implements IDBFactory {
data: Databases = {};
currentRequest: MyRequest|undefined;
@@ -570,7 +833,7 @@ class MemoryIDBFactory implements IDBFactory {
// auto-commit the transaction that the
// previous request worked on.
let lastTx = prevRequest._transaction;
- this.data[lastTx.dbName] = lastTx.transactionDbData;
+ lastTx.commit();
}
};
alreadyResolved.then(() => {
@@ -604,13 +867,19 @@ class MemoryIDBFactory implements IDBFactory {
}
let upgradeNeeded = false;
+ let oldVersion: number;
let mydb: Database;
if (dbName in this.data) {
mydb = this.data[dbName];
+ if (!mydb) {
+ throw Error();
+ }
+ oldVersion = mydb.version;
if (version === undefined || version == mydb.version) {
// we can open without upgrading
} else if (version > mydb.version) {
upgradeNeeded = true;
+ mydb.version = version;
} else {
throw Error("version error");
}
@@ -621,17 +890,21 @@ class MemoryIDBFactory implements IDBFactory {
version: (version || 1),
};
upgradeNeeded = true;
+ oldVersion = 0;
}
+ this.data[dbName] = mydb;
+
const db = new Db(dbName, mydb.version, this);
const tx = new Transaction(dbName, db, "versionchange");
const req = new OpenDBRequest(tx, () => {
+ req._result = db;
if (upgradeNeeded) {
- let versionChangeEvt = new VersionChangeEvent(mydb.version, version);
+ let versionChangeEvt = new VersionChangeEvent(oldVersion,
mydb.version, db);
req.callOnupgradeneeded(versionChangeEvt);
}
- let successEvent = new MyEvent("success");
+ let successEvent = new MyEvent("success", db);
req.callSuccess(successEvent);
});
@@ -640,3 +913,10 @@ class MemoryIDBFactory implements IDBFactory {
return req;
}
}
+
+/**
+ * Inject our IndexedDb implementation in the global namespace,
+ * potentially replacing an existing implementation.
+ */
+export function injectGlobals() {
+}
diff --git a/tsconfig.json b/tsconfig.json
index 1f649ef1..dee558cf 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -40,6 +40,7 @@
"src/i18n.tsx",
"src/i18n/strings.ts",
"src/logging.ts",
+ "src/memidb-test.ts",
"src/memidb.ts",
"src/query.ts",
"src/timer.ts",
diff --git a/yarn.lock b/yarn.lock
index 5bd122cb..0769e283 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -4610,6 +4610,10 @@ address@hidden:
version "2.0.1"
resolved
"https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a"
address@hidden:
+ version "0.2.2"
+ resolved
"https://registry.yarnpkg.com/structured-clone/-/structured-clone-0.2.2.tgz#ac92b6be31958a643db30f1335abc6a1b02dfdc2"
+
address@hidden:
version "0.2.0"
resolved
"https://registry.yarnpkg.com/supports-color/-/supports-color-0.2.0.tgz#d92de2694eb3f67323973d7ae3d8b55b4c22190a"
--
To stop receiving notification emails like this one, please contact
address@hidden