idb: more tests working
This commit is contained in:
parent
a4e4125cca
commit
859a9e72e1
@ -52,9 +52,9 @@ class BridgeIDBCursor {
|
|||||||
|
|
||||||
private _gotValue: boolean = false;
|
private _gotValue: boolean = false;
|
||||||
private _range: CursorRange;
|
private _range: CursorRange;
|
||||||
private _position = undefined; // Key of previously returned record
|
private _indexPosition = undefined; // Key of previously returned record
|
||||||
private _objectStorePosition = undefined;
|
private _objectStorePosition = undefined;
|
||||||
private _keyOnly: boolean = false;
|
private _keyOnly: boolean;
|
||||||
|
|
||||||
private _source: CursorSource;
|
private _source: CursorSource;
|
||||||
private _direction: BridgeIDBCursorDirection;
|
private _direction: BridgeIDBCursorDirection;
|
||||||
@ -63,6 +63,8 @@ class BridgeIDBCursor {
|
|||||||
private _indexName: string | undefined;
|
private _indexName: string | undefined;
|
||||||
private _objectStoreName: string;
|
private _objectStoreName: string;
|
||||||
|
|
||||||
|
protected _value: Value = undefined;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
source: CursorSource,
|
source: CursorSource,
|
||||||
objectStoreName: string,
|
objectStoreName: string,
|
||||||
@ -128,7 +130,7 @@ class BridgeIDBCursor {
|
|||||||
const recordGetRequest: RecordGetRequest = {
|
const recordGetRequest: RecordGetRequest = {
|
||||||
direction: this.direction,
|
direction: this.direction,
|
||||||
indexName: this._indexName,
|
indexName: this._indexName,
|
||||||
lastIndexPosition: this._position,
|
lastIndexPosition: this._indexPosition,
|
||||||
lastObjectStorePosition: this._objectStorePosition,
|
lastObjectStorePosition: this._objectStorePosition,
|
||||||
limit: 1,
|
limit: 1,
|
||||||
range: this._range,
|
range: this._range,
|
||||||
@ -140,15 +142,38 @@ class BridgeIDBCursor {
|
|||||||
|
|
||||||
const { btx } = this.source._confirmActiveTransaction();
|
const { btx } = this.source._confirmActiveTransaction();
|
||||||
|
|
||||||
let response = await this._backend.getRecords(
|
let response = await this._backend.getRecords(btx, recordGetRequest);
|
||||||
btx,
|
|
||||||
recordGetRequest,
|
|
||||||
);
|
|
||||||
|
|
||||||
if (response.count === 0) {
|
if (response.count === 0) {
|
||||||
|
console.log("cursor is returning empty result");
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (response.count !== 1) {
|
||||||
|
throw Error("invariant failed");
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log("request is:", JSON.stringify(recordGetRequest));
|
||||||
|
console.log("get response is:", JSON.stringify(response));
|
||||||
|
|
||||||
|
if (this._indexName !== undefined) {
|
||||||
|
this._key = response.indexKeys![0];
|
||||||
|
} else {
|
||||||
|
this._key = response.primaryKeys![0];
|
||||||
|
}
|
||||||
|
|
||||||
|
this._primaryKey = response.primaryKeys![0];
|
||||||
|
|
||||||
|
if (!this._keyOnly) {
|
||||||
|
this._value = response.values![0];
|
||||||
|
}
|
||||||
|
|
||||||
|
this._gotValue = true;
|
||||||
|
this._objectStorePosition = structuredClone(response.primaryKeys![0]);
|
||||||
|
if (response.indexKeys !== undefined && response.indexKeys.length > 0) {
|
||||||
|
this._indexPosition = structuredClone(response.indexKeys[0]);
|
||||||
|
}
|
||||||
|
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -171,6 +196,7 @@ class BridgeIDBCursor {
|
|||||||
if (this._effectiveObjectStore._deleted) {
|
if (this._effectiveObjectStore._deleted) {
|
||||||
throw new InvalidStateError();
|
throw new InvalidStateError();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (
|
if (
|
||||||
!(this.source instanceof BridgeIDBObjectStore) &&
|
!(this.source instanceof BridgeIDBObjectStore) &&
|
||||||
this.source._deleted
|
this.source._deleted
|
||||||
@ -232,8 +258,12 @@ class BridgeIDBCursor {
|
|||||||
|
|
||||||
if (key !== undefined) {
|
if (key !== undefined) {
|
||||||
key = valueToKey(key);
|
key = valueToKey(key);
|
||||||
|
let lastKey =
|
||||||
|
this._indexName === undefined
|
||||||
|
? this._objectStorePosition
|
||||||
|
: this._indexPosition;
|
||||||
|
|
||||||
const cmpResult = compareKeys(key, this._position);
|
const cmpResult = compareKeys(key, lastKey);
|
||||||
|
|
||||||
if (
|
if (
|
||||||
(cmpResult <= 0 &&
|
(cmpResult <= 0 &&
|
||||||
@ -250,7 +280,7 @@ class BridgeIDBCursor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const operation = async () => {
|
const operation = async () => {
|
||||||
this._iterate(key);
|
return this._iterate(key);
|
||||||
};
|
};
|
||||||
|
|
||||||
transaction._execRequestAsync({
|
transaction._execRequestAsync({
|
||||||
|
@ -22,8 +22,11 @@ import {
|
|||||||
Value,
|
Value,
|
||||||
} from "./util/types";
|
} from "./util/types";
|
||||||
|
|
||||||
class FDBCursorWithValue extends BridgeIDBCursor {
|
class BridgeIDBCursorWithValue extends BridgeIDBCursor {
|
||||||
public value: Value = undefined;
|
|
||||||
|
get value(): Value {
|
||||||
|
return this._value;
|
||||||
|
}
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
source: CursorSource,
|
source: CursorSource,
|
||||||
@ -33,7 +36,7 @@ class FDBCursorWithValue extends BridgeIDBCursor {
|
|||||||
direction: BridgeIDBCursorDirection,
|
direction: BridgeIDBCursorDirection,
|
||||||
request?: any,
|
request?: any,
|
||||||
) {
|
) {
|
||||||
super(source, objectStoreName, indexName, range, direction, request, true);
|
super(source, objectStoreName, indexName, range, direction, request, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public toString() {
|
public toString() {
|
||||||
@ -41,4 +44,4 @@ class FDBCursorWithValue extends BridgeIDBCursor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default FDBCursorWithValue;
|
export default BridgeIDBCursorWithValue;
|
||||||
|
@ -19,7 +19,6 @@ import BridgeIDBCursorWithValue from "./BridgeIDBCursorWithValue";
|
|||||||
import BridgeIDBKeyRange from "./BridgeIDBKeyRange";
|
import BridgeIDBKeyRange from "./BridgeIDBKeyRange";
|
||||||
import BridgeIDBObjectStore from "./BridgeIDBObjectStore";
|
import BridgeIDBObjectStore from "./BridgeIDBObjectStore";
|
||||||
import BridgeIDBRequest from "./BridgeIDBRequest";
|
import BridgeIDBRequest from "./BridgeIDBRequest";
|
||||||
import enforceRange from "./util/enforceRange";
|
|
||||||
import {
|
import {
|
||||||
ConstraintError,
|
ConstraintError,
|
||||||
InvalidStateError,
|
InvalidStateError,
|
||||||
|
@ -215,6 +215,9 @@ class BridgeIDBTransaction extends FakeEventTarget {
|
|||||||
let event;
|
let event;
|
||||||
try {
|
try {
|
||||||
const result = await operation();
|
const result = await operation();
|
||||||
|
if (BridgeIDBFactory.enableTracing) {
|
||||||
|
console.log("TRACE: tx operation finished with success");
|
||||||
|
}
|
||||||
request.readyState = "done";
|
request.readyState = "done";
|
||||||
request.result = result;
|
request.result = result;
|
||||||
request.error = undefined;
|
request.error = undefined;
|
||||||
|
@ -4,7 +4,8 @@ import BridgeIDBFactory from "./BridgeIDBFactory";
|
|||||||
import BridgeIDBRequest from "./BridgeIDBRequest";
|
import BridgeIDBRequest from "./BridgeIDBRequest";
|
||||||
import BridgeIDBDatabase from "./BridgeIDBDatabase";
|
import BridgeIDBDatabase from "./BridgeIDBDatabase";
|
||||||
import BridgeIDBTransaction from "./BridgeIDBTransaction";
|
import BridgeIDBTransaction from "./BridgeIDBTransaction";
|
||||||
|
import BridgeIDBKeyRange from "./BridgeIDBKeyRange";
|
||||||
|
import BridgeIDBCursorWithValue from "./BridgeIDBCursorWithValue";
|
||||||
|
|
||||||
function promiseFromRequest(request: BridgeIDBRequest): Promise<any> {
|
function promiseFromRequest(request: BridgeIDBRequest): Promise<any> {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
@ -17,11 +18,13 @@ function promiseFromRequest(request: BridgeIDBRequest): Promise<any> {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function promiseFromTransaction(transaction: BridgeIDBTransaction): Promise<any> {
|
function promiseFromTransaction(
|
||||||
|
transaction: BridgeIDBTransaction,
|
||||||
|
): Promise<any> {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
console.log("attaching event handlers");
|
console.log("attaching event handlers");
|
||||||
transaction.oncomplete = () => {
|
transaction.oncomplete = () => {
|
||||||
console.log("oncomplete was called from promise")
|
console.log("oncomplete was called from promise");
|
||||||
resolve();
|
resolve();
|
||||||
};
|
};
|
||||||
transaction.onerror = () => {
|
transaction.onerror = () => {
|
||||||
@ -51,7 +54,6 @@ test("Spec: Example 1 Part 1", async t => {
|
|||||||
t.pass();
|
t.pass();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
test("Spec: Example 1 Part 2", async t => {
|
test("Spec: Example 1 Part 2", async t => {
|
||||||
const backend = new MemoryBackend();
|
const backend = new MemoryBackend();
|
||||||
const idb = new BridgeIDBFactory(backend);
|
const idb = new BridgeIDBFactory(backend);
|
||||||
@ -70,21 +72,20 @@ test("Spec: Example 1 Part 2", async t => {
|
|||||||
|
|
||||||
const tx = db.transaction("books", "readwrite");
|
const tx = db.transaction("books", "readwrite");
|
||||||
tx.oncomplete = () => {
|
tx.oncomplete = () => {
|
||||||
console.log("oncomplete called")
|
console.log("oncomplete called");
|
||||||
};
|
};
|
||||||
|
|
||||||
const store = tx.objectStore("books");
|
const store = tx.objectStore("books");
|
||||||
|
|
||||||
store.put({title: "Quarry Memories", author: "Fred", isbn: 123456});
|
store.put({ title: "Quarry Memories", author: "Fred", isbn: 123456 });
|
||||||
store.put({title: "Water Buffaloes", author: "Fred", isbn: 234567});
|
store.put({ title: "Water Buffaloes", author: "Fred", isbn: 234567 });
|
||||||
store.put({title: "Bedrock Nights", author: "Barney", isbn: 345678});
|
store.put({ title: "Bedrock Nights", author: "Barney", isbn: 345678 });
|
||||||
|
|
||||||
await promiseFromTransaction(tx);
|
await promiseFromTransaction(tx);
|
||||||
|
|
||||||
t.pass();
|
t.pass();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
test("Spec: Example 1 Part 3", async t => {
|
test("Spec: Example 1 Part 3", async t => {
|
||||||
const backend = new MemoryBackend();
|
const backend = new MemoryBackend();
|
||||||
const idb = new BridgeIDBFactory(backend);
|
const idb = new BridgeIDBFactory(backend);
|
||||||
@ -102,15 +103,12 @@ test("Spec: Example 1 Part 3", async t => {
|
|||||||
t.is(db.name, "library");
|
t.is(db.name, "library");
|
||||||
|
|
||||||
const tx = db.transaction("books", "readwrite");
|
const tx = db.transaction("books", "readwrite");
|
||||||
tx.oncomplete = () => {
|
|
||||||
console.log("oncomplete called")
|
|
||||||
};
|
|
||||||
|
|
||||||
const store = tx.objectStore("books");
|
const store = tx.objectStore("books");
|
||||||
|
|
||||||
store.put({title: "Quarry Memories", author: "Fred", isbn: 123456});
|
store.put({ title: "Bedrock Nights", author: "Barney", isbn: 345678 });
|
||||||
store.put({title: "Water Buffaloes", author: "Fred", isbn: 234567});
|
store.put({ title: "Quarry Memories", author: "Fred", isbn: 123456 });
|
||||||
store.put({title: "Bedrock Nights", author: "Barney", isbn: 345678});
|
store.put({ title: "Water Buffaloes", author: "Fred", isbn: 234567 });
|
||||||
|
|
||||||
await promiseFromTransaction(tx);
|
await promiseFromTransaction(tx);
|
||||||
|
|
||||||
@ -122,5 +120,38 @@ test("Spec: Example 1 Part 3", async t => {
|
|||||||
|
|
||||||
t.is(result2.author, "Barney");
|
t.is(result2.author, "Barney");
|
||||||
|
|
||||||
|
const tx3 = db.transaction(["books"], "readonly");
|
||||||
|
const store3 = tx3.objectStore("books");
|
||||||
|
const index3 = store3.index("by_author");
|
||||||
|
const request3 = index3.openCursor(BridgeIDBKeyRange.only("Fred"));
|
||||||
|
|
||||||
|
await promiseFromRequest(request3);
|
||||||
|
|
||||||
|
let cursor: BridgeIDBCursorWithValue;
|
||||||
|
cursor = request3.result as BridgeIDBCursorWithValue;
|
||||||
|
t.is(cursor.value.author, "Fred");
|
||||||
|
t.is(cursor.value.isbn, 123456);
|
||||||
|
|
||||||
|
cursor.continue();
|
||||||
|
|
||||||
|
await promiseFromRequest(request3);
|
||||||
|
|
||||||
|
cursor = request3.result as BridgeIDBCursorWithValue;
|
||||||
|
t.is(cursor.value.author, "Fred");
|
||||||
|
t.is(cursor.value.isbn, 234567);
|
||||||
|
|
||||||
|
await promiseFromTransaction(tx3);
|
||||||
|
|
||||||
|
const tx4 = db.transaction("books", "readonly");
|
||||||
|
const store4 = tx4.objectStore("books");
|
||||||
|
const request4 = store4.openCursor();
|
||||||
|
|
||||||
|
await promiseFromRequest(request4);
|
||||||
|
|
||||||
|
cursor = request4.result;
|
||||||
|
t.is(cursor.value.isbn, 123456);
|
||||||
|
|
||||||
|
db.close();
|
||||||
|
|
||||||
t.pass();
|
t.pass();
|
||||||
});
|
});
|
||||||
|
@ -132,8 +132,11 @@ function nextStoreKey<T>(
|
|||||||
return res[1].primaryKey;
|
return res[1].primaryKey;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function furthestKey(
|
||||||
function furthestKey(forward: boolean, key1: Key | undefined, key2: Key | undefined) {
|
forward: boolean,
|
||||||
|
key1: Key | undefined,
|
||||||
|
key2: Key | undefined,
|
||||||
|
) {
|
||||||
if (key1 === undefined) {
|
if (key1 === undefined) {
|
||||||
return key2;
|
return key2;
|
||||||
}
|
}
|
||||||
@ -668,6 +671,7 @@ export class MemoryBackend implements Backend {
|
|||||||
): Promise<RecordGetResponse> {
|
): Promise<RecordGetResponse> {
|
||||||
if (this.enableTracing) {
|
if (this.enableTracing) {
|
||||||
console.log(`TRACING: getRecords`);
|
console.log(`TRACING: getRecords`);
|
||||||
|
console.log("query", req);
|
||||||
}
|
}
|
||||||
const myConn = this.connectionsByTransaction[btx.transactionCookie];
|
const myConn = this.connectionsByTransaction[btx.transactionCookie];
|
||||||
if (!myConn) {
|
if (!myConn) {
|
||||||
@ -687,15 +691,15 @@ export class MemoryBackend implements Backend {
|
|||||||
|
|
||||||
let range;
|
let range;
|
||||||
if (req.range == null || req.range === undefined) {
|
if (req.range == null || req.range === undefined) {
|
||||||
range = new BridgeIDBKeyRange(null, null, true, true);
|
range = new BridgeIDBKeyRange(undefined, undefined, true, true);
|
||||||
} else {
|
} else {
|
||||||
range = req.range;
|
range = req.range;
|
||||||
}
|
}
|
||||||
|
|
||||||
let numResults = 0;
|
let numResults = 0;
|
||||||
let indexKeys: Key[] = [];
|
let indexKeys: Key[] = [];
|
||||||
let primaryKeys = [];
|
let primaryKeys: Key[] = [];
|
||||||
let values = [];
|
let values: Value[] = [];
|
||||||
|
|
||||||
const forward: boolean =
|
const forward: boolean =
|
||||||
req.direction === "next" || req.direction === "nextunique";
|
req.direction === "next" || req.direction === "nextunique";
|
||||||
@ -797,8 +801,6 @@ export class MemoryBackend implements Backend {
|
|||||||
primkeySubPos = forward ? 0 : indexEntry.primaryKeys.length - 1;
|
primkeySubPos = forward ? 0 : indexEntry.primaryKeys.length - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: filter out duplicates
|
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
if (req.limit != 0 && numResults == req.limit) {
|
if (req.limit != 0 && numResults == req.limit) {
|
||||||
break;
|
break;
|
||||||
@ -821,6 +823,16 @@ export class MemoryBackend implements Backend {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (
|
||||||
|
unique &&
|
||||||
|
indexKeys.length > 0 &&
|
||||||
|
compareKeys(indexEntry.indexKey, indexKeys[indexKeys.length - 1]) ===
|
||||||
|
0
|
||||||
|
) {
|
||||||
|
// We only return the first result if subsequent index keys are the same.
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
indexKeys.push(indexEntry.indexKey);
|
||||||
primaryKeys.push(indexEntry.primaryKeys[primkeySubPos]);
|
primaryKeys.push(indexEntry.primaryKeys[primkeySubPos]);
|
||||||
numResults++;
|
numResults++;
|
||||||
primkeySubPos = forward ? 0 : indexEntry.primaryKeys.length - 1;
|
primkeySubPos = forward ? 0 : indexEntry.primaryKeys.length - 1;
|
||||||
@ -850,48 +862,53 @@ export class MemoryBackend implements Backend {
|
|||||||
|
|
||||||
storePos = furthestKey(forward, req.advancePrimaryKey, storePos);
|
storePos = furthestKey(forward, req.advancePrimaryKey, storePos);
|
||||||
|
|
||||||
// Advance store position if we are either still at the last returned
|
if (storePos !== null && storePos !== undefined) {
|
||||||
// store key, or if we are currently not on a key.
|
// Advance store position if we are either still at the last returned
|
||||||
const storeEntry = storeData.get(storePos);
|
// store key, or if we are currently not on a key.
|
||||||
if (
|
const storeEntry = storeData.get(storePos);
|
||||||
!storeEntry ||
|
if (
|
||||||
(req.lastObjectStorePosition !== undefined &&
|
!storeEntry ||
|
||||||
compareKeys(req.lastObjectStorePosition, storeEntry.primaryKey))
|
(req.lastObjectStorePosition !== undefined &&
|
||||||
) {
|
compareKeys(req.lastObjectStorePosition, storeEntry.primaryKey))
|
||||||
storePos = storeData.nextHigherKey(storePos);
|
) {
|
||||||
|
storePos = storeData.nextHigherKey(storePos);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
storePos = forward ? storeData.minKey() : storeData.maxKey();
|
||||||
|
console.log("setting starting store store pos to", storePos);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (req.lastObjectStorePosition)
|
while (1) {
|
||||||
while (1) {
|
if (req.limit != 0 && numResults == req.limit) {
|
||||||
if (req.limit != 0 && numResults == req.limit) {
|
break;
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (storePos === null || storePos === undefined) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (!range.includes(storePos)) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
const res = storeData.get(storePos);
|
|
||||||
|
|
||||||
if (!res) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (req.resultLevel >= ResultLevel.OnlyKeys) {
|
|
||||||
primaryKeys.push(res.primaryKey);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (req.resultLevel >= ResultLevel.Full) {
|
|
||||||
values.push(res.value);
|
|
||||||
}
|
|
||||||
numResults++;
|
|
||||||
storePos = nextStoreKey(forward, storeData, storePos);
|
|
||||||
}
|
}
|
||||||
|
if (storePos === null || storePos === undefined) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (!range.includes(storePos)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
const res = storeData.get(storePos);
|
||||||
|
|
||||||
|
if (res === undefined) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (req.resultLevel >= ResultLevel.OnlyKeys) {
|
||||||
|
primaryKeys.push(structuredClone(storePos));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (req.resultLevel >= ResultLevel.Full) {
|
||||||
|
values.push(res);
|
||||||
|
}
|
||||||
|
|
||||||
|
numResults++;
|
||||||
|
storePos = nextStoreKey(forward, storeData, storePos);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (this.enableTracing) {
|
if (this.enableTracing) {
|
||||||
console.log(`TRACING: getRecords got ${numResults} results`)
|
console.log(`TRACING: getRecords got ${numResults} results`);
|
||||||
}
|
}
|
||||||
return {
|
return {
|
||||||
count: numResults,
|
count: numResults,
|
||||||
@ -962,7 +979,7 @@ export class MemoryBackend implements Backend {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
insertIntoIndex(
|
private insertIntoIndex(
|
||||||
index: Index,
|
index: Index,
|
||||||
primaryKey: Key,
|
primaryKey: Key,
|
||||||
value: Value,
|
value: Value,
|
||||||
@ -987,7 +1004,9 @@ export class MemoryBackend implements Backend {
|
|||||||
} else {
|
} else {
|
||||||
const newIndexRecord = {
|
const newIndexRecord = {
|
||||||
indexKey: indexKey,
|
indexKey: indexKey,
|
||||||
primaryKeys: [primaryKey].concat(existingRecord.primaryKeys),
|
primaryKeys: [primaryKey]
|
||||||
|
.concat(existingRecord.primaryKeys)
|
||||||
|
.sort(compareKeys),
|
||||||
};
|
};
|
||||||
index.modifiedData = indexData.with(indexKey, newIndexRecord, true);
|
index.modifiedData = indexData.with(indexKey, newIndexRecord, true);
|
||||||
}
|
}
|
||||||
|
@ -36,9 +36,9 @@ export interface DatabaseTransaction {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export enum ResultLevel {
|
export enum ResultLevel {
|
||||||
Full,
|
|
||||||
OnlyKeys,
|
|
||||||
OnlyCount,
|
OnlyCount,
|
||||||
|
OnlyKeys,
|
||||||
|
Full,
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface RecordGetRequest {
|
export interface RecordGetRequest {
|
||||||
|
@ -39,6 +39,8 @@ 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 => {
|
const compareKeys = (first: any, second: any): -1 | 0 | 1 => {
|
||||||
|
console.log("comparing keys", first, second);
|
||||||
|
|
||||||
if (second === undefined) {
|
if (second === undefined) {
|
||||||
throw new TypeError();
|
throw new TypeError();
|
||||||
}
|
}
|
||||||
|
@ -14,57 +14,57 @@
|
|||||||
permissions and limitations under the License.
|
permissions and limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
import { DataError } from "./errors";
|
import { DataError } from "./errors";
|
||||||
import { Key } from "./types";
|
import { Key } from "./types";
|
||||||
|
|
||||||
// https://w3c.github.io/IndexedDB/#convert-a-value-to-a-input
|
// https://w3c.github.io/IndexedDB/#convert-a-value-to-a-input
|
||||||
function valueToKey(input: any, seen?: Set<object>): Key | Key[] {
|
function valueToKey(input: any, seen?: Set<object>): Key | Key[] {
|
||||||
if (typeof input === "number") {
|
if (typeof input === "number") {
|
||||||
if (isNaN(input)) {
|
if (isNaN(input)) {
|
||||||
throw new DataError();
|
throw new DataError();
|
||||||
}
|
|
||||||
return input;
|
|
||||||
} else if (input instanceof Date) {
|
|
||||||
const ms = input.valueOf();
|
|
||||||
if (isNaN(ms)) {
|
|
||||||
throw new DataError();
|
|
||||||
}
|
|
||||||
return new Date(ms);
|
|
||||||
} else if (typeof input === "string") {
|
|
||||||
return input;
|
|
||||||
} else if (
|
|
||||||
input instanceof ArrayBuffer ||
|
|
||||||
(typeof ArrayBuffer !== "undefined" &&
|
|
||||||
ArrayBuffer.isView &&
|
|
||||||
ArrayBuffer.isView(input))
|
|
||||||
) {
|
|
||||||
if (input instanceof ArrayBuffer) {
|
|
||||||
return new Uint8Array(input).buffer;
|
|
||||||
}
|
|
||||||
return new Uint8Array(input.buffer).buffer;
|
|
||||||
} else if (Array.isArray(input)) {
|
|
||||||
if (seen === undefined) {
|
|
||||||
seen = new Set();
|
|
||||||
} else if (seen.has(input)) {
|
|
||||||
throw new DataError();
|
|
||||||
}
|
|
||||||
seen.add(input);
|
|
||||||
|
|
||||||
const keys = [];
|
|
||||||
for (let i = 0; i < input.length; i++) {
|
|
||||||
const hop = input.hasOwnProperty(i);
|
|
||||||
if (!hop) {
|
|
||||||
throw new DataError();
|
|
||||||
}
|
|
||||||
const entry = input[i];
|
|
||||||
const key = valueToKey(entry, seen);
|
|
||||||
keys.push(key);
|
|
||||||
}
|
|
||||||
return keys;
|
|
||||||
} else {
|
|
||||||
throw new DataError();
|
|
||||||
}
|
}
|
||||||
};
|
return input;
|
||||||
|
} else if (input instanceof Date) {
|
||||||
|
const ms = input.valueOf();
|
||||||
|
if (isNaN(ms)) {
|
||||||
|
throw new DataError();
|
||||||
|
}
|
||||||
|
return new Date(ms);
|
||||||
|
} else if (typeof input === "string") {
|
||||||
|
return input;
|
||||||
|
} else if (
|
||||||
|
input instanceof ArrayBuffer ||
|
||||||
|
(typeof ArrayBuffer !== "undefined" &&
|
||||||
|
ArrayBuffer.isView &&
|
||||||
|
ArrayBuffer.isView(input))
|
||||||
|
) {
|
||||||
|
if (input instanceof ArrayBuffer) {
|
||||||
|
return new Uint8Array(input).buffer;
|
||||||
|
}
|
||||||
|
return new Uint8Array(input.buffer).buffer;
|
||||||
|
} else if (Array.isArray(input)) {
|
||||||
|
if (seen === undefined) {
|
||||||
|
seen = new Set();
|
||||||
|
} else if (seen.has(input)) {
|
||||||
|
throw new DataError();
|
||||||
|
}
|
||||||
|
seen.add(input);
|
||||||
|
|
||||||
|
const keys = [];
|
||||||
|
for (let i = 0; i < input.length; i++) {
|
||||||
|
const hop = input.hasOwnProperty(i);
|
||||||
|
if (!hop) {
|
||||||
|
throw new DataError();
|
||||||
|
}
|
||||||
|
const entry = input[i];
|
||||||
|
const key = valueToKey(entry, seen);
|
||||||
|
keys.push(key);
|
||||||
|
}
|
||||||
|
return keys;
|
||||||
|
} else {
|
||||||
|
|
||||||
|
throw new DataError();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export default valueToKey;
|
export default valueToKey;
|
||||||
|
Loading…
Reference in New Issue
Block a user