forked from mystiq/hydrogen-web
detect the webkit bug, and await a bogus request when opening a txn
This commit is contained in:
parent
e0d14207ac
commit
932d26ed8c
3 changed files with 60 additions and 2 deletions
|
@ -16,10 +16,14 @@ limitations under the License.
|
|||
|
||||
import {Transaction} from "./Transaction.js";
|
||||
import { STORE_NAMES, StorageError } from "../common.js";
|
||||
import { reqAsPromise } from "./utils.js";
|
||||
|
||||
const WEBKITEARLYCLOSETXNBUG_BOGUS_KEY = "782rh281re38-boguskey";
|
||||
|
||||
export class Storage {
|
||||
constructor(idbDatabase) {
|
||||
constructor(idbDatabase, hasWebkitEarlyCloseTxnBug) {
|
||||
this._db = idbDatabase;
|
||||
this._hasWebkitEarlyCloseTxnBug = hasWebkitEarlyCloseTxnBug;
|
||||
const nameMap = STORE_NAMES.reduce((nameMap, name) => {
|
||||
nameMap[name] = name;
|
||||
return nameMap;
|
||||
|
@ -38,6 +42,11 @@ export class Storage {
|
|||
this._validateStoreNames(storeNames);
|
||||
try {
|
||||
const txn = this._db.transaction(storeNames, "readonly");
|
||||
// https://bugs.webkit.org/show_bug.cgi?id=222746 workaround,
|
||||
// await a bogus idb request on the new txn so it doesn't close early if we await a microtask first
|
||||
if (this._hasWebkitEarlyCloseTxnBug) {
|
||||
await reqAsPromise(txn.objectStore(storeNames[0]).get(WEBKITEARLYCLOSETXNBUG_BOGUS_KEY));
|
||||
}
|
||||
return new Transaction(txn, storeNames);
|
||||
} catch(err) {
|
||||
throw new StorageError("readTxn failed", err);
|
||||
|
@ -48,6 +57,11 @@ export class Storage {
|
|||
this._validateStoreNames(storeNames);
|
||||
try {
|
||||
const txn = this._db.transaction(storeNames, "readwrite");
|
||||
// https://bugs.webkit.org/show_bug.cgi?id=222746 workaround,
|
||||
// await a bogus idb request on the new txn so it doesn't close early if we await a microtask first
|
||||
if (this._hasWebkitEarlyCloseTxnBug) {
|
||||
await reqAsPromise(txn.objectStore(storeNames[0]).get(WEBKITEARLYCLOSETXNBUG_BOGUS_KEY));
|
||||
}
|
||||
return new Transaction(txn, storeNames);
|
||||
} catch(err) {
|
||||
throw new StorageError("readWriteTxn failed", err);
|
||||
|
|
|
@ -18,6 +18,7 @@ import {Storage} from "./Storage.js";
|
|||
import { openDatabase, reqAsPromise } from "./utils.js";
|
||||
import { exportSession, importSession } from "./export.js";
|
||||
import { schema } from "./schema.js";
|
||||
import { detectWebkitEarlyCloseTxnBug } from "./quirks.js";
|
||||
|
||||
const sessionName = sessionId => `hydrogen_session_${sessionId}`;
|
||||
const openDatabaseWithSessionId = sessionId => openDatabase(sessionName(sessionId), createStores, schema.length);
|
||||
|
@ -50,8 +51,10 @@ export class StorageFactory {
|
|||
console.warn("no persisted storage, database can be evicted by browser");
|
||||
}
|
||||
});
|
||||
|
||||
const hasWebkitEarlyCloseTxnBug = await detectWebkitEarlyCloseTxnBug();
|
||||
const db = await openDatabaseWithSessionId(sessionId);
|
||||
return new Storage(db);
|
||||
return new Storage(db, hasWebkitEarlyCloseTxnBug);
|
||||
}
|
||||
|
||||
delete(sessionId) {
|
||||
|
|
41
src/matrix/storage/idb/quirks.js
Normal file
41
src/matrix/storage/idb/quirks.js
Normal file
|
@ -0,0 +1,41 @@
|
|||
/*
|
||||
Copyright 2020 The Matrix.org Foundation C.I.C.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
|
||||
import {openDatabase, txnAsPromise, reqAsPromise} from "./utils.js";
|
||||
|
||||
// filed as https://bugs.webkit.org/show_bug.cgi?id=222746
|
||||
export async function detectWebkitEarlyCloseTxnBug() {
|
||||
const dbName = "hydrogen_webkit_test_inactive_txn_bug";
|
||||
try {
|
||||
const db = await openDatabase(dbName, db => {
|
||||
db.createObjectStore("test", {keyPath: "key"});
|
||||
}, 1);
|
||||
const readTxn = db.transaction(["test"], "readonly");
|
||||
await reqAsPromise(readTxn.objectStore("test").get("somekey"));
|
||||
// schedule a macro task in between the two txns
|
||||
await new Promise(r => setTimeout(r, 0));
|
||||
const writeTxn = db.transaction(["test"], "readwrite");
|
||||
await Promise.resolve();
|
||||
writeTxn.objectStore("test").add({key: "somekey", value: "foo"});
|
||||
await txnAsPromise(writeTxn);
|
||||
} catch (err) {
|
||||
if (err.name === "TransactionInactiveError") {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
Loading…
Reference in a new issue