Are there any characters that are not allowed in l

2019-02-19 02:56发布

问题:

I've been using localStorage to store some binary data in string format, and although the value is definitely set (alerting it immediately after setting, or even some time after setting, shows the correct value) it is lost when the page next loads.

At first I figured it might be because the data contained null bytes, so I redesigned the compressor so that it would never output them. However, this made no difference as the value is still lost.

I added localStorage.testing = 1 immediately after setting the binary data. This value is kept, even when the other is lost.

I am absolutely certain there is no code to delete localStorage.myitem.

What could be causing this issue?

If it helps any, here is the data I'm trying to store, in hex:

0x1103c0a0   0xd6cf0305   0xc0a0d6cf   0x0307c0a0   0xd6cf0309   0xc0a0d6cf
0x030bc0a0   0xd6cf030d   0xc0a0d6cf   0x0311c0a0   0xd6cf0313   0xc0a0d6cf   0x0301

EDIT: I just tested with localStorage.testvalue = realvalue.replace(/[\x00-\x1f]/g,''); and that successfully saved it. So, I'd like to know where the specification says that control characters may not be used in strings.

回答1:

I've set up a test case, and ran the test in various browsers. The results are below (the inclusive ranges of character codes are mentioned). Tests started at the minimum browser version which support localStorage.

  • Chrome 5 - 20: 0x0000 - 0xFFFF
  • Opera 10.50 - 12.00: 0x0000 - 0xFFFF
  • Safari 4.0 - 5.1.7: 0x0000 - 0xFFFF
  • Firefox 3.5 - 16alpha: 0x0000 - 0xD7FF and 0xE000 - 0xFFFE (0xD800-0xDFFF and 0xFFFF are turned in two characters after LS)
  • IE8, IE9, IE10PP6: 0x0009, 0x000A, 0x000D, 0x0020 - 0xD7FF and 0xE000 - 0xFFFD. (Other ranges are either ignored or cause an "Invalid argument" error).
    0x0000 is a NULL-byte, which truncates all following characters in IE.

So, the character ranges 0x20 - 0xD7FF and 0xE000 - 0xFFFD plus 0x09, 0x0A and 0x0D are safe.


I've created three test cases:

  1. The quickest test case, which creates a string with all characters, and tests the value after setting localStorage
  2. A method which used the SPACE character (0x20) as a delimiter, to properly deal with browsers which create a character with length 2.
  3. The worst method, because IE throws an error for invalid strings. Each character is tested individually, which is quite expensive.

All test functions are available in JSFiddle, the first test case is visible below:

function run_test(lowerlimit, UPPERLIMIT) {
    try {
        if (!window.localStorage) {
            // I recall that in one of the older Chrome version (4),
            // localStorage === null
            return 'Localstorage is not supported';
        }
        if (isNaN(lowerlimit) || isNaN(UPPERLIMIT) || lowerlimit > UPPERLIMIT) {
            return 'One of the limits is not a valid number!';
        }
        var i = lowerlimit - 1;
        var character_range = [];
        while (++i < UPPERLIMIT) character_range.push(i);
        input = String.fromCharCode.apply(String, character_range);
        localStorage.setItem('chartest', input);
        output = localStorage.getItem('chartest');
        if (input === output) {
            return true;
        }
        // Uh oh, not equal!
        var result = [];
        for (i=0; i<UPPERLIMIT-lowerlimit; i++) {
            if (input[i] !== output[i]) {
                result.push(i + lowerlimit);
            }
        }
        return result;
    }catch(e){return 'Error:' + e;}
}


回答2:

After further testing, it appears that when localStorage says it stores strings, what it really means is that it stores string that match:

/^[\x00\x09\x0A\x0D\x20-\xff]*$/

So nothing before space is allowed, except HT, CR, LF and NUL.

That said, still no idea why.