1/** 2 * #4502: QuotaExceededError on Local Storage (Clerk) 3 * https://collab.seken.it/projects/295/tasks/36778 4 */ 5(function() { 6 'use strict'; 7 8 /** 9 * Generate LocalStorage dump (only keys >= 1KB) 10 * @returns {*[]} 11 */ 12 function getStorageDump() { 13 let localStorageDump = []; 14 15 for (let i = 0; i < localStorage.length; i++) { 16 let k = localStorage.key(i); 17 let val = localStorage.getItem(k); 18 19 if (!val) { 20 continue; 21 } 22 23 // approximation with length instead of Blob 24 // to avoid crashing the browser when memory is already full 25 let sizeKB = val.length / 1024; 26 27 // Filter only keys greater than or equal to 1 KB 28 if (sizeKB >= 1) { 29 localStorageDump.push({"Key": k, "Size (KB)": parseFloat(sizeKB.toFixed(2))}); 30 } 31 } 32 33 localStorageDump.sort(function(a, b) { 34 return b["Size (KB)"] - a["Size (KB)"]; 35 }); 36 37 return localStorageDump; 38 } 39 40 // Save the original system function 41 var originalSetItem = Storage.prototype.setItem; 42 43 // Override of 'setItem' in Local Storage 44 Storage.prototype.setItem = function(key, value) { 45 try { 46 // Original function call 47 originalSetItem.apply(this, arguments); 48 } catch (e) { 49 // Check if the error is due to full memory 50 if (e.name === 'QuotaExceededError' || e.name === 'NS_ERROR_DOM_QUOTA_REACHED') { 51 52 let attemptedSizeKB = value ? (String(value).length / 1024).toFixed(2) : 0; 53 let failedKey = " | Failed to save key: '" + key + "' (" + attemptedSizeKB + " KB)"; 54 55 console.warn('[Quota Fix Module] LocalStorage full. Attempting to clear __clerk-vp...'); 56 57 // Clear Clerk key 58 if (localStorage.getItem('__clerk-vp')) { 59 localStorage.removeItem('__clerk-vp'); 60 61 try { 62 // 2° Attempt: Retry the original save 63 originalSetItem.apply(this, arguments); 64 console.log('[Quota Fix Module] Save of "' + key + '" successful after clearing Clerk!'); 65 } catch (retryError) { 66 // If it still fails, dump and throw the error 67 let storageKeyDump = getStorageDump(); 68 console.error('[Quota Fix Module] Insufficient space even after removing Clerk. Keys dump (>1KB):'); 69 if (storageKeyDump.length > 0){ 70 console.table(storageKeyDump); 71 } 72 73 let dumpString = ''; 74 if (storageKeyDump.length > 0) { 75 dumpString = '\n\nLocalStorage dump (>1KB):\n' + 76 storageKeyDump.map(item => item.Key + ' = ' + item["Size (KB)"] + ' KB').join('\n'); 77 } 78 throw new Error(retryError.message + failedKey + dumpString); 79 } 80 } else { 81 // Dump keys if Clerk is not present 82 let storageKeyDump = getStorageDump(); 83 console.error('[Quota Fix Module] Insufficient space. Keys dump (>1KB):'); 84 if (storageKeyDump.length > 0) { 85 console.table(storageKeyDump); 86 } 87 88 throw new Error(e.message + failedKey); 89 } 90 } else { 91 // If it's not a memory error 92 throw e; 93 } 94 } 95 }; 96})();
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.