History

Sanity-check decaffeinate app.DB

Simon Legner committed 2 years ago

Commit 8103c281 parent dc3dd671 file · +458 −486Browse files

Unified · Split

assets/javascripts/app/db.js+458−486
@@ -1,587 +1,559 @@
1−// TODO: This file was created by bulk-decaffeinate.
2−// Sanity-check the conversion and remove this comment.
3−/*
4− * decaffeinate suggestions:
5− * DS101: Remove unnecessary use of Array.from
6− * DS102: Remove unnecessary code created because of implicit returns
7− * DS205: Consider reworking code to avoid use of IIFEs
8− * DS206: Consider reworking classes to avoid initClass
9− * DS207: Consider shorter variations of null checks
10− * Full docs: https://github.com/decaffeinate/decaffeinate/blob/main/docs/suggestions.md
11− */
12−(function () {
13− let NAME = undefined;
14− let VERSION = undefined;
15− app.DB = class DB {
16− static initClass() {
17− NAME = "docs";
18− VERSION = 15;
1+app.DB = class DB {
2+ static NAME = "docs";
3+ static VERSION = 15;
4+
5+ constructor() {
6+ this.versionMultipler = $.isIE() ? 1e5 : 1e9;
7+ this.useIndexedDB = this.useIndexedDB();
8+ this.callbacks = [];
9+ }
10+
11+ db(fn) {
12+ if (!this.useIndexedDB) {
13+ return fn();
14+ }
15+ if (fn) {
16+ this.callbacks.push(fn);
17+ }
18+ if (this.open) {
19+ return;
1920 }
2021
21− constructor() {
22− this.versionMultipler = $.isIE() ? 1e5 : 1e9;
23− this.useIndexedDB = this.useIndexedDB();
24− this.callbacks = [];
22+ try {
23+ this.open = true;
24+ const req = indexedDB.open(
25+ DB.NAME,
26+ DB.VERSION * this.versionMultipler + this.userVersion(),
27+ );
28+ req.onsuccess = (event) => this.onOpenSuccess(event);
29+ req.onerror = (event) => this.onOpenError(event);
30+ req.onupgradeneeded = (event) => this.onUpgradeNeeded(event);
31+ } catch (error) {
32+ this.fail("exception", error);
2533 }
34+ }
2635
27− db(fn) {
28− if (!this.useIndexedDB) {
29− return fn();
30− }
31− if (fn) {
32− this.callbacks.push(fn);
33− }
34− if (this.open) {
35− return;
36− }
36+ onOpenSuccess(event) {
37+ let error;
38+ const db = event.target.result;
3739
40+ if (db.objectStoreNames.length === 0) {
3841 try {
39− this.open = true;
40− const req = indexedDB.open(
41− NAME,
42− VERSION * this.versionMultipler + this.userVersion(),
43− );
44− req.onsuccess = (event) => this.onOpenSuccess(event);
45− req.onerror = (event) => this.onOpenError(event);
46− req.onupgradeneeded = (event) => this.onUpgradeNeeded(event);
47− } catch (error) {
48− this.fail("exception", error);
49− }
42+ db.close();
43+ } catch (error1) {}
44+ this.open = false;
45+ this.fail("empty");
46+ } else if ((error = this.buggyIDB(db))) {
47+ try {
48+ db.close();
49+ } catch (error2) {}
50+ this.open = false;
51+ this.fail("buggy", error);
52+ } else {
53+ this.runCallbacks(db);
54+ this.open = false;
55+ db.close();
5056 }
57+ }
58+
59+ onOpenError(event) {
60+ event.preventDefault();
61+ this.open = false;
62+ const { error } = event.target;
63+
64+ switch (error.name) {
65+ case "QuotaExceededError":
66+ this.onQuotaExceededError();
67+ break;
68+ case "VersionError":
69+ this.onVersionError();
70+ break;
71+ case "InvalidStateError":
72+ this.fail("private_mode");
73+ break;
74+ default:
75+ this.fail("cant_open", error);
76+ }
77+ }
5178
52− onOpenSuccess(event) {
53− let error;
54− const db = event.target.result;
55−
56− if (db.objectStoreNames.length === 0) {
57− try {
58− db.close();
59− } catch (error1) {}
60− this.open = false;
61− this.fail("empty");
62− } else if ((error = this.buggyIDB(db))) {
63− try {
64− db.close();
65− } catch (error2) {}
66− this.open = false;
67− this.fail("buggy", error);
68− } else {
69− this.runCallbacks(db);
70− this.open = false;
71− db.close();
79+ fail(reason, error) {
80+ this.cachedDocs = null;
81+ this.useIndexedDB = false;
82+ if (!this.reason) {
83+ this.reason = reason;
84+ }
85+ if (!this.error) {
86+ this.error = error;
87+ }
88+ if (error) {
89+ if (typeof console.error === "function") {
90+ console.error("IDB error", error);
7291 }
7392 }
74−
75− onOpenError(event) {
93+ this.runCallbacks();
94+ if (error && reason === "cant_open") {
95+ Raven.captureMessage(`${error.name}: ${error.message}`, {
96+ level: "warning",
97+ fingerprint: [error.name],
98+ });
99+ }
100+ }
101+
102+ onQuotaExceededError() {
103+ this.reset();
104+ this.db();
105+ app.onQuotaExceeded();
106+ Raven.captureMessage("QuotaExceededError", { level: "warning" });
107+ }
108+
109+ onVersionError() {
110+ const req = indexedDB.open(DB.NAME);
111+ req.onsuccess = (event) => {
112+ return this.handleVersionMismatch(event.target.result.version);
113+ };
114+ req.onerror = function (event) {
76115 event.preventDefault();
77− this.open = false;
78− const { error } = event.target;
79−
80− switch (error.name) {
81− case "QuotaExceededError":
82− this.onQuotaExceededError();
83− break;
84− case "VersionError":
85− this.onVersionError();
86− break;
87− case "InvalidStateError":
88− this.fail("private_mode");
89− break;
90− default:
91− this.fail("cant_open", error);
92− }
116+ return this.fail("cant_open", error);
117+ };
118+ }
119+
120+ handleVersionMismatch(actualVersion) {
121+ if (Math.floor(actualVersion / this.versionMultipler) !== DB.VERSION) {
122+ this.fail("version");
123+ } else {
124+ this.setUserVersion(actualVersion - DB.VERSION * this.versionMultipler);
125+ this.db();
93126 }
127+ }
94128
95− fail(reason, error) {
96− this.cachedDocs = null;
97− this.useIndexedDB = false;
98− if (!this.reason) {
99− this.reason = reason;
100− }
101− if (!this.error) {
102− this.error = error;
103− }
104− if (error) {
105− if (typeof console.error === "function") {
106− console.error("IDB error", error);
107− }
108− }
109− this.runCallbacks();
110− if (error && reason === "cant_open") {
111− Raven.captureMessage(`${error.name}: ${error.message}`, {
112− level: "warning",
113− fingerprint: [error.name],
114− });
115− }
129+ buggyIDB(db) {
130+ if (this.checkedBuggyIDB) {
131+ return;
116132 }
117−
118− onQuotaExceededError() {
119− this.reset();
120− this.db();
121− app.onQuotaExceeded();
122− Raven.captureMessage("QuotaExceededError", { level: "warning" });
133+ this.checkedBuggyIDB = true;
134+ try {
135+ this.idbTransaction(db, {
136+ stores: $.makeArray(db.objectStoreNames).slice(0, 2),
137+ mode: "readwrite",
138+ }).abort(); // https://bugs.webkit.org/show_bug.cgi?id=136937
139+ return;
140+ } catch (error) {
141+ return error;
123142 }
143+ }
124144
125− onVersionError() {
126− const req = indexedDB.open(NAME);
127− req.onsuccess = (event) => {
128− return this.handleVersionMismatch(event.target.result.version);
129− };
130− req.onerror = function (event) {
131− event.preventDefault();
132− return this.fail("cant_open", error);
133− };
145+ runCallbacks(db) {
146+ let fn;
147+ while ((fn = this.callbacks.shift())) {
148+ fn(db);
134149 }
150+ }
135151
136− handleVersionMismatch(actualVersion) {
137− if (Math.floor(actualVersion / this.versionMultipler) !== VERSION) {
138− this.fail("version");
139− } else {
140− this.setUserVersion(actualVersion - VERSION * this.versionMultipler);
141− this.db();
142− }
152+ onUpgradeNeeded(event) {
153+ let db;
154+ if (!(db = event.target.result)) {
155+ return;
143156 }
144157
145− buggyIDB(db) {
146− if (this.checkedBuggyIDB) {
147− return;
148− }
149− this.checkedBuggyIDB = true;
158+ const objectStoreNames = $.makeArray(db.objectStoreNames);
159+
160+ if (!$.arrayDelete(objectStoreNames, "docs")) {
150161 try {
151− this.idbTransaction(db, {
152− stores: $.makeArray(db.objectStoreNames).slice(0, 2),
153− mode: "readwrite",
154− }).abort(); // https://bugs.webkit.org/show_bug.cgi?id=136937
155− return;
156− } catch (error) {
157− return error;
158− }
162+ db.createObjectStore("docs");
163+ } catch (error) {}
159164 }
160165
161− runCallbacks(db) {
162− let fn;
163− while ((fn = this.callbacks.shift())) {
164− fn(db);
166+ for (var doc of app.docs.all()) {
167+ if (!$.arrayDelete(objectStoreNames, doc.slug)) {
168+ try {
169+ db.createObjectStore(doc.slug);
170+ } catch (error1) {}
165171 }
166172 }
167173
168− onUpgradeNeeded(event) {
169− let db;
170− if (!(db = event.target.result)) {
174+ for (var name of objectStoreNames) {
175+ try {
176+ db.deleteObjectStore(name);
177+ } catch (error2) {}
178+ }
179+ }
180+
181+ store(doc, data, onSuccess, onError, _retry) {
182+ if (_retry == null) {
183+ _retry = true;
184+ }
185+ this.db((db) => {
186+ if (!db) {
187+ onError();
171188 return;
172189 }
173190
174− const objectStoreNames = $.makeArray(db.objectStoreNames);
191+ const txn = this.idbTransaction(db, {
192+ stores: ["docs", doc.slug],
193+ mode: "readwrite",
194+ ignoreError: false,
195+ });
196+ txn.oncomplete = () => {
197+ if (this.cachedDocs != null) {
198+ this.cachedDocs[doc.slug] = doc.mtime;
199+ }
200+ onSuccess();
201+ };
202+ txn.onerror = (event) => {
203+ event.preventDefault();
204+ if (txn.error?.name === "NotFoundError" && _retry) {
205+ this.migrate();
206+ setTimeout(() => {
207+ return this.store(doc, data, onSuccess, onError, false);
208+ }, 0);
209+ } else {
210+ onError(event);
211+ }
212+ };
175213
176− if (!$.arrayDelete(objectStoreNames, "docs")) {
177− try {
178− db.createObjectStore("docs");
179− } catch (error) {}
214+ let store = txn.objectStore(doc.slug);
215+ store.clear();
216+ for (var path in data) {
217+ var content = data[path];
218+ store.add(content, path);
180219 }
181220
182− for (var doc of Array.from(app.docs.all())) {
183− if (!$.arrayDelete(objectStoreNames, doc.slug)) {
184− try {
185− db.createObjectStore(doc.slug);
186− } catch (error1) {}
187− }
188− }
221+ store = txn.objectStore("docs");
222+ store.put(doc.mtime, doc.slug);
223+ });
224+ }
189225
190− for (var name of Array.from(objectStoreNames)) {
191− try {
192− db.deleteObjectStore(name);
193− } catch (error2) {}
194− }
226+ unstore(doc, onSuccess, onError, _retry) {
227+ if (_retry == null) {
228+ _retry = true;
195229 }
196−
197− store(doc, data, onSuccess, onError, _retry) {
198− if (_retry == null) {
199− _retry = true;
230+ this.db((db) => {
231+ if (!db) {
232+ onError();
233+ return;
200234 }
201− this.db((db) => {
202− if (!db) {
203− onError();
204− return;
235+
236+ const txn = this.idbTransaction(db, {
237+ stores: ["docs", doc.slug],
238+ mode: "readwrite",
239+ ignoreError: false,
240+ });
241+ txn.oncomplete = () => {
242+ if (this.cachedDocs != null) {
243+ delete this.cachedDocs[doc.slug];
244+ }
245+ onSuccess();
246+ };
247+ txn.onerror = function (event) {
248+ event.preventDefault();
249+ if (txn.error?.name === "NotFoundError" && _retry) {
250+ this.migrate();
251+ setTimeout(() => {
252+ return this.unstore(doc, onSuccess, onError, false);
253+ }, 0);
254+ } else {
255+ onError(event);
205256 }
257+ };
206258
207− const txn = this.idbTransaction(db, {
208− stores: ["docs", doc.slug],
209− mode: "readwrite",
210− ignoreError: false,
211− });
212− txn.oncomplete = () => {
213− if (this.cachedDocs != null) {
214− this.cachedDocs[doc.slug] = doc.mtime;
215− }
216− onSuccess();
217− };
218− txn.onerror = (event) => {
219− event.preventDefault();
220− if (
221− (txn.error != null ? txn.error.name : undefined) ===
222− "NotFoundError" &&
223− _retry
224− ) {
225− this.migrate();
226− setTimeout(() => {
227− return this.store(doc, data, onSuccess, onError, false);
228− }, 0);
229− } else {
230− onError(event);
231− }
232− };
259+ let store = txn.objectStore("docs");
260+ store.delete(doc.slug);
233261
234− let store = txn.objectStore(doc.slug);
235− store.clear();
236− for (var path in data) {
237− var content = data[path];
238− store.add(content, path);
239− }
262+ store = txn.objectStore(doc.slug);
263+ store.clear();
264+ });
265+ }
240266
241− store = txn.objectStore("docs");
242− store.put(doc.mtime, doc.slug);
243− });
267+ version(doc, fn) {
268+ let version = this.cachedVersion(doc);
269+ if (version != null) {
270+ fn(version);
271+ return;
244272 }
245273
246− unstore(doc, onSuccess, onError, _retry) {
247− if (_retry == null) {
248− _retry = true;
274+ this.db((db) => {
275+ if (!db) {
276+ fn(false);
277+ return;
249278 }
250− this.db((db) => {
251− if (!db) {
252− onError();
253− return;
254− }
255279
256− const txn = this.idbTransaction(db, {
257− stores: ["docs", doc.slug],
258− mode: "readwrite",
259− ignoreError: false,
260− });
261− txn.oncomplete = () => {
262− if (this.cachedDocs != null) {
263− delete this.cachedDocs[doc.slug];
264− }
265− onSuccess();
266− };
267− txn.onerror = function (event) {
268− event.preventDefault();
269− if (
270− (txn.error != null ? txn.error.name : undefined) ===
271− "NotFoundError" &&
272− _retry
273− ) {
274− this.migrate();
275− setTimeout(() => {
276− return this.unstore(doc, onSuccess, onError, false);
277− }, 0);
278− } else {
279− onError(event);
280− }
281− };
280+ const txn = this.idbTransaction(db, {
281+ stores: ["docs"],
282+ mode: "readonly",
283+ });
284+ const store = txn.objectStore("docs");
282285
283− let store = txn.objectStore("docs");
284− store.delete(doc.slug);
286+ const req = store.get(doc.slug);
287+ req.onsuccess = function () {
288+ fn(req.result);
289+ };
290+ req.onerror = function (event) {
291+ event.preventDefault();
292+ fn(false);
293+ };
294+ });
295+ }
285296
286− store = txn.objectStore(doc.slug);
287− store.clear();
288− });
297+ cachedVersion(doc) {
298+ if (!this.cachedDocs) {
299+ return;
300+ }
301+ return this.cachedDocs[doc.slug] || false;
302+ }
303+
304+ versions(docs, fn) {
305+ let versions = this.cachedVersions(docs);
306+ if (versions) {
307+ fn(versions);
308+ return;
289309 }
290310
291− version(doc, fn) {
292− let version;
293− if ((version = this.cachedVersion(doc)) != null) {
294− fn(version);
311+ return this.db((db) => {
312+ if (!db) {
313+ fn(false);
295314 return;
296315 }
297316
298− this.db((db) => {
299− if (!db) {
300− fn(false);
301− return;
302− }
303−
304− const txn = this.idbTransaction(db, {
305− stores: ["docs"],
306− mode: "readonly",
307− });
308− const store = txn.objectStore("docs");
317+ const txn = this.idbTransaction(db, {
318+ stores: ["docs"],
319+ mode: "readonly",
320+ });
321+ txn.oncomplete = function () {
322+ fn(result);
323+ };
324+ const store = txn.objectStore("docs");
325+ var result = {};
309326
327+ docs.forEach(function (doc) {
310328 const req = store.get(doc.slug);
311329 req.onsuccess = function () {
312− fn(req.result);
330+ result[doc.slug] = req.result;
313331 };
314332 req.onerror = function (event) {
315333 event.preventDefault();
316− fn(false);
334+ result[doc.slug] = false;
317335 };
318336 });
319− }
337+ });
338+ }
320339
321− cachedVersion(doc) {
322− if (!this.cachedDocs) {
323− return;
324− }
325− return this.cachedDocs[doc.slug] || false;
340+ cachedVersions(docs) {
341+ if (!this.cachedDocs) {
342+ return;
326343 }
327−
328− versions(docs, fn) {
329− let versions;
330− if ((versions = this.cachedVersions(docs))) {
331− fn(versions);
332− return;
333− }
334−
335− return this.db((db) => {
336− if (!db) {
337− fn(false);
338− return;
339− }
340−
341− const txn = this.idbTransaction(db, {
342− stores: ["docs"],
343− mode: "readonly",
344− });
345− txn.oncomplete = function () {
346− fn(result);
347− };
348− const store = txn.objectStore("docs");
349− var result = {};
350−
351− docs.forEach(function (doc) {
352− const req = store.get(doc.slug);
353− req.onsuccess = function () {
354− result[doc.slug] = req.result;
355− };
356− req.onerror = function (event) {
357− event.preventDefault();
358− result[doc.slug] = false;
359− };
360− });
361− });
344+ const result = {};
345+ for (var doc of docs) {
346+ result[doc.slug] = this.cachedVersion(doc);
362347 }
348+ return result;
349+ }
363350
364− cachedVersions(docs) {
365− if (!this.cachedDocs) {
366− return;
367− }
368− const result = {};
369− for (var doc of Array.from(docs)) {
370− result[doc.slug] = this.cachedVersion(doc);
371− }
372− return result;
351+ load(entry, onSuccess, onError) {
352+ if (this.shouldLoadWithIDB(entry)) {
353+ return this.loadWithIDB(entry, onSuccess, () =>
354+ this.loadWithXHR(entry, onSuccess, onError),
355+ );
356+ } else {
357+ return this.loadWithXHR(entry, onSuccess, onError);
373358 }
374−
375− load(entry, onSuccess, onError) {
376− if (this.shouldLoadWithIDB(entry)) {
377− return this.loadWithIDB(entry, onSuccess, () => this.loadWithXHR(entry, onSuccess, onError));
378− } else {
379− return this.loadWithXHR(entry, onSuccess, onError);
359+ }
360+
361+ loadWithXHR(entry, onSuccess, onError) {
362+ return ajax({
363+ url: entry.fileUrl(),
364+ dataType: "html",
365+ success: onSuccess,
366+ error: onError,
367+ });
368+ }
369+
370+ loadWithIDB(entry, onSuccess, onError) {
371+ return this.db((db) => {
372+ if (!db) {
373+ onError();
374+ return;
380375 }
381− }
382376
383− loadWithXHR(entry, onSuccess, onError) {
384− return ajax({
385− url: entry.fileUrl(),
386− dataType: "html",
387− success: onSuccess,
388− error: onError,
389− });
390− }
391−
392− loadWithIDB(entry, onSuccess, onError) {
393− return this.db((db) => {
394− if (!db) {
395− onError();
396− return;
397− }
398−
399− if (!db.objectStoreNames.contains(entry.doc.slug)) {
400− onError();
401− this.loadDocsCache(db);
402− return;
403− }
404−
405− const txn = this.idbTransaction(db, {
406− stores: [entry.doc.slug],
407− mode: "readonly",
408− });
409− const store = txn.objectStore(entry.doc.slug);
410−
411− const req = store.get(entry.dbPath());
412− req.onsuccess = function () {
413− if (req.result) {
414− onSuccess(req.result);
415− } else {
416− onError();
417− }
418− };
419− req.onerror = function (event) {
420− event.preventDefault();
421− onError();
422− };
377+ if (!db.objectStoreNames.contains(entry.doc.slug)) {
378+ onError();
423379 this.loadDocsCache(db);
424− });
425− }
426−
427− loadDocsCache(db) {
428− if (this.cachedDocs) {
429380 return;
430381 }
431− this.cachedDocs = {};
432382
433383 const txn = this.idbTransaction(db, {
434− stores: ["docs"],
384+ stores: [entry.doc.slug],
435385 mode: "readonly",
436386 });
437− txn.oncomplete = () => {
438− setTimeout(() => this.checkForCorruptedDocs(), 50);
439− };
387+ const store = txn.objectStore(entry.doc.slug);
440388
441− const req = txn.objectStore("docs").openCursor();
442− req.onsuccess = (event) => {
443− let cursor;
444− if (!(cursor = event.target.result)) {
445− return;
389+ const req = store.get(entry.dbPath());
390+ req.onsuccess = function () {
391+ if (req.result) {
392+ onSuccess(req.result);
393+ } else {
394+ onError();
446395 }
447− this.cachedDocs[cursor.key] = cursor.value;
448− cursor.continue();
449396 };
450397 req.onerror = function (event) {
451398 event.preventDefault();
399+ onError();
452400 };
453− }
401+ this.loadDocsCache(db);
402+ });
403+ }
454404
455− checkForCorruptedDocs() {
456− this.db((db) => {
457− let slug;
458− this.corruptedDocs = [];
459− const docs = (() => {
460− const result = [];
461− for (var key in this.cachedDocs) {
462− var value = this.cachedDocs[key];
463− if (value) {
464− result.push(key);
465− }
405+ loadDocsCache(db) {
406+ if (this.cachedDocs) {
407+ return;
408+ }
409+ this.cachedDocs = {};
410+
411+ const txn = this.idbTransaction(db, {
412+ stores: ["docs"],
413+ mode: "readonly",
414+ });
415+ txn.oncomplete = () => {
416+ setTimeout(() => this.checkForCorruptedDocs(), 50);
417+ };
418+
419+ const req = txn.objectStore("docs").openCursor();
420+ req.onsuccess = (event) => {
421+ let cursor;
422+ if (!(cursor = event.target.result)) {
423+ return;
424+ }
425+ this.cachedDocs[cursor.key] = cursor.value;
426+ cursor.continue();
427+ };
428+ req.onerror = function (event) {
429+ event.preventDefault();
430+ };
431+ }
432+
433+ checkForCorruptedDocs() {
434+ this.db((db) => {
435+ let slug;
436+ this.corruptedDocs = [];
437+ const docs = (() => {
438+ const result = [];
439+ for (var key in this.cachedDocs) {
440+ var value = this.cachedDocs[key];
441+ if (value) {
442+ result.push(key);
466443 }
467− return result;
468− })();
469− if (docs.length === 0) {
470− return;
471444 }
445+ return result;
446+ })();
447+ if (docs.length === 0) {
448+ return;
449+ }
472450
473− for (slug of Array.from(docs)) {
474− if (!app.docs.findBy("slug", slug)) {
475− this.corruptedDocs.push(slug);
476− }
451+ for (slug of docs) {
452+ if (!app.docs.findBy("slug", slug)) {
453+ this.corruptedDocs.push(slug);
477454 }
455+ }
478456
479− for (slug of Array.from(this.corruptedDocs)) {
480− $.arrayDelete(docs, slug);
481− }
457+ for (slug of this.corruptedDocs) {
458+ $.arrayDelete(docs, slug);
459+ }
460+
461+ if (docs.length === 0) {
462+ setTimeout(() => this.deleteCorruptedDocs(), 0);
463+ return;
464+ }
482465
483− if (docs.length === 0) {
466+ const txn = this.idbTransaction(db, {
467+ stores: docs,
468+ mode: "readonly",
469+ ignoreError: false,
470+ });
471+ txn.oncomplete = () => {
472+ if (this.corruptedDocs.length > 0) {
484473 setTimeout(() => this.deleteCorruptedDocs(), 0);
485− return;
486474 }
475+ };
487476
488− const txn = this.idbTransaction(db, {
489− stores: docs,
490− mode: "readonly",
491− ignoreError: false,
492− });
493− txn.oncomplete = () => {
494− if (this.corruptedDocs.length > 0) {
495− setTimeout(() => this.deleteCorruptedDocs(), 0);
477+ for (var doc of docs) {
478+ txn.objectStore(doc).get("index").onsuccess = (event) => {
479+ if (!event.target.result) {
480+ this.corruptedDocs.push(event.target.source.name);
496481 }
497482 };
483+ }
484+ });
485+ }
498486
499− for (var doc of Array.from(docs)) {
500− txn.objectStore(doc).get("index").onsuccess = (event) => {
501− if (!event.target.result) {
502− this.corruptedDocs.push(event.target.source.name);
503− }
504− };
505− }
506− });
507− }
508−
509− deleteCorruptedDocs() {
510− this.db((db) => {
511− let doc;
512− const txn = this.idbTransaction(db, {
513− stores: ["docs"],
514− mode: "readwrite",
515− ignoreError: false,
516− });
517− const store = txn.objectStore("docs");
518− while ((doc = this.corruptedDocs.pop())) {
519− this.cachedDocs[doc] = false;
520− store.delete(doc);
521− }
522− });
523− Raven.captureMessage("corruptedDocs", {
524− level: "info",
525− extra: { docs: this.corruptedDocs.join(",") },
487+ deleteCorruptedDocs() {
488+ this.db((db) => {
489+ let doc;
490+ const txn = this.idbTransaction(db, {
491+ stores: ["docs"],
492+ mode: "readwrite",
493+ ignoreError: false,
526494 });
527− }
528−
529− shouldLoadWithIDB(entry) {
530− return (
531− this.useIndexedDB &&
532− (!this.cachedDocs || this.cachedDocs[entry.doc.slug])
533− );
534− }
535−
536− idbTransaction(db, options) {
537− app.lastIDBTransaction = [options.stores, options.mode];
538− const txn = db.transaction(options.stores, options.mode);
539− if (options.ignoreError !== false) {
540− txn.onerror = function (event) {
541− event.preventDefault();
542− };
495+ const store = txn.objectStore("docs");
496+ while ((doc = this.corruptedDocs.pop())) {
497+ this.cachedDocs[doc] = false;
498+ store.delete(doc);
543499 }
544− if (options.ignoreAbort !== false) {
545− txn.onabort = function (event) {
546− event.preventDefault();
547− };
548− }
549− return txn;
500+ });
501+ Raven.captureMessage("corruptedDocs", {
502+ level: "info",
503+ extra: { docs: this.corruptedDocs.join(",") },
504+ });
505+ }
506+
507+ shouldLoadWithIDB(entry) {
508+ return (
509+ this.useIndexedDB && (!this.cachedDocs || this.cachedDocs[entry.doc.slug])
510+ );
511+ }
512+
513+ idbTransaction(db, options) {
514+ app.lastIDBTransaction = [options.stores, options.mode];
515+ const txn = db.transaction(options.stores, options.mode);
516+ if (options.ignoreError !== false) {
517+ txn.onerror = function (event) {
518+ event.preventDefault();
519+ };
550520 }
551−
552− reset() {
553− try {
554− if (typeof indexedDB !== "undefined" && indexedDB !== null) {
555− indexedDB.deleteDatabase(NAME);
556− }
557− } catch (error) {}
521+ if (options.ignoreAbort !== false) {
522+ txn.onabort = function (event) {
523+ event.preventDefault();
524+ };
558525 }
559−
560− useIndexedDB() {
561− try {
562− if (!app.isSingleDoc() && window.indexedDB) {
563− return true;
564− } else {
565− this.reason = "not_supported";
566− return false;
567− }
568− } catch (error) {
526+ return txn;
527+ }
528+
529+ reset() {
530+ try {
531+ indexedDB?.deleteDatabase(DB.NAME);
532+ } catch (error) {}
533+ }
534+
535+ useIndexedDB() {
536+ try {
537+ if (!app.isSingleDoc() && window.indexedDB) {
538+ return true;
539+ } else {
540+ this.reason = "not_supported";
569541 return false;
570542 }
543+ } catch (error) {
544+ return false;
571545 }
546+ }
572547
573− migrate() {
574− app.settings.set("schema", this.userVersion() + 1);
575− }
548+ migrate() {
549+ app.settings.set("schema", this.userVersion() + 1);
550+ }
576551
577− setUserVersion(version) {
578− app.settings.set("schema", version);
579− }
552+ setUserVersion(version) {
553+ app.settings.set("schema", version);
554+ }
580555
581− userVersion() {
582− return app.settings.get("schema");
583− }
584− };
585− app.DB.initClass();
586− return app.DB;
587−})();
556+ userVersion() {
557+ return app.settings.get("schema");
558+ }
559+};