marcuswestin / store.js

Cross-browser storage for all use cases, used across the web.
MIT License
14.01k stars 1.33k forks source link

IE LocalStorage.setItem bug with compression #271

Open lianee opened 6 years ago

lianee commented 6 years ago

Using store.everything.min.js 2.0.12, Edge (IE11 also) throw an exception "SCRIPT87: Invalid argument" with the following code:

var x = [
  {"id":"10","keys":"dev"}
];
store.set('test', x);

crash happens line 22 of localStorage.js

It seems that there's a char in the compressed string that IE doesn't like too much. No problem with Chrome or Firefox.

jsfiddle

RonenNess commented 6 years ago

I'm having the same issue on Edge. Since I had to fix it ASAP (it was blocking my checkout page for some users) I added the following patch right after including store.js:

try
{
    store.set("__test_store_", [{"id":"10","keys":"dev"}])
}
catch (e)
{
    console.warn("Store fallback!");
    store = {
        get: function(key)
        {
            return JSON.parse(localStorage.getItem(key));
        },
        set: function(key, val)
        {
            localStorage.setItem(key, JSON.stringify(val));
        },
    }
}

Its not a good solution but its better than nothing for now.. Hope this problem will have a solution soon.

ensemblebd commented 6 years ago

Excellent, thank you for the patch!

I made some adjustments for my use case scenario to hook the func and attempt to use it preferentially

window.storageReadyCallback = function(storage) {
    // internet explorer fallback, due to poor browser code by microsoft.
    try {
        storage.set("__test_store_", [{"id":"10","keys":"dev"}])
    }
    catch (e) {
        console.warn("Store fallback!");
        storage._get = storage.get;
        storage.get = function(key) {
            var r=null;
            try {
                r = storage._get(key);
            } catch (E) {
                r = JSON.parse(localStorage.getItem(key));
            }
            return r;
        };
        storage._set = storage.set;
        storage.set = function(key, val) {
            try {
                storage._set(key, val);
            } catch (E) {
                localStorage.setItem(key, JSON.stringify(val));
            }
        }
    }
};
climff commented 5 years ago

This is probably a little old but just found out from LZString you can do the following (code from http://pieroxy.net/blog/pages/lz-string/guide.html):

var string = "This is my compression test."; alert("Size of sample is: " + string.length); var compressed = LZString.compressToUTF16(string); alert("Size of compressed sample is: " + compressed.length); localStorage.setItem("myData",compressed); (...) string = LZString.decompressFromUTF16(localStorage.getItem("myData")); alert("Sample is: " + string);