Skip to content
This repository has been archived by the owner on Aug 4, 2024. It is now read-only.

Commit

Permalink
Improves localStorage polyfill to store keys as base64
Browse files Browse the repository at this point in the history
  • Loading branch information
mhassan1 authored and JakeChampion committed Dec 9, 2021
1 parent 559f122 commit b89fda3
Show file tree
Hide file tree
Showing 3 changed files with 93 additions and 9 deletions.
7 changes: 6 additions & 1 deletion polyfills/localStorage/config.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
aliases = [ "caniuse:namevalue-storage", "modernizr:localstorage" ]
dependencies = [ "Array.prototype.forEach", "Window" ]
dependencies = [
"Array.prototype.forEach",
"Array.prototype.map",
"atob",
"Window",
]
docs = "https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage"
spec = "http://dev.w3.org/html5/webstorage/#dom-localstorage"

Expand Down
38 changes: 30 additions & 8 deletions polyfills/localStorage/polyfill.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,20 +55,40 @@
var unloadkeys = [];

var keys = getKeys(localStorage);
var encodedKeys = keys.map(encodeKey);

unloadkeys.concat(keys).forEach(function (key) {
unloadkeys.concat(keys).forEach(function (key, i) {
if (key in localStorage) {
element.setAttribute(userdata + key, localStorage[key]);
element.setAttribute(makeAttributeName(encodedKeys[i]), localStorage[key]);
} else {
element.removeAttribute(userdata + key);
element.removeAttribute(makeAttributeName(encodedKeys[i]));
}
});

element.setAttribute(userdata, keys.join(','));
element.setAttribute(userdata, encodedKeys.join(','));

element.save(userdata);
}

function encodeKey (key) {
return btoa(String(key))
.replace(/\+/g, '_')
.replace(/\//g, '-')
.replace(/=/g, '');
}

function decodeKey (encodedKey) {
return atob(
String(encodedKey)
.replace(/_/g, '+')
.replace(/-/g, '/')
);
}

function makeAttributeName (encodedKey) {
return userdata + '_' + encodedKey;
}

var localStorageExists = (function() {
try {
return !!self.localStorage;
Expand All @@ -84,24 +104,26 @@
// set storage element
element = self.document.lastChild.lastChild.appendChild(self.document.createElement('x-local-storage')),
// set userdata key and prefix
userdata = 'userdata',
userdata = 'base64_userdata',
keys;

// proprietary ie local storage
try {
element.addBehavior('#default#' + userdata);
element.addBehavior('#default#userdata');
element.load(userdata);
// eslint-disable-next-line no-empty
} catch (error) {}

// get keys
keys = element.getAttribute(userdata) ? element.getAttribute(userdata).split(',') : [];
keys = element.getAttribute(userdata)
? element.getAttribute(userdata).split(',').map(decodeKey)
: [];

localStorage.length = keys.length;

// assign keys to localStorage
keys.forEach(function (key) {
localStorage[key] = element.getAttribute(userdata + key);
localStorage[key] = element.getAttribute(makeAttributeName(encodeKey(key)));
});

if (self.attachEvent) {
Expand Down
57 changes: 57 additions & 0 deletions polyfills/localStorage/tests.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
/* eslint-env mocha, browser */
/* global proclaim */

beforeEach(function () {
localStorage.clear();
localStorage.setItem('hi', 'there');
});

describe('getItem', function () {
it('should get an item', function () {
proclaim.equal(localStorage.getItem('hi'), 'there');
});
});

describe('setItem', function () {
it('should set an item', function () {
localStorage.setItem('x', 'y');
proclaim.equal(localStorage.getItem('x'), 'y');
});

it('should set an item with special characters', function () {
var key = 'x [{]}\\|;:\'",<.>/?!@#$%^&*()-_=+\n\t'
localStorage.setItem(key, 'y');
proclaim.equal(localStorage.getItem(key), 'y');
});

it('should set an item with an empty key', function () {
localStorage.setItem('', 'y');
proclaim.equal(localStorage.getItem(''), 'y');
});
});

describe('removeItem', function () {
it('should remove an item', function () {
localStorage.removeItem('hi');
proclaim.equal(localStorage.getItem('hi'), null);
});
});

describe('key', function () {
it('should get a key', function () {
proclaim.equal(localStorage.key(0), 'hi');
});
});

describe('clear', function () {
it('should clear all items', function () {
localStorage.clear();
proclaim.equal(localStorage.getItem('hi'), null);
});
});

describe('length', function () {
it('should get number of items', function () {
proclaim.equal(localStorage.length, 1);
});
});

0 comments on commit b89fda3

Please sign in to comment.