mirror of
https://github.com/bitwarden/browser
synced 2025-12-15 07:43:35 +00:00
JSON stringify memory items (#7731)
* JSON stringify memory items stringification is required so they can be reliably sent through messaging * Simplify null handling
This commit is contained in:
@@ -0,0 +1,53 @@
|
||||
import { MemoryStorageService } from "./memory-storage.service";
|
||||
|
||||
describe("MemoryStorageService", () => {
|
||||
let sut: MemoryStorageService;
|
||||
const key = "key";
|
||||
const value = { test: "value" };
|
||||
|
||||
beforeEach(() => {
|
||||
sut = new MemoryStorageService();
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
jest.resetAllMocks();
|
||||
});
|
||||
|
||||
describe("get", () => {
|
||||
it("should return null if the key does not exist", async () => {
|
||||
const result = await sut.get(key);
|
||||
expect(result).toBeNull();
|
||||
});
|
||||
|
||||
it("should return the value if the key exists", async () => {
|
||||
await sut.save(key, value);
|
||||
const result = await sut.get(key);
|
||||
expect(result).toEqual(value);
|
||||
});
|
||||
|
||||
it("should json parse stored values", async () => {
|
||||
sut["store"][key] = JSON.stringify({ test: "value" });
|
||||
const result = await sut.get(key);
|
||||
|
||||
expect(result).toEqual({ test: "value" });
|
||||
});
|
||||
});
|
||||
|
||||
describe("save", () => {
|
||||
it("should store the value as json string", async () => {
|
||||
const value = { test: "value" };
|
||||
await sut.save(key, value);
|
||||
|
||||
expect(sut["store"][key]).toEqual(JSON.stringify(value));
|
||||
});
|
||||
});
|
||||
|
||||
describe("remove", () => {
|
||||
it("should remove a value from store", async () => {
|
||||
await sut.save(key, value);
|
||||
await sut.remove(key);
|
||||
|
||||
expect(Object.keys(sut["store"])).not.toContain(key);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,56 @@
|
||||
import { Subject } from "rxjs";
|
||||
|
||||
import {
|
||||
AbstractMemoryStorageService,
|
||||
ObservableStorageService,
|
||||
StorageUpdate,
|
||||
} from "../../abstractions/storage.service";
|
||||
|
||||
export class MemoryStorageService
|
||||
extends AbstractMemoryStorageService
|
||||
implements ObservableStorageService
|
||||
{
|
||||
protected store: Record<string, string> = {};
|
||||
private updatesSubject = new Subject<StorageUpdate>();
|
||||
|
||||
get valuesRequireDeserialization(): boolean {
|
||||
return true;
|
||||
}
|
||||
get updates$() {
|
||||
return this.updatesSubject.asObservable();
|
||||
}
|
||||
|
||||
get<T>(key: string): Promise<T> {
|
||||
const json = this.store[key];
|
||||
if (json) {
|
||||
const obj = JSON.parse(json as string);
|
||||
return Promise.resolve(obj as T);
|
||||
}
|
||||
return Promise.resolve(null);
|
||||
}
|
||||
|
||||
async has(key: string): Promise<boolean> {
|
||||
return (await this.get(key)) != null;
|
||||
}
|
||||
|
||||
save<T>(key: string, obj: T): Promise<void> {
|
||||
if (obj == null) {
|
||||
return this.remove(key);
|
||||
}
|
||||
// TODO: Remove once foreground/background contexts are separated in browser
|
||||
// Needed to ensure ownership of all memory by the context running the storage service
|
||||
this.store[key] = JSON.stringify(obj);
|
||||
this.updatesSubject.next({ key, updateType: "save" });
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
remove(key: string): Promise<void> {
|
||||
delete this.store[key];
|
||||
this.updatesSubject.next({ key, updateType: "remove" });
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
getBypassCache<T>(key: string): Promise<T> {
|
||||
return this.get<T>(key);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user