blob: 37c97a3fbd154eb9608d6df0c9af885de649a61b [file] [log] [blame]
// Copyright 2012 The ChromiumOS Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import {lib} from './lib.js';
/**
* window.localStorage based class with an async interface that is
* interchangeable with other lib.Storage.* implementations.
*/
lib.Storage.Local = class extends lib.Storage {
/**
* @param {!Storage=} storage The backing storage.
*/
constructor(storage = undefined) {
super();
/** @type {!Storage} */
this.storage_ = storage ? storage : lib.notNull(globalThis.localStorage);
// Closure thinks all addEventListener calls take Events.
globalThis.addEventListener(
'storage',
/** @type {function(!Event)} */ (this.onStorage_.bind(this)));
}
/**
* Called by the storage implementation when the storage is modified.
*
* @param {!StorageEvent} e The setting that has changed.
*/
onStorage_(e) {
if (e.storageArea != this.storage_) {
return;
}
const o = {};
o[e.key] = {
oldValue: parseJson_(e.oldValue),
newValue: parseJson_(e.newValue),
};
for (let i = 0; i < this.observers_.length; i++) {
this.observers_[i](o);
}
}
/**
* @return {!Promise<void>}
* @override
*/
async clear() {
this.storage_.clear();
// Force deferment for the standard API.
await 0;
}
/**
* @param {?Array<string>} keys
* @return {!Promise<!Object<string, *>>}
* @override
*/
async getItems(keys) {
const rv = {};
if (!keys) {
keys = [];
for (let i = 0; i < this.storage_.length; i++) {
keys.push(this.storage_.key(i));
}
}
for (const key of keys) {
const value = this.storage_.getItem(key);
if (typeof value == 'string') {
rv[key] = parseJson_(value);
}
}
// Force deferment for the standard API.
await 0;
return rv;
}
/**
* @param {!Object} obj
* @return {!Promise<void>}
* @override
*/
async setItems(obj) {
for (const key in obj) {
this.storage_.setItem(key, JSON.stringify(obj[key]));
}
// Force deferment for the standard API.
await 0;
}
/**
* @param {!Array<string>} keys
* @return {!Promise<void>}
* @override
*/
async removeItems(keys) {
for (let i = 0; i < keys.length; i++) {
this.storage_.removeItem(keys[i]);
}
// Force deferment for the standard API.
await 0;
}
};
/**
* Returns parsed JSON, or original value if JSON.parse fails.
*
* @param {?string} jsonString The string to parse.
* @return {*}
*/
function parseJson_(jsonString) {
if (jsonString !== null) {
try {
return JSON.parse(jsonString);
} catch (e) {
// Ignore and return jsonString.
}
}
return jsonString;
}