summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFlorian Dold <florian.dold@gmail.com>2017-10-15 20:31:50 +0200
committerFlorian Dold <florian.dold@gmail.com>2017-10-15 20:31:50 +0200
commit1eec95e840ff95c4902e4f38f46963f29a086727 (patch)
treefcb0cc6ed799dc5d1cbed2793de60f2c7bbfe8cc
parent8b2f53e3ed810a0539f76feb993f0044bc8c0f38 (diff)
downloadwallet-core-1eec95e840ff95c4902e4f38f46963f29a086727.tar.gz
wallet-core-1eec95e840ff95c4902e4f38f46963f29a086727.tar.bz2
wallet-core-1eec95e840ff95c4902e4f38f46963f29a086727.zip
remove incomplete memory IDB implementation for now
Currently lives in its own branch, will be re-added to master once complete to avoid linting issues.
-rw-r--r--src/i18n/de.po28
-rw-r--r--src/i18n/en-US.po16
-rw-r--r--src/i18n/fr.po16
-rw-r--r--src/i18n/it.po16
-rw-r--r--src/i18n/strings.ts10
-rw-r--r--src/i18n/taler-wallet-webex.pot16
-rw-r--r--src/memidb-test.ts114
-rw-r--r--src/memidb.ts922
8 files changed, 49 insertions, 1089 deletions
diff --git a/src/i18n/de.po b/src/i18n/de.po
index 5cef25386..9950865e0 100644
--- a/src/i18n/de.po
+++ b/src/i18n/de.po
@@ -61,7 +61,7 @@ msgstr ""
msgid "The merchant%1$s offers you to purchase:\n"
msgstr ""
-#: src/webex/pages/confirm-contract.tsx:232
+#: src/webex/pages/confirm-contract.tsx:235
#, fuzzy, c-format
msgid "Confirm payment"
msgstr "Bezahlung bestätigen"
@@ -270,38 +270,41 @@ msgid ""
msgstr "Reserve (%1$s) mit %2$s bei %3$s erzeugt"
#: src/webex/pages/popup.tsx:368
-#, c-format
-msgid "Merchant%1$soffered contract%2$s;\n"
+#, fuzzy, c-format
+msgid "Merchant%1$soffered contract%2$s.\n"
msgstr ""
+"%1$s\n"
+" möchte einen Vertrag über %2$s\n"
+" mit Ihnen abschließen."
-#: src/webex/pages/popup.tsx:378
+#: src/webex/pages/popup.tsx:379
#, fuzzy, c-format
msgid "Withdrew%1$sfrom%2$s(%3$s).\n"
msgstr "Reserve (%1$s) mit %2$s bei %3$s erzeugt"
-#: src/webex/pages/popup.tsx:388
+#: src/webex/pages/popup.tsx:389
#, fuzzy, c-format
msgid ""
"Paid%1$sto merchant%2$s.\n"
" (%3$s)\n"
msgstr "Reserve (%1$s) mit %2$s bei %3$s erzeugt"
-#: src/webex/pages/popup.tsx:398
+#: src/webex/pages/popup.tsx:399
#, c-format
msgid "Merchant%1$sgave a refund over%2$s.\n"
msgstr ""
-#: src/webex/pages/popup.tsx:405
+#: src/webex/pages/popup.tsx:406
#, c-format
msgid "Unknown event (%1$s)"
msgstr ""
-#: src/webex/pages/popup.tsx:448
+#: src/webex/pages/popup.tsx:449
#, c-format
msgid "Error: could not retrieve event history"
msgstr ""
-#: src/webex/pages/popup.tsx:473
+#: src/webex/pages/popup.tsx:474
#, c-format
msgid "Your wallet has no events recorded."
msgstr "Ihre Geldbörse verzeichnet keine Vorkommnisse."
@@ -342,13 +345,6 @@ msgid "Unknown Wire Detail"
msgstr ""
#, fuzzy
-#~ msgid "The merchant%1$swants to enter a contract over%2$s with you.\n"
-#~ msgstr ""
-#~ "%1$s\n"
-#~ " möchte einen Vertrag über %2$s\n"
-#~ " mit Ihnen abschließen."
-
-#, fuzzy
#~ msgid "You are about to purchase:"
#~ msgstr "Sie sind dabei, Folgendes zu kaufen:"
diff --git a/src/i18n/en-US.po b/src/i18n/en-US.po
index eb8e36240..117f00b4b 100644
--- a/src/i18n/en-US.po
+++ b/src/i18n/en-US.po
@@ -61,7 +61,7 @@ msgstr ""
msgid "The merchant%1$s offers you to purchase:\n"
msgstr ""
-#: src/webex/pages/confirm-contract.tsx:232
+#: src/webex/pages/confirm-contract.tsx:235
#, c-format
msgid "Confirm payment"
msgstr ""
@@ -271,37 +271,37 @@ msgstr ""
#: src/webex/pages/popup.tsx:368
#, c-format
-msgid "Merchant%1$soffered contract%2$s;\n"
+msgid "Merchant%1$soffered contract%2$s.\n"
msgstr ""
-#: src/webex/pages/popup.tsx:378
+#: src/webex/pages/popup.tsx:379
#, c-format
msgid "Withdrew%1$sfrom%2$s(%3$s).\n"
msgstr ""
-#: src/webex/pages/popup.tsx:388
+#: src/webex/pages/popup.tsx:389
#, c-format
msgid ""
"Paid%1$sto merchant%2$s.\n"
" (%3$s)\n"
msgstr ""
-#: src/webex/pages/popup.tsx:398
+#: src/webex/pages/popup.tsx:399
#, c-format
msgid "Merchant%1$sgave a refund over%2$s.\n"
msgstr ""
-#: src/webex/pages/popup.tsx:405
+#: src/webex/pages/popup.tsx:406
#, c-format
msgid "Unknown event (%1$s)"
msgstr ""
-#: src/webex/pages/popup.tsx:448
+#: src/webex/pages/popup.tsx:449
#, c-format
msgid "Error: could not retrieve event history"
msgstr ""
-#: src/webex/pages/popup.tsx:473
+#: src/webex/pages/popup.tsx:474
#, c-format
msgid "Your wallet has no events recorded."
msgstr ""
diff --git a/src/i18n/fr.po b/src/i18n/fr.po
index 1d55c916d..fe9f3902f 100644
--- a/src/i18n/fr.po
+++ b/src/i18n/fr.po
@@ -61,7 +61,7 @@ msgstr ""
msgid "The merchant%1$s offers you to purchase:\n"
msgstr ""
-#: src/webex/pages/confirm-contract.tsx:232
+#: src/webex/pages/confirm-contract.tsx:235
#, c-format
msgid "Confirm payment"
msgstr ""
@@ -271,37 +271,37 @@ msgstr ""
#: src/webex/pages/popup.tsx:368
#, c-format
-msgid "Merchant%1$soffered contract%2$s;\n"
+msgid "Merchant%1$soffered contract%2$s.\n"
msgstr ""
-#: src/webex/pages/popup.tsx:378
+#: src/webex/pages/popup.tsx:379
#, c-format
msgid "Withdrew%1$sfrom%2$s(%3$s).\n"
msgstr ""
-#: src/webex/pages/popup.tsx:388
+#: src/webex/pages/popup.tsx:389
#, c-format
msgid ""
"Paid%1$sto merchant%2$s.\n"
" (%3$s)\n"
msgstr ""
-#: src/webex/pages/popup.tsx:398
+#: src/webex/pages/popup.tsx:399
#, c-format
msgid "Merchant%1$sgave a refund over%2$s.\n"
msgstr ""
-#: src/webex/pages/popup.tsx:405
+#: src/webex/pages/popup.tsx:406
#, c-format
msgid "Unknown event (%1$s)"
msgstr ""
-#: src/webex/pages/popup.tsx:448
+#: src/webex/pages/popup.tsx:449
#, c-format
msgid "Error: could not retrieve event history"
msgstr ""
-#: src/webex/pages/popup.tsx:473
+#: src/webex/pages/popup.tsx:474
#, c-format
msgid "Your wallet has no events recorded."
msgstr ""
diff --git a/src/i18n/it.po b/src/i18n/it.po
index 1d55c916d..fe9f3902f 100644
--- a/src/i18n/it.po
+++ b/src/i18n/it.po
@@ -61,7 +61,7 @@ msgstr ""
msgid "The merchant%1$s offers you to purchase:\n"
msgstr ""
-#: src/webex/pages/confirm-contract.tsx:232
+#: src/webex/pages/confirm-contract.tsx:235
#, c-format
msgid "Confirm payment"
msgstr ""
@@ -271,37 +271,37 @@ msgstr ""
#: src/webex/pages/popup.tsx:368
#, c-format
-msgid "Merchant%1$soffered contract%2$s;\n"
+msgid "Merchant%1$soffered contract%2$s.\n"
msgstr ""
-#: src/webex/pages/popup.tsx:378
+#: src/webex/pages/popup.tsx:379
#, c-format
msgid "Withdrew%1$sfrom%2$s(%3$s).\n"
msgstr ""
-#: src/webex/pages/popup.tsx:388
+#: src/webex/pages/popup.tsx:389
#, c-format
msgid ""
"Paid%1$sto merchant%2$s.\n"
" (%3$s)\n"
msgstr ""
-#: src/webex/pages/popup.tsx:398
+#: src/webex/pages/popup.tsx:399
#, c-format
msgid "Merchant%1$sgave a refund over%2$s.\n"
msgstr ""
-#: src/webex/pages/popup.tsx:405
+#: src/webex/pages/popup.tsx:406
#, c-format
msgid "Unknown event (%1$s)"
msgstr ""
-#: src/webex/pages/popup.tsx:448
+#: src/webex/pages/popup.tsx:449
#, c-format
msgid "Error: could not retrieve event history"
msgstr ""
-#: src/webex/pages/popup.tsx:473
+#: src/webex/pages/popup.tsx:474
#, c-format
msgid "Your wallet has no events recorded."
msgstr ""
diff --git a/src/i18n/strings.ts b/src/i18n/strings.ts
index b83b4ca13..78a52bf2b 100644
--- a/src/i18n/strings.ts
+++ b/src/i18n/strings.ts
@@ -156,8 +156,8 @@ strings['de'] = {
"Started to withdraw\n %1$s from%2$s(%3$s).\n": [
"Reserve (%1$s) mit %2$s bei %3$s erzeugt"
],
- "Merchant%1$soffered contract%2$s;\n": [
- ""
+ "Merchant%1$soffered contract%2$s.\n": [
+ "%1$s\n möchte einen Vertrag über %2$s\n mit Ihnen abschließen."
],
"Withdrew%1$sfrom%2$s(%3$s).\n": [
"Reserve (%1$s) mit %2$s bei %3$s erzeugt"
@@ -342,7 +342,7 @@ strings['en-US'] = {
"Started to withdraw\n %1$s from%2$s(%3$s).\n": [
""
],
- "Merchant%1$soffered contract%2$s;\n": [
+ "Merchant%1$soffered contract%2$s.\n": [
""
],
"Withdrew%1$sfrom%2$s(%3$s).\n": [
@@ -528,7 +528,7 @@ strings['fr'] = {
"Started to withdraw\n %1$s from%2$s(%3$s).\n": [
""
],
- "Merchant%1$soffered contract%2$s;\n": [
+ "Merchant%1$soffered contract%2$s.\n": [
""
],
"Withdrew%1$sfrom%2$s(%3$s).\n": [
@@ -714,7 +714,7 @@ strings['it'] = {
"Started to withdraw\n %1$s from%2$s(%3$s).\n": [
""
],
- "Merchant%1$soffered contract%2$s;\n": [
+ "Merchant%1$soffered contract%2$s.\n": [
""
],
"Withdrew%1$sfrom%2$s(%3$s).\n": [
diff --git a/src/i18n/taler-wallet-webex.pot b/src/i18n/taler-wallet-webex.pot
index 1d55c916d..fe9f3902f 100644
--- a/src/i18n/taler-wallet-webex.pot
+++ b/src/i18n/taler-wallet-webex.pot
@@ -61,7 +61,7 @@ msgstr ""
msgid "The merchant%1$s offers you to purchase:\n"
msgstr ""
-#: src/webex/pages/confirm-contract.tsx:232
+#: src/webex/pages/confirm-contract.tsx:235
#, c-format
msgid "Confirm payment"
msgstr ""
@@ -271,37 +271,37 @@ msgstr ""
#: src/webex/pages/popup.tsx:368
#, c-format
-msgid "Merchant%1$soffered contract%2$s;\n"
+msgid "Merchant%1$soffered contract%2$s.\n"
msgstr ""
-#: src/webex/pages/popup.tsx:378
+#: src/webex/pages/popup.tsx:379
#, c-format
msgid "Withdrew%1$sfrom%2$s(%3$s).\n"
msgstr ""
-#: src/webex/pages/popup.tsx:388
+#: src/webex/pages/popup.tsx:389
#, c-format
msgid ""
"Paid%1$sto merchant%2$s.\n"
" (%3$s)\n"
msgstr ""
-#: src/webex/pages/popup.tsx:398
+#: src/webex/pages/popup.tsx:399
#, c-format
msgid "Merchant%1$sgave a refund over%2$s.\n"
msgstr ""
-#: src/webex/pages/popup.tsx:405
+#: src/webex/pages/popup.tsx:406
#, c-format
msgid "Unknown event (%1$s)"
msgstr ""
-#: src/webex/pages/popup.tsx:448
+#: src/webex/pages/popup.tsx:449
#, c-format
msgid "Error: could not retrieve event history"
msgstr ""
-#: src/webex/pages/popup.tsx:473
+#: src/webex/pages/popup.tsx:474
#, c-format
msgid "Your wallet has no events recorded."
msgstr ""
diff --git a/src/memidb-test.ts b/src/memidb-test.ts
deleted file mode 100644
index b6e4792d3..000000000
--- a/src/memidb-test.ts
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
- 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
deleted file mode 100644
index 795bdc941..000000000
--- a/src/memidb.ts
+++ /dev/null
@@ -1,922 +0,0 @@
-/*
- 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/>
- */
-
-/**
- * In-memory implementation of the IndexedDB interface.
- *
- * Transactions support rollback, but they are all run sequentially within the
- * same MemoryIDBFactory.
- *
- * Every operation involves copying the whole database state, making it only
- * feasible for small databases.
- */
-
-/* work in progres ... */
-/* tslint:disable */
-
-
-const structuredClone = require("structured-clone");
-
-
-interface Store {
- name: string;
- keyPath?: string | string[];
- keyGenerator: number;
- autoIncrement: boolean;
- 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[] };
-}
-
-
-interface Database {
- name: string;
- version: number;
- stores: { [name: string]: Store };
-}
-
-
-interface Databases {
- [name: string]: Database;
-}
-
-
-/**
- * Resolved promise, used to schedule various things
- * by calling .next on it.
- */
-const alreadyResolved = Promise.resolve();
-
-
-class MyDomStringList extends Array<string> implements DOMStringList {
- contains(s: string) {
- for (let i = 0; i < this.length; i++) {
- if (s === this[i]) {
- return true;
- }
- }
- return false;
- }
- item(i: number) {
- return this[i];
- }
-}
-
-
-//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");
- }
-}
-
-class MyRequest implements IDBRequest {
- onerror: (this: IDBRequest, ev: Event) => any;
-
- onsuccess: (this: IDBRequest, ev: Event) => any;
- successHandlers: Array<(this: IDBRequest, ev: Event) => any> = [];
-
- done: boolean = false;
- _result: any;
-
- constructor(public _transaction: Transaction, public runner: () => void) {
- }
-
- callSuccess(ev: Event) {
- if (this.onsuccess) {
- this.onsuccess(ev);
- }
- for (let h of this.successHandlers) {
- h.call(this, ev);
- }
- }
-
- get error(): DOMException {
- return (null as any) as DOMException;
- }
-
- get result(): any {
- return this._result;
- }
-
- get source() {
- // buggy type definitions don't allow null even though it's in
- // the spec.
- return (null as any) as (IDBObjectStore | IDBIndex | IDBCursor);
- }
-
- get transaction() {
- return this._transaction;
- }
-
- dispatchEvent(evt: Event): boolean {
- return false;
- }
-
- get readyState() {
- if (this.done) {
- return "done";
- }
- return "pending";
- }
-
- removeEventListener(type: string,
- listener?: EventListenerOrEventListenerObject,
- options?: boolean | EventListenerOptions): void {
- throw Error("not implemented");
- }
-
- addEventListener(type: string,
- listener: EventListenerOrEventListenerObject,
- useCapture?: boolean): void {
- switch (type) {
- case "success":
- this.successHandlers.push(listener as any);
- break;
- }
- }
-}
-
-class OpenDBRequest extends MyRequest implements IDBOpenDBRequest {
- onblocked: (this: IDBOpenDBRequest, ev: Event) => any;
-
- onupgradeneeded: (this: IDBOpenDBRequest, ev: IDBVersionChangeEvent) => any;
- upgradeneededHandlers: Array<(this: IDBOpenDBRequest, ev: IDBVersionChangeEvent) => any> = [];
-
- callOnupgradeneeded(ev: IDBVersionChangeEvent) {
- if (this.onupgradeneeded) {
- this.onupgradeneeded(ev);
- }
- for (let h of this.upgradeneededHandlers) {
- h.call(this, ev);
- }
- }
-
- removeEventListener(type: string,
- listener?: EventListenerOrEventListenerObject,
- options?: boolean | EventListenerOptions): void {
- throw Error("not implemented");
- }
-
- addEventListener(type: string,
- listener: EventListenerOrEventListenerObject,
- useCapture?: boolean): void {
- switch (type) {
- case "upgradeneeded":
- this.upgradeneededHandlers.push(listener as any);
- break;
- default:
- super.addEventListener(type, listener, useCapture);
- }
- }
-}
-
-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 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(): string | string[] {
- // TypeScript definitions are wrong here and don't permit a null keyPath
- return this._keyPath as (string | string[]);
- }
-
- get name() {
- return this.storeName;
- }
-
- get autoIncrement() {
- return this._autoIncrement;
- }
-
- 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 {
- return this.storeImpl(value, key, true);
- }
-
- add(value: any, key?: any): IDBRequest {
- return this.storeImpl(value, key, false);
- }
-
- delete(key: any): IDBRequest {
- throw Error("not implemented");
- }
-
- get(key: any): IDBRequest {
- throw Error("not implemented");
- }
-
- deleteIndex(indexName: string) {
- throw Error("not implemented");
- }
-
- clear(): IDBRequest {
- throw Error("not implemented");
- }
-
- count(key?: any): IDBRequest {
- throw Error("not implemented");
- }
-
- createIndex(name: string, keyPath: string | string[], optionalParameters?: IDBIndexParameters): IDBIndex {
- throw Error("not implemented");
- }
-
- index(indexName: string): IDBIndex {
- return new IndexHandle(this, indexName);
- }
-
- openCursor(range?: IDBKeyRange | IDBValidKey, direction?: IDBCursorDirection): IDBRequest {
- throw Error("not implemented");
- }
-}
-
-
-class Db implements IDBDatabase {
-
- onabort: (this: IDBDatabase, ev: Event) => any;
- 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(): 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(...this._storeNames);
- }
-
- get version() {
- return this._version;
- }
-
- close() {
- }
-
- createObjectStore(name: string, optionalParameters?: IDBObjectStoreParameters): IDBObjectStore {
- 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 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 {
- 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 {
- const tx = new Transaction(this._name, this, mode);
- return tx;
- }
-
- dispatchEvent(evt: Event): boolean {
- throw Error("not implemented");
- }
-
- removeEventListener(type: string,
- listener?: EventListenerOrEventListenerObject,
- options?: boolean | EventListenerOptions): void {
- throw Error("not implemented");
- }
-
- addEventListener(type: string,
- listener: EventListenerOrEventListenerObject,
- useCapture?: boolean): void {
- throw Error("not implemented");
- }
-}
-
-enum TransactionState {
- Created = 1,
- Running = 2,
- Commited = 3,
- Aborted = 4,
-}
-
-class Transaction implements IDBTransaction {
- readonly READ_ONLY: string = "readonly";
- readonly READ_WRITE: string = "readwrite";
- readonly VERSION_CHANGE: string = "versionchange";
-
- onabort: (this: IDBTransaction, ev: Event) => any;
- onerror: (this: IDBTransaction, ev: Event) => any;
- oncomplete: (this: IDBTransaction, ev: Event) => any;
-
- completeHandlers: Array<(this: IDBTransaction, ev: Event) => any> = [];
-
- state: TransactionState = TransactionState.Created;
-
- _transactionDbData: Database|undefined;
-
- constructor(public dbName: string, public dbHandle: Db, public _mode: IDBTransactionMode) {
- }
-
- get mode() {
- 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 {
- throw Error("not implemented");
- }
-
- get db() {
- return this.dbHandle;
- }
-
- get transactionDbData() {
- if (this.state != TransactionState.Running) {
- throw Error();
- }
- let d = this._transactionDbData;
- if (!d) {
- throw Error();
- }
- return d;
- }
-
- abort() {
- throw Error("not implemented");
- }
-
- objectStore(storeName: string): IDBObjectStore {
- return new MyObjectStore(this, storeName);
- }
-
- dispatchEvent(evt: Event): boolean {
- throw Error("not implemented");
- }
-
- removeEventListener(type: string,
- listener?: EventListenerOrEventListenerObject,
- options?: boolean | EventListenerOptions): void {
- throw Error("not implemented");
- }
-
- addEventListener(type: string,
- listener: EventListenerOrEventListenerObject,
- useCapture?: boolean): void {
- switch (type) {
- case "complete":
- this.completeHandlers.push(listener as any);
- break;
- }
- }
-
- callComplete(ev: Event) {
- if (this.oncomplete) {
- this.oncomplete(ev);
- }
- for (let h of this.completeHandlers) {
- h.call(this, ev);
- }
- }
-}
-
-
-/**
- * Polyfill for CustomEvent.
- */
-class MyEvent implements Event {
- readonly NONE: number = 0;
- readonly CAPTURING_PHASE: number = 1;
- readonly AT_TARGET: number = 2;
- readonly BUBBLING_PHASE: number = 3;
-
- _bubbles = false;
- _cancelable = false;
- _target: any;
- _currentTarget: any;
- _defaultPrevented: boolean = false;
- _eventPhase: number = 0;
- _timeStamp: number = 0;
- _type: string;
-
- constructor(typeArg: string, target: any) {
- this._type = typeArg;
- this._target = target;
- }
-
- get eventPhase() {
- return this._eventPhase;
- }
-
- get returnValue() {
- return this.defaultPrevented;
- }
-
- set returnValue(v: boolean) {
- if (v) {
- this.preventDefault();
- }
- }
-
- get isTrusted() {
- return false;
- }
-
- get bubbles() {
- return this._bubbles;
- }
-
- get cancelable() {
- return this._cancelable;
- }
-
- set cancelBubble(v: boolean) {
- if (v) {
- this.stopPropagation();
- }
- }
-
- get defaultPrevented() {
- return this._defaultPrevented;
- }
-
- stopPropagation() {
- throw Error("not implemented");
- }
-
- get currentTarget() {
- return this._currentTarget;
- }
-
- get target() {
- return this._target;
- }
-
- preventDefault() {
- }
-
- get srcElement() {
- return this.target;
- }
-
- get timeStamp() {
- return this._timeStamp;
- }
-
- get type() {
- return this._type;
- }
-
- get scoped() {
- return false;
- }
-
- initEvent(eventTypeArg: string, canBubbleArg: boolean, cancelableArg: boolean) {
- if (this._eventPhase != 0) {
- return;
- }
-
- this._type = eventTypeArg;
- this._bubbles = canBubbleArg;
- this._cancelable = cancelableArg;
- }
-
- stopImmediatePropagation() {
- throw Error("not implemented");
- }
-
- deepPath(): EventTarget[] {
- return [];
- }
-}
-
-
-class VersionChangeEvent extends MyEvent {
- _newVersion: number|null;
- _oldVersion: number;
- constructor(oldVersion: number, newVersion: number|null, target: any) {
- super("VersionChange", target);
- this._oldVersion = oldVersion;
- this._newVersion = newVersion;
- }
-
- get newVersion() {
- return this._newVersion;
- }
-
- get oldVersion() {
- return this._oldVersion;
- }
-}
-
-
-export class MemoryIDBFactory implements IDBFactory {
- data: Databases = {};
-
- currentRequest: MyRequest|undefined;
-
- scheduledRequests: MyRequest[] = [];
-
- private addRequest(r: MyRequest) {
- this.scheduledRequests.push(r);
- if (this.currentRequest) {
- return;
- }
- const runNext = (prevRequest?: MyRequest) => {
- const nextRequest = this.scheduledRequests.shift();
- if (nextRequest) {
- const tx = nextRequest.transaction;
-
- if (tx.state === TransactionState.Running) {
- // Okay, we're continuing with the same transaction
- } else if (tx.state === TransactionState.Created) {
- tx.start();
- } else {
- throw Error();
- }
-
- this.currentRequest = nextRequest;
- this.currentRequest.runner();
- this.currentRequest.done = true;
- this.currentRequest = undefined;
- runNext(nextRequest);
- } else if (prevRequest) {
- // We have no other request scheduled, so
- // auto-commit the transaction that the
- // previous request worked on.
- let lastTx = prevRequest._transaction;
- lastTx.commit();
- }
- };
- alreadyResolved.then(() => {
- runNext();
- });
- }
-
- /**
- * Get the only transaction that is active right now
- * or throw if no transaction is active.
- */
- getTransaction() {
- const req = this.currentRequest;
- if (!req) {
- throw Error();
- }
- return req.transaction;
- }
-
- cmp(a: any, b: any): number {
- throw Error("not implemented");
- }
-
- deleteDatabase(name: string): IDBOpenDBRequest {
- throw Error("not implemented");
- }
-
- open(dbName: string, version?: number): IDBOpenDBRequest {
- if (version !== undefined && version <= 0) {
- throw Error("invalid version");
- }
-
- 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");
- }
- } else {
- mydb = {
- name: dbName,
- stores: {},
- 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(oldVersion, mydb.version, db);
- req.callOnupgradeneeded(versionChangeEvt);
- }
- let successEvent = new MyEvent("success", db);
- req.callSuccess(successEvent);
- });
-
- this.addRequest(req);
-
- return req;
- }
-}
-
-/**
- * Inject our IndexedDb implementation in the global namespace,
- * potentially replacing an existing implementation.
- */
-export function injectGlobals() {
-}