New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Remove localstorage limit #13465
Comments
Alright, I have a repro! With the Electron 2.0.2 application, from the dev tools: localStorage.length
> 635
for (let i = 0; i < 10000; i++) { localStorage.setItem(i.toString(), Array(1000).fill(1).toString()) }
> undefined
localStorage.length
> 5630
for (let i = 10000; i < 20000; i++) { localStorage.setItem(i.toString(), Array(1000).fill(1).toString()) }
> undefined
localStorage.length
> 5630 I when I try to add more, it doesn't work and there are no errors! In Electron 1.8.1 application, from the dev tools: localStorage.length
> 359
for (let i = 0; i < 10000; i++) { localStorage.setItem(i.toString(), Array(1000).fill(1).toString()) }
> undefined
localStorage.length
> 10359
for (let i = 10000; i < 20000; i++) { localStorage.setItem(i.toString(), Array(1000).fill(1).toString()) }
> undefined
localStorage.length
> 20008
for (let i = 0; i < 800000; i++) { localStorage.setItem(i.toString(), Array(1000).fill(1).toString()) }
> undefined
localStorage.length
> 800008 Now, I'm not sure why we appear to have lost some entries -- its possible that the application itself removed some stuff -- but for the most part, it worked. It took about 2 minutes to add the 800000 entries, so its definitely working. Sounds like a bug to me! |
@ccorcos does it reproduce if you run this early before
|
localStorage.length
> 155
for (let i = 0; i < 10000; i++) { localStorage.setItem(i.toString(), Array(1000).fill(1).toString()) }
> undefined
localStorage.length
> 10155
for (let i = 10000; i < 20000; i++) { localStorage.setItem(i.toString(), Array(1000).fill(1).toString()) }
> undefined
localStorage.length
> 20155
for (let i = 0; i < 800000; i++) { localStorage.setItem(i.toString(), Array(1000).fill(1).toString()) }
> undefined
localStorage.length
> 800009 Seems to be the culprit! |
This looks like an issue with |
Hey @bpasero would you mind trying? 3.0.0-beta.1 keeps crashing :/ |
@ccorcos I think this still reproduces in Electron 3.0.0-beta.1. Output: |
Hmm yeah, that's no good! |
Just tried this in Electron 3.0.9 and its still an issue and |
@deepak1556 any idea what happened to this command line option to turn off mojo? |
@ccorcos |
Seems like the localstorage limit is not completely removed, during commit operation the size constraint is still maintained at 5MB. |
I think the test code used above is misleading. (In fact, so is the test I originally contributed). I found that within a script I can call localStorage.setItem('junk', new Array(50*1024*1024/2).fill('x').join('')); console.log(localStorage.getItem('junk').length) However, the data isn't necessarily persisted. If the As a more thorough test, I've forked the quick start app and scripted it to run a series of tests separated by For current versions (5.0.1 and 6.0.0-beta.4) the limit appears to be about 21176304 bytes (i.e. 20MiB + about 1% grace). |
Hmm. That's weird because localStorage is supposed to be synchronous |
I'd have to review the spec again, but I think it's synchronous from the perspective of the script. That is, calling setItem then getItem must give back the new value. However, I don't think the underlying structures are required to be, so if something goes wrong (e.g. disk full, limit exceeded, etc.) then future calls to getItem may differ. |
Maybe it got deleted now, but I got an email saying that this issue appeared to be out-of-date / only applicable to old versions of Electron. This is not the case. I just rebased my test repo (see |
I started looking into this again and think I found a clue as to what is going wrong with the current patch. The Update 1: Actually, the value passed to Update 2: Circumventing the quota check in |
The previous version of this patch did not include changes required to circumvent the quota enforcement performed by StorageAreaImpl. Consequently when the quota was exceeded, things still "appeared to work" at first but then would later fail silently. That is, the cache would be updated but the backing store would not. Refer to the discussion linked below for more information: electron#13465 (comment)
The previous version of this patch did not include changes required to circumvent the quota enforcement performed by StorageAreaImpl. Consequently when the quota was exceeded, things still "appeared to work" at first but then would later fail silently. That is, the cache would be updated but the backing store would not. Refer to the discussion linked below for more information: electron#13465 (comment)
The previous version of this patch did not include changes required to circumvent the quota enforcement performed by StorageAreaImpl. Consequently when the quota was exceeded, things still "appeared to work" at first but then would later fail silently. That is, the cache would be updated but the backing store would not. This could be fixed by disabling the code below (from `content/browser/dom_storage/storage_area_impl.cc`) ``` // Only check quota if the size is increasing, this allows // shrinking changes to pre-existing maps that are over budget. if (new_item_size > old_item_size && new_storage_used > max_size_) { if (map_state_ == MapState::LOADED_KEYS_ONLY) { receivers_.ReportBadMessage( "The quota in browser cannot exceed when there is only one " "renderer."); } else { std::move(callback).Run(false); } return; } ``` However, since this seems to have some unintended side-effects (see updated notes in dom_storage_limits.patch) it seems more prudent to simply increase the quota to a larger yet still reasonable size rather than attempt to circumvent the storage quota altogether.
The previous version of this patch did not include changes required to circumvent the quota enforcement performed by StorageAreaImpl. Consequently when the quota was exceeded, things still "appeared to work" at first but then would later fail silently. That is, the cache would be updated but the backing store would not. This could be fixed by disabling the code below (from `content/browser/dom_storage/storage_area_impl.cc`) ``` // Only check quota if the size is increasing, this allows // shrinking changes to pre-existing maps that are over budget. if (new_item_size > old_item_size && new_storage_used > max_size_) { if (map_state_ == MapState::LOADED_KEYS_ONLY) { receivers_.ReportBadMessage( "The quota in browser cannot exceed when there is only one " "renderer."); } else { std::move(callback).Run(false); } return; } ``` However, since this seems to have some unintended side-effects (see updated notes in dom_storage_limits.patch) it seems more prudent to simply increase the quota to a larger yet still reasonable size rather than attempt to circumvent the storage quota altogether.
The previous version of this patch did not include changes required to circumvent the quota enforcement performed by StorageAreaImpl. Consequently when the quota was exceeded, things still "appeared to work" at first but then would later fail silently. That is, the cache would be updated but the backing store would not. This could be fixed by disabling the code below (from `content/browser/dom_storage/storage_area_impl.cc`) ``` // Only check quota if the size is increasing, this allows // shrinking changes to pre-existing maps that are over budget. if (new_item_size > old_item_size && new_storage_used > max_size_) { if (map_state_ == MapState::LOADED_KEYS_ONLY) { receivers_.ReportBadMessage( "The quota in browser cannot exceed when there is only one " "renderer."); } else { std::move(callback).Run(false); } return; } ``` However, since this seems to have some unintended side-effects (see updated notes in dom_storage_limits.patch) it seems more prudent to simply increase the quota to a larger yet still reasonable size rather than attempt to circumvent the storage quota altogether.
The previous version of this patch did not include changes required to circumvent the quota enforcement performed by StorageAreaImpl. Consequently when the quota was exceeded, things still "appeared to work" at first but then would later fail silently. That is, the cache would be updated but the backing store would not. This could be fixed by disabling the code below (from `content/browser/dom_storage/storage_area_impl.cc`) ``` // Only check quota if the size is increasing, this allows // shrinking changes to pre-existing maps that are over budget. if (new_item_size > old_item_size && new_storage_used > max_size_) { if (map_state_ == MapState::LOADED_KEYS_ONLY) { receivers_.ReportBadMessage( "The quota in browser cannot exceed when there is only one " "renderer."); } else { std::move(callback).Run(false); } return; } ``` However, since this seems to have some unintended side-effects (see updated notes in dom_storage_limits.patch) it seems more prudent to simply increase the quota to a larger yet still reasonable size rather than attempt to circumvent the storage quota altogether.
The previous version of this patch did not include changes required to circumvent the quota enforcement performed by StorageAreaImpl. Consequently when the quota was exceeded, things still "appeared to work" at first but then would later fail silently. That is, the cache would be updated but the backing store would not. This could be fixed by disabling the code below (from `content/browser/dom_storage/storage_area_impl.cc`) ``` // Only check quota if the size is increasing, this allows // shrinking changes to pre-existing maps that are over budget. if (new_item_size > old_item_size && new_storage_used > max_size_) { if (map_state_ == MapState::LOADED_KEYS_ONLY) { receivers_.ReportBadMessage( "The quota in browser cannot exceed when there is only one " "renderer."); } else { std::move(callback).Run(false); } return; } ``` However, since this seems to have some unintended side-effects (see updated notes in dom_storage_limits.patch) it seems more prudent to simply increase the quota to a larger yet still reasonable size rather than attempt to circumvent the storage quota altogether.
The previous version of this patch did not include changes required to circumvent the quota enforcement performed by StorageAreaImpl. Consequently when the quota was exceeded, things still "appeared to work" at first but then would later fail silently. That is, the cache would be updated but the backing store would not. This could be fixed by disabling the code below (from `content/browser/dom_storage/storage_area_impl.cc`) ``` // Only check quota if the size is increasing, this allows // shrinking changes to pre-existing maps that are over budget. if (new_item_size > old_item_size && new_storage_used > max_size_) { if (map_state_ == MapState::LOADED_KEYS_ONLY) { receivers_.ReportBadMessage( "The quota in browser cannot exceed when there is only one " "renderer."); } else { std::move(callback).Run(false); } return; } ``` However, since this seems to have some unintended side-effects (see updated notes in dom_storage_limits.patch) it seems more prudent to simply increase the quota to a larger yet still reasonable size rather than attempt to circumvent the storage quota altogether.
The previous version of this patch did not include changes required to circumvent the quota enforcement performed by StorageAreaImpl. Consequently when the quota was exceeded, things still "appeared to work" at first but then would later fail silently. That is, the cache would be updated but the backing store would not. This could be fixed by disabling the code below (from `content/browser/dom_storage/storage_area_impl.cc`) ``` // Only check quota if the size is increasing, this allows // shrinking changes to pre-existing maps that are over budget. if (new_item_size > old_item_size && new_storage_used > max_size_) { if (map_state_ == MapState::LOADED_KEYS_ONLY) { receivers_.ReportBadMessage( "The quota in browser cannot exceed when there is only one " "renderer."); } else { std::move(callback).Run(false); } return; } ``` However, since this seems to have some unintended side-effects (see updated notes in dom_storage_limits.patch) it seems more prudent to simply increase the quota to a larger yet still reasonable size rather than attempt to circumvent the storage quota altogether.
…#20899) * test: update DOM storage quota limits test * fix: update dom_storage_limits.patch (fixes electron#13465) The previous version of this patch did not include changes required to circumvent the quota enforcement performed by StorageAreaImpl. Consequently when the quota was exceeded, things still "appeared to work" at first but then would later fail silently. That is, the cache would be updated but the backing store would not. This could be fixed by disabling the code below (from `content/browser/dom_storage/storage_area_impl.cc`) ``` // Only check quota if the size is increasing, this allows // shrinking changes to pre-existing maps that are over budget. if (new_item_size > old_item_size && new_storage_used > max_size_) { if (map_state_ == MapState::LOADED_KEYS_ONLY) { receivers_.ReportBadMessage( "The quota in browser cannot exceed when there is only one " "renderer."); } else { std::move(callback).Run(false); } return; } ``` However, since this seems to have some unintended side-effects (see updated notes in dom_storage_limits.patch) it seems more prudent to simply increase the quota to a larger yet still reasonable size rather than attempt to circumvent the storage quota altogether.
…21380) * test: update DOM storage quota limits test * fix: update dom_storage_limits.patch (fixes #13465) The previous version of this patch did not include changes required to circumvent the quota enforcement performed by StorageAreaImpl. Consequently when the quota was exceeded, things still "appeared to work" at first but then would later fail silently. That is, the cache would be updated but the backing store would not. This could be fixed by disabling the code below (from `content/browser/dom_storage/storage_area_impl.cc`) ``` // Only check quota if the size is increasing, this allows // shrinking changes to pre-existing maps that are over budget. if (new_item_size > old_item_size && new_storage_used > max_size_) { if (map_state_ == MapState::LOADED_KEYS_ONLY) { receivers_.ReportBadMessage( "The quota in browser cannot exceed when there is only one " "renderer."); } else { std::move(callback).Run(false); } return; } ``` However, since this seems to have some unintended side-effects (see updated notes in dom_storage_limits.patch) it seems more prudent to simply increase the quota to a larger yet still reasonable size rather than attempt to circumvent the storage quota altogether.
Sorry for the extremely vague bug report, but I found a serious bug in our app where localStorage seems to have stopped working without throwing any errors causing using users to lose data.
Upon deleting the Application Support files, everything started working again. Is it possible that we are not raising an error in some cases when localStorage doesn't work? Perhaps the data has been corrupted or something?
I apologize that I don't have reproducible steps, but I think its worth documenting in case others have a similar issue.
The text was updated successfully, but these errors were encountered: