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.1app.DB = class DB {
2// Sanity-check the conversion and remove this comment.2 static NAME = "docs";
3/*3 static VERSION = 15;
4 * decaffeinate suggestions:4
5 * DS101: Remove unnecessary use of Array.from5 constructor() {
6 * DS102: Remove unnecessary code created because of implicit returns6 this.versionMultipler = $.isIE() ? 1e5 : 1e9;
7 * DS205: Consider reworking code to avoid use of IIFEs7 this.useIndexedDB = this.useIndexedDB();
8 * DS206: Consider reworking classes to avoid initClass8 this.callbacks = [];
9 * DS207: Consider shorter variations of null checks9 }
10 * Full docs: https://github.com/decaffeinate/decaffeinate/blob/main/docs/suggestions.md10
11 */11 db(fn) {
12(function () {12 if (!this.useIndexedDB) {
13 let NAME = undefined;13 return fn();
14 let VERSION = undefined;14 }
15 app.DB = class DB {15 if (fn) {
16 static initClass() {16 this.callbacks.push(fn);
17 NAME = "docs";17 }
18 VERSION = 15;18 if (this.open) {
19 return;
19 }20 }
20 21
21 constructor() {22 try {
22 this.versionMultipler = $.isIE() ? 1e5 : 1e9;23 this.open = true;
23 this.useIndexedDB = this.useIndexedDB();24 const req = indexedDB.open(
24 this.callbacks = [];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);
25 }33 }
34 }
26 35
27 db(fn) {36 onOpenSuccess(event) {
28 if (!this.useIndexedDB) {37 let error;
29 return fn();38 const db = event.target.result;
30 }
31 if (fn) {
32 this.callbacks.push(fn);
33 }
34 if (this.open) {
35 return;
36 }
37 39
40 if (db.objectStoreNames.length === 0) {
38 try {41 try {
39 this.open = true;42 db.close();
40 const req = indexedDB.open(43 } catch (error1) {}
41 NAME,44 this.open = false;
42 VERSION * this.versionMultipler + this.userVersion(),45 this.fail("empty");
43 );46 } else if ((error = this.buggyIDB(db))) {
44 req.onsuccess = (event) => this.onOpenSuccess(event);47 try {
45 req.onerror = (event) => this.onOpenError(event);48 db.close();
46 req.onupgradeneeded = (event) => this.onUpgradeNeeded(event);49 } catch (error2) {}
47 } catch (error) {50 this.open = false;
48 this.fail("exception", error);51 this.fail("buggy", error);
49 }52 } else {
53 this.runCallbacks(db);
54 this.open = false;
55 db.close();
50 }56 }
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 }
51 78
52 onOpenSuccess(event) {79 fail(reason, error) {
53 let error;80 this.cachedDocs = null;
54 const db = event.target.result;81 this.useIndexedDB = false;
55 82 if (!this.reason) {
56 if (db.objectStoreNames.length === 0) {83 this.reason = reason;
57 try {84 }
58 db.close();85 if (!this.error) {
59 } catch (error1) {}86 this.error = error;
60 this.open = false;87 }
61 this.fail("empty");88 if (error) {
62 } else if ((error = this.buggyIDB(db))) {89 if (typeof console.error === "function") {
63 try {90 console.error("IDB error", error);
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();
72 }91 }
73 }92 }
74 93 this.runCallbacks();
75 onOpenError(event) {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) {
76 event.preventDefault();115 event.preventDefault();
77 this.open = false;116 return this.fail("cant_open", error);
78 const { error } = event.target;117 };
79 118 }
80 switch (error.name) {119
81 case "QuotaExceededError":120 handleVersionMismatch(actualVersion) {
82 this.onQuotaExceededError();121 if (Math.floor(actualVersion / this.versionMultipler) !== DB.VERSION) {
83 break;122 this.fail("version");
84 case "VersionError":123 } else {
85 this.onVersionError();124 this.setUserVersion(actualVersion - DB.VERSION * this.versionMultipler);
86 break;125 this.db();
87 case "InvalidStateError":
88 this.fail("private_mode");
89 break;
90 default:
91 this.fail("cant_open", error);
92 }
93 }126 }
127 }
94 128
95 fail(reason, error) {129 buggyIDB(db) {
96 this.cachedDocs = null;130 if (this.checkedBuggyIDB) {
97 this.useIndexedDB = false;131 return;
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 }
116 }132 }
117 133 this.checkedBuggyIDB = true;
118 onQuotaExceededError() {134 try {
119 this.reset();135 this.idbTransaction(db, {
120 this.db();136 stores: $.makeArray(db.objectStoreNames).slice(0, 2),
121 app.onQuotaExceeded();137 mode: "readwrite",
122 Raven.captureMessage("QuotaExceededError", { level: "warning" });138 }).abort(); // https://bugs.webkit.org/show_bug.cgi?id=136937
139 return;
140 } catch (error) {
141 return error;
123 }142 }
143 }
124 144
125 onVersionError() {145 runCallbacks(db) {
126 const req = indexedDB.open(NAME);146 let fn;
127 req.onsuccess = (event) => {147 while ((fn = this.callbacks.shift())) {
128 return this.handleVersionMismatch(event.target.result.version);148 fn(db);
129 };
130 req.onerror = function (event) {
131 event.preventDefault();
132 return this.fail("cant_open", error);
133 };
134 }149 }
150 }
135 151
136 handleVersionMismatch(actualVersion) {152 onUpgradeNeeded(event) {
137 if (Math.floor(actualVersion / this.versionMultipler) !== VERSION) {153 let db;
138 this.fail("version");154 if (!(db = event.target.result)) {
139 } else {155 return;
140 this.setUserVersion(actualVersion - VERSION * this.versionMultipler);
141 this.db();
142 }
143 }156 }
144 157
145 buggyIDB(db) {158 const objectStoreNames = $.makeArray(db.objectStoreNames);
146 if (this.checkedBuggyIDB) {159
147 return;160 if (!$.arrayDelete(objectStoreNames, "docs")) {
148 }
149 this.checkedBuggyIDB = true;
150 try {161 try {
151 this.idbTransaction(db, {162 db.createObjectStore("docs");
152 stores: $.makeArray(db.objectStoreNames).slice(0, 2),163 } catch (error) {}
153 mode: "readwrite",
154 }).abort(); // https://bugs.webkit.org/show_bug.cgi?id=136937
155 return;
156 } catch (error) {
157 return error;
158 }
159 }164 }
160 165
161 runCallbacks(db) {166 for (var doc of app.docs.all()) {
162 let fn;167 if (!$.arrayDelete(objectStoreNames, doc.slug)) {
163 while ((fn = this.callbacks.shift())) {168 try {
164 fn(db);169 db.createObjectStore(doc.slug);
170 } catch (error1) {}
165 }171 }
166 }172 }
167 173
168 onUpgradeNeeded(event) {174 for (var name of objectStoreNames) {
169 let db;175 try {
170 if (!(db = event.target.result)) {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();
171 return;188 return;
172 }189 }
173 190
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 };
175 213
176 if (!$.arrayDelete(objectStoreNames, "docs")) {214 let store = txn.objectStore(doc.slug);
177 try {215 store.clear();
178 db.createObjectStore("docs");216 for (var path in data) {
179 } catch (error) {}217 var content = data[path];
218 store.add(content, path);
180 }219 }
181 220
182 for (var doc of Array.from(app.docs.all())) {221 store = txn.objectStore("docs");
183 if (!$.arrayDelete(objectStoreNames, doc.slug)) {222 store.put(doc.mtime, doc.slug);
184 try {223 });
185 db.createObjectStore(doc.slug);224 }
186 } catch (error1) {}
187 }
188 }
189 225
190 for (var name of Array.from(objectStoreNames)) {226 unstore(doc, onSuccess, onError, _retry) {
191 try {227 if (_retry == null) {
192 db.deleteObjectStore(name);228 _retry = true;
193 } catch (error2) {}
194 }
195 }229 }
196 230 this.db((db) => {
197 store(doc, data, onSuccess, onError, _retry) {231 if (!db) {
198 if (_retry == null) {232 onError();
199 _retry = true;233 return;
200 }234 }
201 this.db((db) => {235
202 if (!db) {236 const txn = this.idbTransaction(db, {
203 onError();237 stores: ["docs", doc.slug],
204 return;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);
205 }256 }
257 };
206 258
207 const txn = this.idbTransaction(db, {259 let store = txn.objectStore("docs");
208 stores: ["docs", doc.slug],260 store.delete(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 };
233 261
234 let store = txn.objectStore(doc.slug);262 store = txn.objectStore(doc.slug);
235 store.clear();263 store.clear();
236 for (var path in data) {264 });
237 var content = data[path];265 }
238 store.add(content, path);
239 }
240 266
241 store = txn.objectStore("docs");267 version(doc, fn) {
242 store.put(doc.mtime, doc.slug);268 let version = this.cachedVersion(doc);
243 });269 if (version != null) {
270 fn(version);
271 return;
244 }272 }
245 273
246 unstore(doc, onSuccess, onError, _retry) {274 this.db((db) => {
247 if (_retry == null) {275 if (!db) {
248 _retry = true;276 fn(false);
277 return;
249 }278 }
250 this.db((db) => {
251 if (!db) {
252 onError();
253 return;
254 }
255 279
256 const txn = this.idbTransaction(db, {280 const txn = this.idbTransaction(db, {
257 stores: ["docs", doc.slug],281 stores: ["docs"],
258 mode: "readwrite",282 mode: "readonly",
259 ignoreError: false,283 });
260 });284 const store = txn.objectStore("docs");
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 };
282 285
283 let store = txn.objectStore("docs");286 const req = store.get(doc.slug);
284 store.delete(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 }
285 296
286 store = txn.objectStore(doc.slug);297 cachedVersion(doc) {
287 store.clear();298 if (!this.cachedDocs) {
288 });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;
289 }309 }
290 310
291 version(doc, fn) {311 return this.db((db) => {
292 let version;312 if (!db) {
293 if ((version = this.cachedVersion(doc)) != null) {313 fn(false);
294 fn(version);
295 return;314 return;
296 }315 }
297 316
298 this.db((db) => {317 const txn = this.idbTransaction(db, {
299 if (!db) {318 stores: ["docs"],
300 fn(false);319 mode: "readonly",
301 return;320 });
302 }321 txn.oncomplete = function () {
303 322 fn(result);
304 const txn = this.idbTransaction(db, {323 };
305 stores: ["docs"],324 const store = txn.objectStore("docs");
306 mode: "readonly",325 var result = {};
307 });
308 const store = txn.objectStore("docs");
309 326
327 docs.forEach(function (doc) {
310 const req = store.get(doc.slug);328 const req = store.get(doc.slug);
311 req.onsuccess = function () {329 req.onsuccess = function () {
312 fn(req.result);330 result[doc.slug] = req.result;
313 };331 };
314 req.onerror = function (event) {332 req.onerror = function (event) {
315 event.preventDefault();333 event.preventDefault();
316 fn(false);334 result[doc.slug] = false;
317 };335 };
318 });336 });
319 }337 });
338 }
320 339
321 cachedVersion(doc) {340 cachedVersions(docs) {
322 if (!this.cachedDocs) {341 if (!this.cachedDocs) {
323 return;342 return;
324 }
325 return this.cachedDocs[doc.slug] || false;
326 }343 }
327 344 const result = {};
328 versions(docs, fn) {345 for (var doc of docs) {
329 let versions;346 result[doc.slug] = this.cachedVersion(doc);
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 });
362 }347 }
348 return result;
349 }
363 350
364 cachedVersions(docs) {351 load(entry, onSuccess, onError) {
365 if (!this.cachedDocs) {352 if (this.shouldLoadWithIDB(entry)) {
366 return;353 return this.loadWithIDB(entry, onSuccess, () =>
367 }354 this.loadWithXHR(entry, onSuccess, onError),
368 const result = {};355 );
369 for (var doc of Array.from(docs)) {356 } else {
370 result[doc.slug] = this.cachedVersion(doc);357 return this.loadWithXHR(entry, onSuccess, onError);
371 }
372 return result;
373 }358 }
374 359 }
375 load(entry, onSuccess, onError) {360
376 if (this.shouldLoadWithIDB(entry)) {361 loadWithXHR(entry, onSuccess, onError) {
377 return this.loadWithIDB(entry, onSuccess, () => this.loadWithXHR(entry, onSuccess, onError));362 return ajax({
378 } else {363 url: entry.fileUrl(),
379 return this.loadWithXHR(entry, onSuccess, onError);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;
380 }375 }
381 }
382 376
383 loadWithXHR(entry, onSuccess, onError) {377 if (!db.objectStoreNames.contains(entry.doc.slug)) {
384 return ajax({378 onError();
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 };
423 this.loadDocsCache(db);379 this.loadDocsCache(db);
424 });
425 }
426
427 loadDocsCache(db) {
428 if (this.cachedDocs) {
429 return;380 return;
430 }381 }
431 this.cachedDocs = {};
432 382
433 const txn = this.idbTransaction(db, {383 const txn = this.idbTransaction(db, {
434 stores: ["docs"],384 stores: [entry.doc.slug],
435 mode: "readonly",385 mode: "readonly",
436 });386 });
437 txn.oncomplete = () => {387 const store = txn.objectStore(entry.doc.slug);
438 setTimeout(() => this.checkForCorruptedDocs(), 50);
439 };
440 388
441 const req = txn.objectStore("docs").openCursor();389 const req = store.get(entry.dbPath());
442 req.onsuccess = (event) => {390 req.onsuccess = function () {
443 let cursor;391 if (req.result) {
444 if (!(cursor = event.target.result)) {392 onSuccess(req.result);
445 return;393 } else {
394 onError();
446 }395 }
447 this.cachedDocs[cursor.key] = cursor.value;
448 cursor.continue();
449 };396 };
450 req.onerror = function (event) {397 req.onerror = function (event) {
451 event.preventDefault();398 event.preventDefault();
399 onError();
452 };400 };
453 }401 this.loadDocsCache(db);
402 });
403 }
454 404
455 checkForCorruptedDocs() {405 loadDocsCache(db) {
456 this.db((db) => {406 if (this.cachedDocs) {
457 let slug;407 return;
458 this.corruptedDocs = [];408 }
459 const docs = (() => {409 this.cachedDocs = {};
460 const result = [];410
461 for (var key in this.cachedDocs) {411 const txn = this.idbTransaction(db, {
462 var value = this.cachedDocs[key];412 stores: ["docs"],
463 if (value) {413 mode: "readonly",
464 result.push(key);414 });
465 }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);
466 }443 }
467 return result;
468 })();
469 if (docs.length === 0) {
470 return;
471 }444 }
445 return result;
446 })();
447 if (docs.length === 0) {
448 return;
449 }
472 450
473 for (slug of Array.from(docs)) {451 for (slug of docs) {
474 if (!app.docs.findBy("slug", slug)) {452 if (!app.docs.findBy("slug", slug)) {
475 this.corruptedDocs.push(slug);453 this.corruptedDocs.push(slug);
476 }
477 }454 }
455 }
478 456
479 for (slug of Array.from(this.corruptedDocs)) {457 for (slug of this.corruptedDocs) {
480 $.arrayDelete(docs, slug);458 $.arrayDelete(docs, slug);
481 }459 }
460
461 if (docs.length === 0) {
462 setTimeout(() => this.deleteCorruptedDocs(), 0);
463 return;
464 }
482 465
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) {
484 setTimeout(() => this.deleteCorruptedDocs(), 0);473 setTimeout(() => this.deleteCorruptedDocs(), 0);
485 return;
486 }474 }
475 };
487 476
488 const txn = this.idbTransaction(db, {477 for (var doc of docs) {
489 stores: docs,478 txn.objectStore(doc).get("index").onsuccess = (event) => {
490 mode: "readonly",479 if (!event.target.result) {
491 ignoreError: false,480 this.corruptedDocs.push(event.target.source.name);
492 });
493 txn.oncomplete = () => {
494 if (this.corruptedDocs.length > 0) {
495 setTimeout(() => this.deleteCorruptedDocs(), 0);
496 }481 }
497 };482 };
483 }
484 });
485 }
498 486
499 for (var doc of Array.from(docs)) {487 deleteCorruptedDocs() {
500 txn.objectStore(doc).get("index").onsuccess = (event) => {488 this.db((db) => {
501 if (!event.target.result) {489 let doc;
502 this.corruptedDocs.push(event.target.source.name);490 const txn = this.idbTransaction(db, {
503 }491 stores: ["docs"],
504 };492 mode: "readwrite",
505 }493 ignoreError: false,
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(",") },
526 });494 });
527 }495 const store = txn.objectStore("docs");
528 496 while ((doc = this.corruptedDocs.pop())) {
529 shouldLoadWithIDB(entry) {497 this.cachedDocs[doc] = false;
530 return (498 store.delete(doc);
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 };
543 }499 }
544 if (options.ignoreAbort !== false) {500 });
545 txn.onabort = function (event) {501 Raven.captureMessage("corruptedDocs", {
546 event.preventDefault();502 level: "info",
547 };503 extra: { docs: this.corruptedDocs.join(",") },
548 }504 });
549 return txn;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 };
550 }520 }
551 521 if (options.ignoreAbort !== false) {
552 reset() {522 txn.onabort = function (event) {
553 try {523 event.preventDefault();
554 if (typeof indexedDB !== "undefined" && indexedDB !== null) {524 };
555 indexedDB.deleteDatabase(NAME);
556 }
557 } catch (error) {}
558 }525 }
559 526 return txn;
560 useIndexedDB() {527 }
561 try {528
562 if (!app.isSingleDoc() && window.indexedDB) {529 reset() {
563 return true;530 try {
564 } else {531 indexedDB?.deleteDatabase(DB.NAME);
565 this.reason = "not_supported";532 } catch (error) {}
566 return false;533 }
567 }534
568 } catch (error) {535 useIndexedDB() {
536 try {
537 if (!app.isSingleDoc() && window.indexedDB) {
538 return true;
539 } else {
540 this.reason = "not_supported";
569 return false;541 return false;
570 }542 }
543 } catch (error) {
544 return false;
571 }545 }
546 }
572 547
573 migrate() {548 migrate() {
574 app.settings.set("schema", this.userVersion() + 1);549 app.settings.set("schema", this.userVersion() + 1);
575 }550 }
576 551
577 setUserVersion(version) {552 setUserVersion(version) {
578 app.settings.set("schema", version);553 app.settings.set("schema", version);
579 }554 }
580 555
581 userVersion() {556 userVersion() {
582 return app.settings.get("schema");557 return app.settings.get("schema");
583 }558 }
584 };559};
585 app.DB.initClass();
586 return app.DB;
587})();