Improve IDB error reporting
Hope this can help with https://github.com/vector-im/hydrogen-web/issues/50
This commit is contained in:
parent
991f5fee4c
commit
cc4c9d7893
3 changed files with 32 additions and 10 deletions
|
@ -39,6 +39,11 @@ export class StorageError extends Error {
|
||||||
if (typeof cause.code === "number") {
|
if (typeof cause.code === "number") {
|
||||||
fullMessage += `(code: ${cause.name}) `;
|
fullMessage += `(code: ${cause.name}) `;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
if (value) {
|
||||||
|
fullMessage += `(value: ${JSON.stringify(value)}) `;
|
||||||
|
}
|
||||||
|
if (cause) {
|
||||||
fullMessage += cause.message;
|
fullMessage += cause.message;
|
||||||
}
|
}
|
||||||
super(fullMessage);
|
super(fullMessage);
|
||||||
|
@ -48,4 +53,8 @@ export class StorageError extends Error {
|
||||||
this.cause = cause;
|
this.cause = cause;
|
||||||
this.value = value;
|
this.value = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get name() {
|
||||||
|
return "StorageError";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -114,7 +114,7 @@ export class Store extends QueryTarget {
|
||||||
return await reqAsPromise(this._idbStore.put(value));
|
return await reqAsPromise(this._idbStore.put(value));
|
||||||
} catch(err) {
|
} catch(err) {
|
||||||
const originalErr = err.cause;
|
const originalErr = err.cause;
|
||||||
throw new StorageError(`put on ${this._idbStore.name} failed`, originalErr, value);
|
throw new StorageError(`put on ${err.databaseName}.${err.storeName} failed`, originalErr, value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -123,11 +123,17 @@ export class Store extends QueryTarget {
|
||||||
return await reqAsPromise(this._idbStore.add(value));
|
return await reqAsPromise(this._idbStore.add(value));
|
||||||
} catch(err) {
|
} catch(err) {
|
||||||
const originalErr = err.cause;
|
const originalErr = err.cause;
|
||||||
throw new StorageError(`add on ${this._idbStore.name} failed`, originalErr, value);
|
throw new StorageError(`add on ${err.databaseName}.${err.storeName} failed`, originalErr, value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
delete(keyOrKeyRange) {
|
async delete(keyOrKeyRange) {
|
||||||
return reqAsPromise(this._idbStore.delete(keyOrKeyRange));
|
try {
|
||||||
|
return await reqAsPromise(this._idbStore.delete(keyOrKeyRange));
|
||||||
|
} catch(err) {
|
||||||
|
const originalErr = err.cause;
|
||||||
|
throw new StorageError(`delete on ${err.databaseName}.${err.storeName} failed`, originalErr, keyOrKeyRange);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,7 +15,18 @@ limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { StorageError } from "../common.js";
|
import { StorageError } from "../common.js";
|
||||||
|
import { readPath } from "../../../utils/validate.js";
|
||||||
|
|
||||||
|
class WrappedDOMException extends StorageError {
|
||||||
|
constructor(request) {
|
||||||
|
// protect against browsers not implementing any of these properties by using readPath
|
||||||
|
const storeName = readPath(request, ["source", "name"], "<unknown store>");
|
||||||
|
const databaseName = readPath(request, ["source", "transaction", "db", "name"], "<unknown db>");
|
||||||
|
super(`Failed IDBRequest on ${databaseName}.${storeName}`, request.error);
|
||||||
|
this.storeName = storeName;
|
||||||
|
this.databaseName = databaseName;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// storage keys are defined to be unsigned 32bit numbers in WebPlatform.js, which is assumed by idb
|
// storage keys are defined to be unsigned 32bit numbers in WebPlatform.js, which is assumed by idb
|
||||||
export function encodeUint32(n) {
|
export function encodeUint32(n) {
|
||||||
|
@ -37,21 +48,17 @@ export function openDatabase(name, createObjectStore, version) {
|
||||||
return reqAsPromise(req);
|
return reqAsPromise(req);
|
||||||
}
|
}
|
||||||
|
|
||||||
function wrapError(err) {
|
|
||||||
return new StorageError(`wrapped DOMException`, err);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function reqAsPromise(req) {
|
export function reqAsPromise(req) {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
req.addEventListener("success", event => resolve(event.target.result));
|
req.addEventListener("success", event => resolve(event.target.result));
|
||||||
req.addEventListener("error", event => reject(wrapError(event.target.error)));
|
req.addEventListener("error", event => reject(new WrappedDOMException(event.target)));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
export function txnAsPromise(txn) {
|
export function txnAsPromise(txn) {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
txn.addEventListener("complete", resolve);
|
txn.addEventListener("complete", resolve);
|
||||||
txn.addEventListener("abort", event => reject(wrapError(event.target.error)));
|
txn.addEventListener("abort", event => reject(new WrappedDOMException(event.target)));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Reference in a new issue