next batch of test cases and fixes
This commit is contained in:
parent
db59275b6b
commit
987f22de02
@ -27,10 +27,7 @@ import {
|
|||||||
StoreLevel,
|
StoreLevel,
|
||||||
RecordStoreResponse,
|
RecordStoreResponse,
|
||||||
} from "./backend-interface";
|
} from "./backend-interface";
|
||||||
import {
|
import { structuredClone, structuredRevive } from "./util/structuredClone";
|
||||||
structuredClone,
|
|
||||||
structuredRevive,
|
|
||||||
} from "./util/structuredClone";
|
|
||||||
import {
|
import {
|
||||||
InvalidStateError,
|
InvalidStateError,
|
||||||
InvalidAccessError,
|
InvalidAccessError,
|
||||||
@ -42,11 +39,7 @@ 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 { IDBKeyRange, IDBTransactionMode, IDBValidKey } from "./idbtypes";
|
||||||
IDBKeyRange,
|
|
||||||
IDBTransactionMode,
|
|
||||||
IDBValidKey,
|
|
||||||
} from "./idbtypes";
|
|
||||||
import { BridgeIDBKeyRange } from "./bridge-idb";
|
import { BridgeIDBKeyRange } from "./bridge-idb";
|
||||||
|
|
||||||
type Key = IDBValidKey;
|
type Key = IDBValidKey;
|
||||||
@ -488,10 +481,10 @@ export class MemoryBackend implements Backend {
|
|||||||
objectStores: string[],
|
objectStores: string[],
|
||||||
mode: IDBTransactionMode,
|
mode: IDBTransactionMode,
|
||||||
): Promise<DatabaseTransaction> {
|
): Promise<DatabaseTransaction> {
|
||||||
if (this.enableTracing) {
|
|
||||||
console.log(`TRACING: beginTransaction`);
|
|
||||||
}
|
|
||||||
const transactionCookie = `tx-${this.transactionIdCounter++}`;
|
const transactionCookie = `tx-${this.transactionIdCounter++}`;
|
||||||
|
if (this.enableTracing) {
|
||||||
|
console.log(`TRACING: beginTransaction ${transactionCookie}`);
|
||||||
|
}
|
||||||
const myConn = this.connections[conn.connectionCookie];
|
const myConn = this.connections[conn.connectionCookie];
|
||||||
if (!myConn) {
|
if (!myConn) {
|
||||||
throw Error("connection not found");
|
throw Error("connection not found");
|
||||||
@ -556,7 +549,7 @@ export class MemoryBackend implements Backend {
|
|||||||
|
|
||||||
async close(conn: DatabaseConnection): Promise<void> {
|
async close(conn: DatabaseConnection): Promise<void> {
|
||||||
if (this.enableTracing) {
|
if (this.enableTracing) {
|
||||||
console.log(`TRACING: close`);
|
console.log(`TRACING: close (${conn.connectionCookie})`);
|
||||||
}
|
}
|
||||||
const myConn = this.connections[conn.connectionCookie];
|
const myConn = this.connections[conn.connectionCookie];
|
||||||
if (!myConn) {
|
if (!myConn) {
|
||||||
@ -640,7 +633,7 @@ export class MemoryBackend implements Backend {
|
|||||||
if (this.enableTracing) {
|
if (this.enableTracing) {
|
||||||
console.log(`TRACING: deleteIndex(${indexName})`);
|
console.log(`TRACING: deleteIndex(${indexName})`);
|
||||||
}
|
}
|
||||||
const myConn = this.connections[btx.transactionCookie];
|
const myConn = this.connectionsByTransaction[btx.transactionCookie];
|
||||||
if (!myConn) {
|
if (!myConn) {
|
||||||
throw Error("unknown connection");
|
throw Error("unknown connection");
|
||||||
}
|
}
|
||||||
@ -670,9 +663,11 @@ export class MemoryBackend implements Backend {
|
|||||||
|
|
||||||
deleteObjectStore(btx: DatabaseTransaction, name: string): void {
|
deleteObjectStore(btx: DatabaseTransaction, name: string): void {
|
||||||
if (this.enableTracing) {
|
if (this.enableTracing) {
|
||||||
console.log(`TRACING: deleteObjectStore(${name})`);
|
console.log(
|
||||||
|
`TRACING: deleteObjectStore(${name}) in ${btx.transactionCookie}`,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
const myConn = this.connections[btx.transactionCookie];
|
const myConn = this.connectionsByTransaction[btx.transactionCookie];
|
||||||
if (!myConn) {
|
if (!myConn) {
|
||||||
throw Error("unknown connection");
|
throw Error("unknown connection");
|
||||||
}
|
}
|
||||||
@ -714,7 +709,7 @@ export class MemoryBackend implements Backend {
|
|||||||
console.log(`TRACING: renameObjectStore(?, ${oldName}, ${newName})`);
|
console.log(`TRACING: renameObjectStore(?, ${oldName}, ${newName})`);
|
||||||
}
|
}
|
||||||
|
|
||||||
const myConn = this.connections[btx.transactionCookie];
|
const myConn = this.connectionsByTransaction[btx.transactionCookie];
|
||||||
if (!myConn) {
|
if (!myConn) {
|
||||||
throw Error("unknown connection");
|
throw Error("unknown connection");
|
||||||
}
|
}
|
||||||
@ -846,7 +841,15 @@ export class MemoryBackend implements Backend {
|
|||||||
objectStoreMapEntry.store.originalData;
|
objectStoreMapEntry.store.originalData;
|
||||||
|
|
||||||
storeData.forEach((v, k) => {
|
storeData.forEach((v, k) => {
|
||||||
this.insertIntoIndex(newIndex, k, v.value, indexProperties);
|
try {
|
||||||
|
this.insertIntoIndex(newIndex, k, v.value, indexProperties);
|
||||||
|
} catch (e) {
|
||||||
|
if (e instanceof DataError) {
|
||||||
|
// We don't propagate this error here.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1404,6 +1407,16 @@ export class MemoryBackend implements Backend {
|
|||||||
const autoIncrement =
|
const autoIncrement =
|
||||||
schema.objectStores[storeReq.objectStoreName].autoIncrement;
|
schema.objectStores[storeReq.objectStoreName].autoIncrement;
|
||||||
const keyPath = schema.objectStores[storeReq.objectStoreName].keyPath;
|
const keyPath = schema.objectStores[storeReq.objectStoreName].keyPath;
|
||||||
|
|
||||||
|
if (
|
||||||
|
keyPath !== null &&
|
||||||
|
keyPath !== undefined &&
|
||||||
|
storeReq.key !== undefined
|
||||||
|
) {
|
||||||
|
// If in-line keys are used, a key can't be explicitly specified.
|
||||||
|
throw new DataError();
|
||||||
|
}
|
||||||
|
|
||||||
let storeKeyResult: StoreKeyResult;
|
let storeKeyResult: StoreKeyResult;
|
||||||
const revivedValue = structuredRevive(storeReq.value);
|
const revivedValue = structuredRevive(storeReq.value);
|
||||||
try {
|
try {
|
||||||
@ -1463,7 +1476,16 @@ export class MemoryBackend implements Backend {
|
|||||||
}
|
}
|
||||||
const indexProperties =
|
const indexProperties =
|
||||||
schema.objectStores[storeReq.objectStoreName].indexes[indexName];
|
schema.objectStores[storeReq.objectStoreName].indexes[indexName];
|
||||||
this.insertIntoIndex(index, key, value, indexProperties);
|
try {
|
||||||
|
this.insertIntoIndex(index, key, value, indexProperties);
|
||||||
|
} catch (e) {
|
||||||
|
if (e instanceof DataError) {
|
||||||
|
// https://www.w3.org/TR/IndexedDB-2/#object-store-storage-operation
|
||||||
|
// Do nothing
|
||||||
|
} else {
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return { key };
|
return { key };
|
||||||
|
@ -58,6 +58,7 @@ import {
|
|||||||
import { fakeDOMStringList } from "./util/fakeDOMStringList";
|
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 { makeStoreKeyValue } from "./util/makeStoreKeyValue";
|
||||||
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";
|
||||||
@ -605,7 +606,17 @@ export class BridgeIDBDatabase extends FakeEventTarget implements IDBDatabase {
|
|||||||
throw new TypeError();
|
throw new TypeError();
|
||||||
}
|
}
|
||||||
const transaction = confirmActiveVersionchangeTransaction(this);
|
const transaction = confirmActiveVersionchangeTransaction(this);
|
||||||
transaction._objectStoresCache.delete(name);
|
const backendTx = transaction._backendTransaction;
|
||||||
|
if (!backendTx) {
|
||||||
|
throw Error("invariant violated");
|
||||||
|
}
|
||||||
|
this._backend.deleteObjectStore(backendTx, name);
|
||||||
|
const os = transaction._objectStoresCache.get(name);
|
||||||
|
if (os) {
|
||||||
|
os._deleted = true;
|
||||||
|
transaction._objectStoresCache.delete(name);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public _internalTransaction(
|
public _internalTransaction(
|
||||||
@ -866,7 +877,9 @@ export class BridgeIDBFactory {
|
|||||||
event2.eventPath = [request];
|
event2.eventPath = [request];
|
||||||
request.dispatchEvent(event2);
|
request.dispatchEvent(event2);
|
||||||
} else {
|
} else {
|
||||||
console.log(`dispatching success event, _active=${transaction._active}`);
|
console.log(
|
||||||
|
`dispatching success event, _active=${transaction._active}`,
|
||||||
|
);
|
||||||
const event2 = new FakeEvent("success", {
|
const event2 = new FakeEvent("success", {
|
||||||
bubbles: false,
|
bubbles: false,
|
||||||
cancelable: false,
|
cancelable: false,
|
||||||
@ -1064,8 +1077,23 @@ export class BridgeIDBIndex implements IDBIndex {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public get(key: BridgeIDBKeyRange | IDBValidKey) {
|
|
||||||
|
private _confirmIndexExists() {
|
||||||
|
const storeSchema = this._schema.objectStores[this._objectStore._name];
|
||||||
|
if (!storeSchema) {
|
||||||
|
throw new InvalidStateError();
|
||||||
|
}
|
||||||
|
if (!storeSchema.indexes[this._name]) {
|
||||||
|
throw new InvalidStateError();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
get(key: BridgeIDBKeyRange | IDBValidKey) {
|
||||||
confirmActiveTransaction(this);
|
confirmActiveTransaction(this);
|
||||||
|
this._confirmIndexExists();
|
||||||
|
if (this._deleted) {
|
||||||
|
throw new InvalidStateError();
|
||||||
|
}
|
||||||
|
|
||||||
if (!(key instanceof BridgeIDBKeyRange)) {
|
if (!(key instanceof BridgeIDBKeyRange)) {
|
||||||
key = BridgeIDBKeyRange._valueToKeyRange(key);
|
key = BridgeIDBKeyRange._valueToKeyRange(key);
|
||||||
@ -1384,6 +1412,7 @@ export class BridgeIDBObjectStore implements IDBObjectStore {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
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`);
|
||||||
@ -1391,6 +1420,22 @@ export class BridgeIDBObjectStore implements IDBObjectStore {
|
|||||||
if (this._transaction.mode === "readonly") {
|
if (this._transaction.mode === "readonly") {
|
||||||
throw new ReadOnlyError();
|
throw new ReadOnlyError();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const { keyPath, autoIncrement } = this._schema.objectStores[this._name];
|
||||||
|
|
||||||
|
if (key !== null && key !== undefined) {
|
||||||
|
valueToKey(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
// We only call this to synchronously verify the request.
|
||||||
|
makeStoreKeyValue(
|
||||||
|
value,
|
||||||
|
key,
|
||||||
|
1,
|
||||||
|
autoIncrement,
|
||||||
|
keyPath,
|
||||||
|
);
|
||||||
|
|
||||||
const operation = async () => {
|
const operation = async () => {
|
||||||
const { btx } = this._confirmActiveTransaction();
|
const { btx } = this._confirmActiveTransaction();
|
||||||
const result = await this._backend.storeRecord(btx, {
|
const result = await this._backend.storeRecord(btx, {
|
||||||
@ -1411,6 +1456,9 @@ export class BridgeIDBObjectStore implements IDBObjectStore {
|
|||||||
if (arguments.length === 0) {
|
if (arguments.length === 0) {
|
||||||
throw new TypeError();
|
throw new TypeError();
|
||||||
}
|
}
|
||||||
|
if (this._deleted) {
|
||||||
|
throw new InvalidStateError("tried to call 'put' on a deleted object store");
|
||||||
|
}
|
||||||
return this._store(value, key, true);
|
return this._store(value, key, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1418,6 +1466,9 @@ export class BridgeIDBObjectStore implements IDBObjectStore {
|
|||||||
if (arguments.length === 0) {
|
if (arguments.length === 0) {
|
||||||
throw new TypeError();
|
throw new TypeError();
|
||||||
}
|
}
|
||||||
|
if (!this._schema.objectStores[this._name]) {
|
||||||
|
throw new InvalidStateError("object store does not exist");
|
||||||
|
}
|
||||||
return this._store(value, key, false);
|
return this._store(value, key, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1425,7 +1476,9 @@ export class BridgeIDBObjectStore implements IDBObjectStore {
|
|||||||
if (arguments.length === 0) {
|
if (arguments.length === 0) {
|
||||||
throw new TypeError();
|
throw new TypeError();
|
||||||
}
|
}
|
||||||
|
if (this._deleted) {
|
||||||
|
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();
|
||||||
}
|
}
|
||||||
@ -1458,6 +1511,10 @@ export class BridgeIDBObjectStore implements IDBObjectStore {
|
|||||||
throw new TypeError();
|
throw new TypeError();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (this._deleted) {
|
||||||
|
throw new InvalidStateError("tried to call 'delete' on a deleted object store");
|
||||||
|
}
|
||||||
|
|
||||||
let keyRange: BridgeIDBKeyRange;
|
let keyRange: BridgeIDBKeyRange;
|
||||||
|
|
||||||
if (key instanceof BridgeIDBKeyRange) {
|
if (key instanceof BridgeIDBKeyRange) {
|
||||||
@ -1541,6 +1598,9 @@ export class BridgeIDBObjectStore implements IDBObjectStore {
|
|||||||
range?: IDBKeyRange | IDBValidKey,
|
range?: IDBKeyRange | IDBValidKey,
|
||||||
direction: IDBCursorDirection = "next",
|
direction: IDBCursorDirection = "next",
|
||||||
) {
|
) {
|
||||||
|
if (this._deleted) {
|
||||||
|
throw new InvalidStateError("tried to call 'openCursor' on a deleted object store");
|
||||||
|
}
|
||||||
if (range === null) {
|
if (range === null) {
|
||||||
range = undefined;
|
range = undefined;
|
||||||
}
|
}
|
||||||
@ -1572,6 +1632,9 @@ export class BridgeIDBObjectStore implements IDBObjectStore {
|
|||||||
range?: BridgeIDBKeyRange | IDBValidKey,
|
range?: BridgeIDBKeyRange | IDBValidKey,
|
||||||
direction?: IDBCursorDirection,
|
direction?: IDBCursorDirection,
|
||||||
) {
|
) {
|
||||||
|
if (this._deleted) {
|
||||||
|
throw new InvalidStateError("tried to call 'openKeyCursor' on a deleted object store");
|
||||||
|
}
|
||||||
if (range === null) {
|
if (range === null) {
|
||||||
range = undefined;
|
range = undefined;
|
||||||
}
|
}
|
||||||
@ -2091,7 +2154,9 @@ export class BridgeIDBTransaction
|
|||||||
request.dispatchEvent(event);
|
request.dispatchEvent(event);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
if (BridgeIDBFactory.enableTracing) {
|
if (BridgeIDBFactory.enableTracing) {
|
||||||
console.log("TRACING: caught error in transaction success event handler");
|
console.log(
|
||||||
|
"TRACING: caught error in transaction success event handler",
|
||||||
|
);
|
||||||
}
|
}
|
||||||
this._abort("AbortError");
|
this._abort("AbortError");
|
||||||
this._active = false;
|
this._active = false;
|
||||||
|
177
packages/idb-bridge/src/idb-wpt-ported/idbindex_get.test.ts
Normal file
177
packages/idb-bridge/src/idb-wpt-ported/idbindex_get.test.ts
Normal file
@ -0,0 +1,177 @@
|
|||||||
|
import test from "ava";
|
||||||
|
import { BridgeIDBKeyRange, BridgeIDBRequest } from "..";
|
||||||
|
import { IDBDatabase } from "../idbtypes";
|
||||||
|
import { createdb } from "./wptsupport";
|
||||||
|
|
||||||
|
// IDBIndex.get() - returns the record
|
||||||
|
test("WPT idbindex_get.htm", async (t) => {
|
||||||
|
await new Promise<void>((resolve, reject) => {
|
||||||
|
var db: any, index: any;
|
||||||
|
const record = { key: 1, indexedProperty: "data" };
|
||||||
|
|
||||||
|
var open_rq = createdb(t);
|
||||||
|
open_rq.onupgradeneeded = function (e: any) {
|
||||||
|
db = e.target.result;
|
||||||
|
var objStore = db.createObjectStore("store", { keyPath: "key" });
|
||||||
|
index = objStore.createIndex("index", "indexedProperty");
|
||||||
|
|
||||||
|
objStore.add(record);
|
||||||
|
};
|
||||||
|
|
||||||
|
open_rq.onsuccess = function (e) {
|
||||||
|
var rq = db
|
||||||
|
.transaction("store")
|
||||||
|
.objectStore("store")
|
||||||
|
.index("index")
|
||||||
|
.get(record.indexedProperty);
|
||||||
|
|
||||||
|
rq.onsuccess = function (e: any) {
|
||||||
|
t.deepEqual(e.target.result.key, record.key);
|
||||||
|
resolve();
|
||||||
|
};
|
||||||
|
};
|
||||||
|
});
|
||||||
|
t.pass();
|
||||||
|
});
|
||||||
|
|
||||||
|
// IDBIndex.get() - returns the record where the index contains duplicate values
|
||||||
|
test("WPT idbindex_get2.htm", async (t) => {
|
||||||
|
await new Promise<void>((resolve, reject) => {
|
||||||
|
var db: any;
|
||||||
|
const records = [
|
||||||
|
{ key: 1, indexedProperty: "data" },
|
||||||
|
{ key: 2, indexedProperty: "data" },
|
||||||
|
{ key: 3, indexedProperty: "data" },
|
||||||
|
];
|
||||||
|
|
||||||
|
var open_rq = createdb(t);
|
||||||
|
open_rq.onupgradeneeded = function (e: any) {
|
||||||
|
db = e.target.result;
|
||||||
|
var objStore = db.createObjectStore("test", { keyPath: "key" });
|
||||||
|
objStore.createIndex("index", "indexedProperty");
|
||||||
|
|
||||||
|
for (var i = 0; i < records.length; i++) objStore.add(records[i]);
|
||||||
|
};
|
||||||
|
|
||||||
|
open_rq.onsuccess = function (e) {
|
||||||
|
var rq = db
|
||||||
|
.transaction("test")
|
||||||
|
.objectStore("test")
|
||||||
|
.index("index")
|
||||||
|
.get("data");
|
||||||
|
|
||||||
|
rq.onsuccess = function (e: any) {
|
||||||
|
t.deepEqual(e.target.result.key, records[0].key);
|
||||||
|
resolve();
|
||||||
|
};
|
||||||
|
};
|
||||||
|
});
|
||||||
|
t.pass();
|
||||||
|
});
|
||||||
|
|
||||||
|
// IDBIndex.get() - attempt to retrieve a record that doesn't exist
|
||||||
|
test("WPT idbindex_get3.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 rq = db
|
||||||
|
.createObjectStore("test", { keyPath: "key" })
|
||||||
|
.createIndex("index", "indexedProperty")
|
||||||
|
.get(1);
|
||||||
|
|
||||||
|
rq.onsuccess = function (e: any) {
|
||||||
|
t.deepEqual(e.target.result, undefined);
|
||||||
|
resolve();
|
||||||
|
};
|
||||||
|
};
|
||||||
|
});
|
||||||
|
t.pass();
|
||||||
|
});
|
||||||
|
|
||||||
|
// IDBIndex.get() - returns the record with the first key in the range
|
||||||
|
test("WPT idbindex_get4.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" });
|
||||||
|
store.createIndex("index", "indexedProperty");
|
||||||
|
|
||||||
|
for (var i = 0; i < 10; i++) {
|
||||||
|
store.add({ key: i, indexedProperty: "data" + i });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
open_rq.onsuccess = function (e) {
|
||||||
|
var rq = db
|
||||||
|
.transaction("store")
|
||||||
|
.objectStore("store")
|
||||||
|
.index("index")
|
||||||
|
.get(BridgeIDBKeyRange.bound("data4", "data7"));
|
||||||
|
|
||||||
|
rq.onsuccess = function (e: any) {
|
||||||
|
t.deepEqual(e.target.result.key, 4);
|
||||||
|
t.deepEqual(e.target.result.indexedProperty, "data4");
|
||||||
|
setTimeout(function () {
|
||||||
|
resolve();
|
||||||
|
}, 4);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
});
|
||||||
|
t.pass();
|
||||||
|
});
|
||||||
|
|
||||||
|
// IDBIndex.get() - throw DataError when using invalid key
|
||||||
|
test("WPT idbindex_get5.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 index = db
|
||||||
|
.createObjectStore("test", { keyPath: "key" })
|
||||||
|
.createIndex("index", "indexedProperty");
|
||||||
|
t.throws(
|
||||||
|
function () {
|
||||||
|
index.get(NaN);
|
||||||
|
},
|
||||||
|
{ name: "DataError" },
|
||||||
|
);
|
||||||
|
resolve();
|
||||||
|
};
|
||||||
|
});
|
||||||
|
t.pass();
|
||||||
|
});
|
||||||
|
|
||||||
|
// IDBIndex.get() - throw InvalidStateError when the index is deleted
|
||||||
|
test("WPT idbindex_get6.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" });
|
||||||
|
store.deleteIndex("index");
|
||||||
|
|
||||||
|
t.throws(
|
||||||
|
function () {
|
||||||
|
index.get("data");
|
||||||
|
},
|
||||||
|
{ name: "InvalidStateError" },
|
||||||
|
);
|
||||||
|
resolve();
|
||||||
|
};
|
||||||
|
});
|
||||||
|
t.pass();
|
||||||
|
});
|
@ -1,4 +1,5 @@
|
|||||||
import test from "ava";
|
import test from "ava";
|
||||||
|
import { BridgeIDBRequest } from "..";
|
||||||
import { IDBDatabase } from "../idbtypes";
|
import { IDBDatabase } from "../idbtypes";
|
||||||
import { createdb } from "./wptsupport";
|
import { createdb } from "./wptsupport";
|
||||||
|
|
||||||
@ -228,7 +229,8 @@ test("WPT idbobjectstore_add7.htm", async (t) => {
|
|||||||
t.pass();
|
t.pass();
|
||||||
});
|
});
|
||||||
|
|
||||||
// IDBObjectStore.add() - object store has autoIncrement:true and the key path is an object attribute
|
// IDBObjectStore.add() - object store has autoIncrement:true and the key path
|
||||||
|
// is an object attribute
|
||||||
test("WPT idbobjectstore_add8.htm", async (t) => {
|
test("WPT idbobjectstore_add8.htm", async (t) => {
|
||||||
await new Promise<void>((resolve, reject) => {
|
await new Promise<void>((resolve, reject) => {
|
||||||
var db: any;
|
var db: any;
|
||||||
@ -268,3 +270,217 @@ test("WPT idbobjectstore_add8.htm", async (t) => {
|
|||||||
});
|
});
|
||||||
t.pass();
|
t.pass();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// IDBObjectStore.add() - Attempt to add a record that does not meet the
|
||||||
|
// constraints of an object store's inline key requirements
|
||||||
|
test("WPT idbobjectstore_add9.htm", async (t) => {
|
||||||
|
await new Promise<void>((resolve, reject) => {
|
||||||
|
const record = { key: 1, property: "data" };
|
||||||
|
|
||||||
|
var open_rq = createdb(t);
|
||||||
|
open_rq.onupgradeneeded = function (e: any) {
|
||||||
|
var rq,
|
||||||
|
db = e.target.result,
|
||||||
|
objStore = db.createObjectStore("store", { keyPath: "key" });
|
||||||
|
|
||||||
|
t.throws(
|
||||||
|
function () {
|
||||||
|
rq = objStore.add(record, 1);
|
||||||
|
},
|
||||||
|
{ name: "DataError" },
|
||||||
|
);
|
||||||
|
t.deepEqual(rq, undefined);
|
||||||
|
resolve();
|
||||||
|
};
|
||||||
|
});
|
||||||
|
t.pass();
|
||||||
|
});
|
||||||
|
|
||||||
|
// IDBObjectStore.add() - Attempt to call 'add' without an key parameter when the
|
||||||
|
// object store uses out-of-line keys.
|
||||||
|
test("WPT idbobjectstore_add10.htm", async (t) => {
|
||||||
|
await new Promise<void>((resolve, reject) => {
|
||||||
|
var db: any;
|
||||||
|
const record = { property: "data" };
|
||||||
|
|
||||||
|
var open_rq = createdb(t);
|
||||||
|
open_rq.onupgradeneeded = function (e: any) {
|
||||||
|
db = e.target.result;
|
||||||
|
|
||||||
|
var rq,
|
||||||
|
objStore = db.createObjectStore("store");
|
||||||
|
|
||||||
|
t.throws(
|
||||||
|
function () {
|
||||||
|
rq = objStore.add(record);
|
||||||
|
},
|
||||||
|
{ name: "DataError" },
|
||||||
|
);
|
||||||
|
|
||||||
|
t.deepEqual(rq, undefined);
|
||||||
|
resolve();
|
||||||
|
};
|
||||||
|
});
|
||||||
|
t.pass();
|
||||||
|
});
|
||||||
|
|
||||||
|
// IDBObjectStore.add() - Attempt to add a record where the record's key
|
||||||
|
// does not meet the constraints of a valid key
|
||||||
|
test("WPT idbobjectstore_add11.htm", async (t) => {
|
||||||
|
await new Promise<void>((resolve, reject) => {
|
||||||
|
var db: any;
|
||||||
|
const record = { key: { value: 1 }, property: "data" };
|
||||||
|
|
||||||
|
var open_rq = createdb(t);
|
||||||
|
open_rq.onupgradeneeded = function (e: any) {
|
||||||
|
db = e.target.result;
|
||||||
|
|
||||||
|
var rq,
|
||||||
|
objStore = db.createObjectStore("store", { keyPath: "key" });
|
||||||
|
|
||||||
|
t.throws(
|
||||||
|
function () {
|
||||||
|
rq = objStore.add(record);
|
||||||
|
},
|
||||||
|
{ name: "DataError" },
|
||||||
|
);
|
||||||
|
|
||||||
|
t.deepEqual(rq, undefined);
|
||||||
|
resolve();
|
||||||
|
};
|
||||||
|
});
|
||||||
|
t.pass();
|
||||||
|
});
|
||||||
|
|
||||||
|
// IDBObjectStore.add() - Attempt to add a record where the
|
||||||
|
// record's in-line key is not defined
|
||||||
|
test("WPT idbobjectstore_add12.htm", async (t) => {
|
||||||
|
await new Promise<void>((resolve, reject) => {
|
||||||
|
var db: any;
|
||||||
|
const record = { property: "data" };
|
||||||
|
|
||||||
|
var open_rq = createdb(t);
|
||||||
|
open_rq.onupgradeneeded = function (e: any) {
|
||||||
|
db = e.target.result;
|
||||||
|
|
||||||
|
var rq,
|
||||||
|
objStore = db.createObjectStore("store", { keyPath: "key" });
|
||||||
|
t.throws(
|
||||||
|
function () {
|
||||||
|
rq = objStore.add(record);
|
||||||
|
},
|
||||||
|
{ name: "DataError" },
|
||||||
|
);
|
||||||
|
t.deepEqual(rq, undefined);
|
||||||
|
resolve();
|
||||||
|
};
|
||||||
|
});
|
||||||
|
t.pass();
|
||||||
|
});
|
||||||
|
|
||||||
|
// IDBObjectStore.add() - Attempt to add a record where the out of line
|
||||||
|
// key provided does not meet the constraints of a valid key
|
||||||
|
test("WPT idbobjectstore_add13.htm", async (t) => {
|
||||||
|
await new Promise<void>((resolve, reject) => {
|
||||||
|
var db: any;
|
||||||
|
const record = { property: "data" };
|
||||||
|
|
||||||
|
var open_rq = createdb(t);
|
||||||
|
open_rq.onupgradeneeded = function (e: any) {
|
||||||
|
db = e.target.result;
|
||||||
|
|
||||||
|
var rq,
|
||||||
|
objStore = db.createObjectStore("store");
|
||||||
|
|
||||||
|
t.throws(
|
||||||
|
function () {
|
||||||
|
rq = objStore.add(record, { value: 1 });
|
||||||
|
},
|
||||||
|
{ name: "DataError" },
|
||||||
|
);
|
||||||
|
|
||||||
|
t.deepEqual(rq, undefined);
|
||||||
|
resolve();
|
||||||
|
};
|
||||||
|
});
|
||||||
|
t.pass();
|
||||||
|
});
|
||||||
|
|
||||||
|
// IDBObjectStore.add() - Add a record where a value
|
||||||
|
// being indexed does not meet the constraints of a valid key
|
||||||
|
test("WPT idbobjectstore_add14.htm", async (t) => {
|
||||||
|
await new Promise<void>((resolve, reject) => {
|
||||||
|
var db: any;
|
||||||
|
const record = { key: 1, indexedProperty: { property: "data" } };
|
||||||
|
|
||||||
|
var open_rq = createdb(t);
|
||||||
|
open_rq.onupgradeneeded = function (e: any) {
|
||||||
|
db = e.target.result;
|
||||||
|
|
||||||
|
var rq,
|
||||||
|
objStore = db.createObjectStore("store", { keyPath: "key" });
|
||||||
|
|
||||||
|
objStore.createIndex("index", "indexedProperty");
|
||||||
|
|
||||||
|
rq = objStore.add(record);
|
||||||
|
|
||||||
|
t.assert(rq instanceof BridgeIDBRequest);
|
||||||
|
rq.onsuccess = function () {
|
||||||
|
resolve();
|
||||||
|
};
|
||||||
|
};
|
||||||
|
});
|
||||||
|
t.pass();
|
||||||
|
});
|
||||||
|
|
||||||
|
// IDBObjectStore.add() - If the transaction this IDBObjectStore belongs
|
||||||
|
// to has its mode set to readonly, throw ReadOnlyError
|
||||||
|
test("WPT idbobjectstore_add15.htm", async (t) => {
|
||||||
|
await new Promise<void>((resolve, reject) => {
|
||||||
|
var db: any;
|
||||||
|
|
||||||
|
var open_rq = createdb(t);
|
||||||
|
open_rq.onupgradeneeded = function (event: any) {
|
||||||
|
db = event.target.result;
|
||||||
|
db.createObjectStore("store", { keyPath: "pKey" });
|
||||||
|
};
|
||||||
|
|
||||||
|
open_rq.onsuccess = function (event) {
|
||||||
|
var txn = db.transaction("store");
|
||||||
|
var ostore = txn.objectStore("store");
|
||||||
|
t.throws(
|
||||||
|
function () {
|
||||||
|
ostore.add({ pKey: "primaryKey_0" });
|
||||||
|
},
|
||||||
|
{ name: "ReadOnlyError" },
|
||||||
|
);
|
||||||
|
resolve();
|
||||||
|
};
|
||||||
|
});
|
||||||
|
t.pass();
|
||||||
|
});
|
||||||
|
|
||||||
|
// IDBObjectStore.add() - If the object store has been
|
||||||
|
// deleted, the implementation must throw a DOMException of type InvalidStateError
|
||||||
|
test("WPT idbobjectstore_add16.htm", async (t) => {
|
||||||
|
await new Promise<void>((resolve, reject) => {
|
||||||
|
var db: any;
|
||||||
|
let ostore: any;
|
||||||
|
|
||||||
|
var open_rq = createdb(t);
|
||||||
|
open_rq.onupgradeneeded = function (event: any) {
|
||||||
|
db = event.target.result;
|
||||||
|
ostore = db.createObjectStore("store", { keyPath: "pKey" });
|
||||||
|
db.deleteObjectStore("store");
|
||||||
|
|
||||||
|
t.throws(
|
||||||
|
function () {
|
||||||
|
ostore.add({ pKey: "primaryKey_0" });
|
||||||
|
},
|
||||||
|
{ name: "InvalidStateError" },
|
||||||
|
);
|
||||||
|
resolve();
|
||||||
|
};
|
||||||
|
});
|
||||||
|
t.pass();
|
||||||
|
});
|
||||||
|
@ -5,7 +5,9 @@ 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 backend = new MemoryBackend();
|
||||||
|
backend.enableTracing = true;
|
||||||
|
const idbFactory = new BridgeIDBFactory(backend);
|
||||||
|
|
||||||
const self = {
|
const self = {
|
||||||
indexedDB: idbFactory,
|
indexedDB: idbFactory,
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
import { IDBValidKey } from "..";
|
import { IDBValidKey } from "..";
|
||||||
import { DataError } from "./errors";
|
import { DataError } from "./errors";
|
||||||
|
|
||||||
// https://w3c.github.io/IndexedDB/#convert-a-value-to-a-input
|
// https://www.w3.org/TR/IndexedDB-2/#convert-a-value-to-a-key
|
||||||
export function valueToKey(
|
export function valueToKey(
|
||||||
input: any,
|
input: any,
|
||||||
seen?: Set<object>,
|
seen?: Set<object>,
|
||||||
|
Loading…
Reference in New Issue
Block a user