add more tests and fix various issues
This commit is contained in:
parent
d1f00aeaa2
commit
db59275b6b
@ -23,7 +23,7 @@ import {
|
|||||||
BridgeIDBRequest,
|
BridgeIDBRequest,
|
||||||
BridgeIDBTransaction,
|
BridgeIDBTransaction,
|
||||||
} from "./bridge-idb";
|
} from "./bridge-idb";
|
||||||
import MemoryBackend from "./MemoryBackend";
|
import { MemoryBackend } from "./MemoryBackend";
|
||||||
|
|
||||||
function promiseFromRequest(request: BridgeIDBRequest): Promise<any> {
|
function promiseFromRequest(request: BridgeIDBRequest): Promise<any> {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
|
@ -29,7 +29,6 @@ import {
|
|||||||
} from "./backend-interface";
|
} from "./backend-interface";
|
||||||
import {
|
import {
|
||||||
structuredClone,
|
structuredClone,
|
||||||
structuredEncapsulate,
|
|
||||||
structuredRevive,
|
structuredRevive,
|
||||||
} from "./util/structuredClone";
|
} from "./util/structuredClone";
|
||||||
import {
|
import {
|
||||||
@ -39,12 +38,11 @@ import {
|
|||||||
DataError,
|
DataError,
|
||||||
} from "./util/errors";
|
} from "./util/errors";
|
||||||
import BTree, { ISortedMapF } from "./tree/b+tree";
|
import BTree, { ISortedMapF } from "./tree/b+tree";
|
||||||
import compareKeys from "./util/cmp";
|
import { compareKeys } from "./util/cmp";
|
||||||
import { StoreKeyResult, makeStoreKeyValue } from "./util/makeStoreKeyValue";
|
import { StoreKeyResult, makeStoreKeyValue } from "./util/makeStoreKeyValue";
|
||||||
import getIndexKeys from "./util/getIndexKeys";
|
import { getIndexKeys } from "./util/getIndexKeys";
|
||||||
import openPromise from "./util/openPromise";
|
import { openPromise } from "./util/openPromise";
|
||||||
import {
|
import {
|
||||||
IDBKeyPath,
|
|
||||||
IDBKeyRange,
|
IDBKeyRange,
|
||||||
IDBTransactionMode,
|
IDBTransactionMode,
|
||||||
IDBValidKey,
|
IDBValidKey,
|
||||||
@ -1440,7 +1438,7 @@ export class MemoryBackend implements Backend {
|
|||||||
const hasKey = modifiedData.has(key);
|
const hasKey = modifiedData.has(key);
|
||||||
|
|
||||||
if (hasKey && storeReq.storeLevel !== StoreLevel.AllowOverwrite) {
|
if (hasKey && storeReq.storeLevel !== StoreLevel.AllowOverwrite) {
|
||||||
throw Error("refusing to overwrite");
|
throw new ConstraintError("refusing to overwrite");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1537,7 +1535,7 @@ export class MemoryBackend implements Backend {
|
|||||||
}
|
}
|
||||||
const myConn = this.connectionsByTransaction[btx.transactionCookie];
|
const myConn = this.connectionsByTransaction[btx.transactionCookie];
|
||||||
if (!myConn) {
|
if (!myConn) {
|
||||||
throw Error("unknown connection");
|
throw Error("unknown transaction");
|
||||||
}
|
}
|
||||||
const db = this.databases[myConn.dbName];
|
const db = this.databases[myConn.dbName];
|
||||||
if (!db) {
|
if (!db) {
|
||||||
@ -1626,5 +1624,3 @@ export class MemoryBackend implements Backend {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default MemoryBackend;
|
|
||||||
|
@ -42,8 +42,8 @@ import {
|
|||||||
IDBTransactionMode,
|
IDBTransactionMode,
|
||||||
IDBValidKey,
|
IDBValidKey,
|
||||||
} from "./idbtypes";
|
} from "./idbtypes";
|
||||||
import compareKeys from "./util/cmp";
|
import { compareKeys } from "./util/cmp";
|
||||||
import enforceRange from "./util/enforceRange";
|
import { enforceRange } from "./util/enforceRange";
|
||||||
import {
|
import {
|
||||||
AbortError,
|
AbortError,
|
||||||
ConstraintError,
|
ConstraintError,
|
||||||
@ -59,15 +59,15 @@ import { fakeDOMStringList } from "./util/fakeDOMStringList";
|
|||||||
import FakeEvent from "./util/FakeEvent";
|
import FakeEvent from "./util/FakeEvent";
|
||||||
import FakeEventTarget from "./util/FakeEventTarget";
|
import FakeEventTarget from "./util/FakeEventTarget";
|
||||||
import { normalizeKeyPath } from "./util/normalizeKeyPath";
|
import { normalizeKeyPath } from "./util/normalizeKeyPath";
|
||||||
import openPromise from "./util/openPromise";
|
import { openPromise } from "./util/openPromise";
|
||||||
import queueTask from "./util/queueTask";
|
import queueTask from "./util/queueTask";
|
||||||
import {
|
import {
|
||||||
structuredClone,
|
structuredClone,
|
||||||
structuredEncapsulate,
|
structuredEncapsulate,
|
||||||
structuredRevive,
|
structuredRevive,
|
||||||
} from "./util/structuredClone";
|
} from "./util/structuredClone";
|
||||||
import validateKeyPath from "./util/validateKeyPath";
|
import { validateKeyPath } from "./util/validateKeyPath";
|
||||||
import valueToKey from "./util/valueToKey";
|
import { valueToKey } from "./util/valueToKey";
|
||||||
|
|
||||||
/** @public */
|
/** @public */
|
||||||
export type CursorSource = BridgeIDBIndex | BridgeIDBObjectStore;
|
export type CursorSource = BridgeIDBIndex | BridgeIDBObjectStore;
|
||||||
|
@ -0,0 +1,270 @@
|
|||||||
|
import test from "ava";
|
||||||
|
import { IDBDatabase } from "../idbtypes";
|
||||||
|
import { createdb } from "./wptsupport";
|
||||||
|
|
||||||
|
// IDBObjectStore.add() - add with an inline key
|
||||||
|
test("WPT idbobjectstore_add.htm", async (t) => {
|
||||||
|
await new Promise<void>((resolve, reject) => {
|
||||||
|
var db: IDBDatabase | undefined;
|
||||||
|
const record = { key: 1, property: "data" };
|
||||||
|
|
||||||
|
var open_rq = createdb(t);
|
||||||
|
open_rq.onupgradeneeded = function (e: any) {
|
||||||
|
db = e.target.result;
|
||||||
|
var objStore = db!.createObjectStore("store", { keyPath: "key" });
|
||||||
|
|
||||||
|
objStore.add(record);
|
||||||
|
};
|
||||||
|
|
||||||
|
open_rq.onsuccess = function (e) {
|
||||||
|
var rq = db!.transaction("store").objectStore("store").get(record.key);
|
||||||
|
|
||||||
|
rq.onsuccess = function (e: any) {
|
||||||
|
t.deepEqual(e.target.result.property, record.property);
|
||||||
|
t.deepEqual(e.target.result.key, record.key);
|
||||||
|
resolve();
|
||||||
|
};
|
||||||
|
};
|
||||||
|
});
|
||||||
|
t.pass();
|
||||||
|
});
|
||||||
|
|
||||||
|
// IDBObjectStore.add() - add with an out-of-line key
|
||||||
|
test("WPT idbobjectstore_add2.htm", async (t) => {
|
||||||
|
await new Promise<void>((resolve, reject) => {
|
||||||
|
var db: any;
|
||||||
|
const key = 1;
|
||||||
|
const record = { property: "data" };
|
||||||
|
|
||||||
|
var open_rq = createdb(t);
|
||||||
|
open_rq.onupgradeneeded = function (e: any) {
|
||||||
|
db = e.target.result;
|
||||||
|
var objStore = db.createObjectStore("store");
|
||||||
|
|
||||||
|
objStore.add(record, key);
|
||||||
|
};
|
||||||
|
|
||||||
|
open_rq.onsuccess = function (e) {
|
||||||
|
var rq = db.transaction("store").objectStore("store").get(key);
|
||||||
|
|
||||||
|
rq.onsuccess = function (e: any) {
|
||||||
|
t.deepEqual(e.target.result.property, record.property);
|
||||||
|
resolve();
|
||||||
|
};
|
||||||
|
};
|
||||||
|
});
|
||||||
|
t.pass();
|
||||||
|
});
|
||||||
|
|
||||||
|
// IDBObjectStore.add() - record with same key already exists
|
||||||
|
test("WPT idbobjectstore_add3.htm", async (t) => {
|
||||||
|
await new Promise<void>((resolve, reject) => {
|
||||||
|
var db: any;
|
||||||
|
const record = { key: 1, property: "data" };
|
||||||
|
|
||||||
|
var open_rq = createdb(t);
|
||||||
|
open_rq.onupgradeneeded = function (e: any) {
|
||||||
|
db = e.target.result;
|
||||||
|
var objStore = db.createObjectStore("store", { keyPath: "key" });
|
||||||
|
objStore.add(record);
|
||||||
|
|
||||||
|
var rq = objStore.add(record);
|
||||||
|
rq.onsuccess = () => t.fail("success on adding duplicate record");
|
||||||
|
|
||||||
|
rq.onerror = function (e: any) {
|
||||||
|
t.deepEqual(e.target.error.name, "ConstraintError");
|
||||||
|
t.deepEqual(rq.error.name, "ConstraintError");
|
||||||
|
t.deepEqual(e.type, "error");
|
||||||
|
e.preventDefault();
|
||||||
|
e.stopPropagation();
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
// Defer done, giving rq.onsuccess a chance to run
|
||||||
|
open_rq.onsuccess = function (e) {
|
||||||
|
resolve();
|
||||||
|
};
|
||||||
|
});
|
||||||
|
t.pass();
|
||||||
|
});
|
||||||
|
|
||||||
|
// IDBObjectStore.add() - add where an index has unique:true specified
|
||||||
|
test("WPT idbobjectstore_add4.htm", async (t) => {
|
||||||
|
await new Promise<void>((resolve, reject) => {
|
||||||
|
let db: any;
|
||||||
|
let record = { key: 1, property: "data" };
|
||||||
|
|
||||||
|
var open_rq = createdb(t);
|
||||||
|
open_rq.onupgradeneeded = function (e: any) {
|
||||||
|
db = e.target.result;
|
||||||
|
var objStore = db.createObjectStore("store", { autoIncrement: true });
|
||||||
|
objStore.createIndex("i1", "property", { unique: true });
|
||||||
|
objStore.add(record);
|
||||||
|
|
||||||
|
var rq = objStore.add(record);
|
||||||
|
rq.onsuccess = () => t.fail("success on adding duplicate indexed record");
|
||||||
|
|
||||||
|
rq.onerror = function (e: any) {
|
||||||
|
t.deepEqual(rq.error.name, "ConstraintError");
|
||||||
|
t.deepEqual(e.target.error.name, "ConstraintError");
|
||||||
|
t.deepEqual(e.type, "error");
|
||||||
|
e.preventDefault();
|
||||||
|
e.stopPropagation();
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
// Defer done, giving a spurious rq.onsuccess a chance to run
|
||||||
|
open_rq.onsuccess = function (e) {
|
||||||
|
resolve();
|
||||||
|
};
|
||||||
|
});
|
||||||
|
t.pass();
|
||||||
|
});
|
||||||
|
|
||||||
|
// IDBObjectStore.add() - object store's key path is an object attribute
|
||||||
|
test("WPT idbobjectstore_add5.htm", async (t) => {
|
||||||
|
await new Promise<void>((resolve, reject) => {
|
||||||
|
var db: any;
|
||||||
|
const record = { test: { obj: { key: 1 } }, property: "data" };
|
||||||
|
|
||||||
|
var open_rq = createdb(t);
|
||||||
|
open_rq.onupgradeneeded = function (e: any) {
|
||||||
|
db = e.target.result;
|
||||||
|
var objStore = db.createObjectStore("store", { keyPath: "test.obj.key" });
|
||||||
|
objStore.add(record);
|
||||||
|
};
|
||||||
|
|
||||||
|
open_rq.onsuccess = function (e: any) {
|
||||||
|
var rq = db
|
||||||
|
.transaction("store")
|
||||||
|
.objectStore("store")
|
||||||
|
.get(record.test.obj.key);
|
||||||
|
|
||||||
|
rq.onsuccess = function (e: any) {
|
||||||
|
t.deepEqual(e.target.result.property, record.property);
|
||||||
|
resolve();
|
||||||
|
};
|
||||||
|
};
|
||||||
|
});
|
||||||
|
t.pass();
|
||||||
|
});
|
||||||
|
|
||||||
|
// IDBObjectStore.add() - autoIncrement and inline keys
|
||||||
|
test("WPT idbobjectstore_add6.htm", async (t) => {
|
||||||
|
await new Promise<void>((resolve, reject) => {
|
||||||
|
var db: any;
|
||||||
|
const record = { property: "data" };
|
||||||
|
const expected_keys = [1, 2, 3, 4];
|
||||||
|
|
||||||
|
var open_rq = createdb(t);
|
||||||
|
open_rq.onupgradeneeded = function (e: any) {
|
||||||
|
db = e.target.result;
|
||||||
|
var objStore = db.createObjectStore("store", {
|
||||||
|
keyPath: "key",
|
||||||
|
autoIncrement: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
objStore.add(record);
|
||||||
|
objStore.add(record);
|
||||||
|
objStore.add(record);
|
||||||
|
objStore.add(record);
|
||||||
|
};
|
||||||
|
|
||||||
|
open_rq.onsuccess = function (e) {
|
||||||
|
var actual_keys: any[] = [],
|
||||||
|
rq = db.transaction("store").objectStore("store").openCursor();
|
||||||
|
|
||||||
|
rq.onsuccess = function (e: any) {
|
||||||
|
var cursor = e.target.result;
|
||||||
|
|
||||||
|
if (cursor) {
|
||||||
|
actual_keys.push(cursor.value.key);
|
||||||
|
cursor.continue();
|
||||||
|
} else {
|
||||||
|
t.deepEqual(actual_keys, expected_keys);
|
||||||
|
resolve();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
});
|
||||||
|
t.pass();
|
||||||
|
});
|
||||||
|
|
||||||
|
// IDBObjectStore.add() - autoIncrement and out-of-line keys
|
||||||
|
test("WPT idbobjectstore_add7.htm", async (t) => {
|
||||||
|
await new Promise<void>((resolve, reject) => {
|
||||||
|
var db: any;
|
||||||
|
const record = { property: "data" };
|
||||||
|
const expected_keys = [1, 2, 3, 4];
|
||||||
|
|
||||||
|
var open_rq = createdb(t);
|
||||||
|
open_rq.onupgradeneeded = function (e: any) {
|
||||||
|
db = e.target.result;
|
||||||
|
var objStore = db.createObjectStore("store", { autoIncrement: true });
|
||||||
|
|
||||||
|
objStore.add(record);
|
||||||
|
objStore.add(record);
|
||||||
|
objStore.add(record);
|
||||||
|
objStore.add(record);
|
||||||
|
};
|
||||||
|
|
||||||
|
open_rq.onsuccess = function (e) {
|
||||||
|
var actual_keys: any[] = [],
|
||||||
|
rq = db.transaction("store").objectStore("store").openCursor();
|
||||||
|
|
||||||
|
rq.onsuccess = function (e: any) {
|
||||||
|
var cursor = e.target.result;
|
||||||
|
|
||||||
|
if (cursor) {
|
||||||
|
actual_keys.push(cursor.key);
|
||||||
|
cursor.continue();
|
||||||
|
} else {
|
||||||
|
t.deepEqual(actual_keys, expected_keys);
|
||||||
|
resolve();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
});
|
||||||
|
t.pass();
|
||||||
|
});
|
||||||
|
|
||||||
|
// IDBObjectStore.add() - object store has autoIncrement:true and the key path is an object attribute
|
||||||
|
test("WPT idbobjectstore_add8.htm", async (t) => {
|
||||||
|
await new Promise<void>((resolve, reject) => {
|
||||||
|
var db: any;
|
||||||
|
const record = { property: "data" };
|
||||||
|
const expected_keys = [1, 2, 3, 4];
|
||||||
|
|
||||||
|
var open_rq = createdb(t);
|
||||||
|
open_rq.onupgradeneeded = function (e: any) {
|
||||||
|
db = e.target.result;
|
||||||
|
var objStore = db.createObjectStore("store", {
|
||||||
|
keyPath: "test.obj.key",
|
||||||
|
autoIncrement: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
objStore.add(record);
|
||||||
|
objStore.add(record);
|
||||||
|
objStore.add(record);
|
||||||
|
objStore.add(record);
|
||||||
|
};
|
||||||
|
|
||||||
|
open_rq.onsuccess = function (e) {
|
||||||
|
var actual_keys: any[] = [],
|
||||||
|
rq = db.transaction("store").objectStore("store").openCursor();
|
||||||
|
|
||||||
|
rq.onsuccess = function (e: any) {
|
||||||
|
var cursor = e.target.result;
|
||||||
|
|
||||||
|
if (cursor) {
|
||||||
|
actual_keys.push(cursor.value.test.obj.key);
|
||||||
|
cursor.continue();
|
||||||
|
} else {
|
||||||
|
t.deepEqual(actual_keys, expected_keys);
|
||||||
|
resolve();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
});
|
||||||
|
t.pass();
|
||||||
|
});
|
@ -1,8 +1,8 @@
|
|||||||
import { ExecutionContext } from "ava";
|
import { ExecutionContext } from "ava";
|
||||||
import { BridgeIDBFactory } from "..";
|
import { BridgeIDBFactory } from "..";
|
||||||
import { IDBOpenDBRequest } from "../idbtypes";
|
import { IDBOpenDBRequest } from "../idbtypes";
|
||||||
import MemoryBackend from "../MemoryBackend";
|
import { MemoryBackend } from "../MemoryBackend";
|
||||||
import compareKeys from "../util/cmp";
|
import { compareKeys } from "../util/cmp";
|
||||||
|
|
||||||
BridgeIDBFactory.enableTracing = true;
|
BridgeIDBFactory.enableTracing = true;
|
||||||
const idbFactory = new BridgeIDBFactory(new MemoryBackend());
|
const idbFactory = new BridgeIDBFactory(new MemoryBackend());
|
||||||
|
@ -15,7 +15,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { DataError } from "./errors";
|
import { DataError } from "./errors";
|
||||||
import valueToKey from "./valueToKey";
|
import { valueToKey } from "./valueToKey";
|
||||||
|
|
||||||
const getType = (x: any) => {
|
const getType = (x: any) => {
|
||||||
if (typeof x === "number") {
|
if (typeof x === "number") {
|
||||||
@ -38,7 +38,7 @@ const getType = (x: any) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// https://w3c.github.io/IndexedDB/#compare-two-keys
|
// https://w3c.github.io/IndexedDB/#compare-two-keys
|
||||||
const compareKeys = (first: any, second: any): -1 | 0 | 1 => {
|
export const compareKeys = (first: any, second: any): -1 | 0 | 1 => {
|
||||||
if (second === undefined) {
|
if (second === undefined) {
|
||||||
throw new TypeError();
|
throw new TypeError();
|
||||||
}
|
}
|
||||||
@ -104,5 +104,3 @@ const compareKeys = (first: any, second: any): -1 | 0 | 1 => {
|
|||||||
|
|
||||||
return first > second ? 1 : -1;
|
return first > second ? 1 : -1;
|
||||||
};
|
};
|
||||||
|
|
||||||
export default compareKeys;
|
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
|
|
||||||
// https://heycam.github.io/webidl/#EnforceRange
|
// https://heycam.github.io/webidl/#EnforceRange
|
||||||
|
|
||||||
const enforceRange = (
|
export const enforceRange = (
|
||||||
num: number,
|
num: number,
|
||||||
type: "MAX_SAFE_INTEGER" | "unsigned long",
|
type: "MAX_SAFE_INTEGER" | "unsigned long",
|
||||||
) => {
|
) => {
|
||||||
@ -31,5 +31,3 @@ const enforceRange = (
|
|||||||
return Math.floor(num);
|
return Math.floor(num);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export default enforceRange;
|
|
||||||
|
@ -16,10 +16,10 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { IDBKeyPath, IDBValidKey } from "../idbtypes";
|
import { IDBKeyPath, IDBValidKey } from "../idbtypes";
|
||||||
import valueToKey from "./valueToKey";
|
import { valueToKey } from "./valueToKey";
|
||||||
|
|
||||||
// http://www.w3.org/TR/2015/REC-IndexedDB-20150108/#dfn-steps-for-extracting-a-key-from-a-value-using-a-key-path
|
// http://www.w3.org/TR/2015/REC-IndexedDB-20150108/#dfn-steps-for-extracting-a-key-from-a-value-using-a-key-path
|
||||||
const extractKey = (keyPath: IDBKeyPath | IDBKeyPath[], value: any) => {
|
export const extractKey = (keyPath: IDBKeyPath | IDBKeyPath[], value: any) => {
|
||||||
if (Array.isArray(keyPath)) {
|
if (Array.isArray(keyPath)) {
|
||||||
const result: IDBValidKey[] = [];
|
const result: IDBValidKey[] = [];
|
||||||
|
|
||||||
@ -68,5 +68,3 @@ const extractKey = (keyPath: IDBKeyPath | IDBKeyPath[], value: any) => {
|
|||||||
|
|
||||||
return object;
|
return object;
|
||||||
};
|
};
|
||||||
|
|
||||||
export default extractKey;
|
|
||||||
|
@ -16,8 +16,8 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { IDBKeyPath, IDBValidKey } from "../idbtypes";
|
import { IDBKeyPath, IDBValidKey } from "../idbtypes";
|
||||||
import extractKey from "./extractKey";
|
import { extractKey } from "./extractKey";
|
||||||
import valueToKey from "./valueToKey";
|
import { valueToKey } from "./valueToKey";
|
||||||
|
|
||||||
export function getIndexKeys(
|
export function getIndexKeys(
|
||||||
value: any,
|
value: any,
|
||||||
@ -43,5 +43,3 @@ export function getIndexKeys(
|
|||||||
throw Error(`unsupported key path: ${typeof keyPath}`);
|
throw Error(`unsupported key path: ${typeof keyPath}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default getIndexKeys;
|
|
||||||
|
@ -30,6 +30,11 @@ export function injectKey(
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const newValue = structuredClone(value);
|
||||||
|
|
||||||
|
// Position inside the new value where we'll place the key eventually.
|
||||||
|
let ptr = newValue;
|
||||||
|
|
||||||
const identifiers = keyPath.split(".");
|
const identifiers = keyPath.split(".");
|
||||||
if (identifiers.length === 0) {
|
if (identifiers.length === 0) {
|
||||||
throw new Error("Assert: identifiers is not empty");
|
throw new Error("Assert: identifiers is not empty");
|
||||||
@ -42,26 +47,23 @@ export function injectKey(
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (const identifier of identifiers) {
|
for (const identifier of identifiers) {
|
||||||
if (typeof value !== "object" && !Array.isArray(value)) {
|
if (typeof ptr !== "object" && !Array.isArray(ptr)) {
|
||||||
return false;
|
throw new Error("can't inject key");
|
||||||
}
|
}
|
||||||
|
|
||||||
const hop = value.hasOwnProperty(identifier);
|
const hop = value.hasOwnProperty(identifier);
|
||||||
if (!hop) {
|
if (!hop) {
|
||||||
return true;
|
ptr[identifier] = {};
|
||||||
}
|
}
|
||||||
|
|
||||||
value = value[identifier];
|
ptr = ptr[identifier];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(typeof value === "object" || Array.isArray(value))) {
|
if (!(typeof ptr === "object" || Array.isArray(ptr))) {
|
||||||
throw new Error("can't inject key");
|
throw new Error("can't inject key");
|
||||||
}
|
}
|
||||||
|
|
||||||
const newValue = structuredClone(value);
|
ptr[lastIdentifier] = structuredClone(key);
|
||||||
newValue[lastIdentifier] = structuredClone(key);
|
|
||||||
|
|
||||||
return newValue;
|
return newValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default injectKey;
|
|
||||||
|
@ -14,11 +14,11 @@
|
|||||||
permissions and limitations under the License.
|
permissions and limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import extractKey from "./extractKey";
|
import { extractKey } from "./extractKey";
|
||||||
import { DataError } from "./errors";
|
import { DataError } from "./errors";
|
||||||
import valueToKey from "./valueToKey";
|
import { valueToKey } from "./valueToKey";
|
||||||
import { structuredClone } from "./structuredClone";
|
import { structuredClone } from "./structuredClone";
|
||||||
import injectKey from "./injectKey";
|
import { injectKey } from "./injectKey";
|
||||||
import { IDBKeyPath, IDBValidKey } from "../idbtypes";
|
import { IDBKeyPath, IDBValidKey } from "../idbtypes";
|
||||||
|
|
||||||
export interface StoreKeyResult {
|
export interface StoreKeyResult {
|
||||||
|
@ -14,7 +14,7 @@
|
|||||||
permissions and limitations under the License.
|
permissions and limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
function openPromise<T>(): {
|
export function openPromise<T>(): {
|
||||||
promise: Promise<T>;
|
promise: Promise<T>;
|
||||||
resolve: (v?: T | PromiseLike<T>) => void;
|
resolve: (v?: T | PromiseLike<T>) => void;
|
||||||
reject: (err?: any) => void;
|
reject: (err?: any) => void;
|
||||||
@ -34,5 +34,3 @@ function openPromise<T>(): {
|
|||||||
|
|
||||||
return { promise, resolve, reject };
|
return { promise, resolve, reject };
|
||||||
}
|
}
|
||||||
|
|
||||||
export default openPromise;
|
|
||||||
|
@ -17,7 +17,10 @@
|
|||||||
import { IDBKeyPath } from "../idbtypes";
|
import { IDBKeyPath } from "../idbtypes";
|
||||||
|
|
||||||
// http://www.w3.org/TR/2015/REC-IndexedDB-20150108/#dfn-valid-key-path
|
// http://www.w3.org/TR/2015/REC-IndexedDB-20150108/#dfn-valid-key-path
|
||||||
const validateKeyPath = (keyPath: IDBKeyPath | IDBKeyPath[], parent?: "array" | "string") => {
|
export const validateKeyPath = (
|
||||||
|
keyPath: IDBKeyPath | IDBKeyPath[],
|
||||||
|
parent?: "array" | "string",
|
||||||
|
) => {
|
||||||
// This doesn't make sense to me based on the spec, but it is needed to pass the W3C KeyPath tests (see same
|
// This doesn't make sense to me based on the spec, but it is needed to pass the W3C KeyPath tests (see same
|
||||||
// comment in extractKey)
|
// comment in extractKey)
|
||||||
let myKeyPath: IDBKeyPath | IDBKeyPath[] = keyPath;
|
let myKeyPath: IDBKeyPath | IDBKeyPath[] = keyPath;
|
||||||
@ -74,5 +77,3 @@ const validateKeyPath = (keyPath: IDBKeyPath | IDBKeyPath[], parent?: "array" |
|
|||||||
|
|
||||||
throw new SyntaxError();
|
throw new SyntaxError();
|
||||||
};
|
};
|
||||||
|
|
||||||
export default validateKeyPath;
|
|
||||||
|
@ -18,7 +18,7 @@ import { IDBValidKey } from "..";
|
|||||||
import { DataError } from "./errors";
|
import { DataError } from "./errors";
|
||||||
|
|
||||||
// https://w3c.github.io/IndexedDB/#convert-a-value-to-a-input
|
// https://w3c.github.io/IndexedDB/#convert-a-value-to-a-input
|
||||||
function valueToKey(
|
export function valueToKey(
|
||||||
input: any,
|
input: any,
|
||||||
seen?: Set<object>,
|
seen?: Set<object>,
|
||||||
): IDBValidKey | IDBValidKey[] {
|
): IDBValidKey | IDBValidKey[] {
|
||||||
@ -68,5 +68,3 @@ function valueToKey(
|
|||||||
throw new DataError();
|
throw new DataError();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default valueToKey;
|
|
||||||
|
Loading…
Reference in New Issue
Block a user