Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/src/vs/workbench/common/memento.ts
3292 views
1
/*---------------------------------------------------------------------------------------------
2
* Copyright (c) Microsoft Corporation. All rights reserved.
3
* Licensed under the MIT License. See License.txt in the project root for license information.
4
*--------------------------------------------------------------------------------------------*/
5
6
import { IStorageService, IStorageValueChangeEvent, StorageScope, StorageTarget } from '../../platform/storage/common/storage.js';
7
import { isEmptyObject } from '../../base/common/types.js';
8
import { onUnexpectedError } from '../../base/common/errors.js';
9
import { DisposableStore } from '../../base/common/lifecycle.js';
10
import { Event } from '../../base/common/event.js';
11
12
export type MementoObject = { [key: string]: any };
13
14
export class Memento {
15
16
private static readonly applicationMementos = new Map<string, ScopedMemento>();
17
private static readonly profileMementos = new Map<string, ScopedMemento>();
18
private static readonly workspaceMementos = new Map<string, ScopedMemento>();
19
20
private static readonly COMMON_PREFIX = 'memento/';
21
22
private readonly id: string;
23
24
constructor(id: string, private storageService: IStorageService) {
25
this.id = Memento.COMMON_PREFIX + id;
26
}
27
28
getMemento(scope: StorageScope, target: StorageTarget): MementoObject {
29
switch (scope) {
30
case StorageScope.WORKSPACE: {
31
let workspaceMemento = Memento.workspaceMementos.get(this.id);
32
if (!workspaceMemento) {
33
workspaceMemento = new ScopedMemento(this.id, scope, target, this.storageService);
34
Memento.workspaceMementos.set(this.id, workspaceMemento);
35
}
36
37
return workspaceMemento.getMemento();
38
}
39
40
case StorageScope.PROFILE: {
41
let profileMemento = Memento.profileMementos.get(this.id);
42
if (!profileMemento) {
43
profileMemento = new ScopedMemento(this.id, scope, target, this.storageService);
44
Memento.profileMementos.set(this.id, profileMemento);
45
}
46
47
return profileMemento.getMemento();
48
}
49
50
case StorageScope.APPLICATION: {
51
let applicationMemento = Memento.applicationMementos.get(this.id);
52
if (!applicationMemento) {
53
applicationMemento = new ScopedMemento(this.id, scope, target, this.storageService);
54
Memento.applicationMementos.set(this.id, applicationMemento);
55
}
56
57
return applicationMemento.getMemento();
58
}
59
}
60
}
61
62
onDidChangeValue(scope: StorageScope, disposables: DisposableStore): Event<IStorageValueChangeEvent> {
63
return this.storageService.onDidChangeValue(scope, this.id, disposables);
64
}
65
66
saveMemento(): void {
67
Memento.workspaceMementos.get(this.id)?.save();
68
Memento.profileMementos.get(this.id)?.save();
69
Memento.applicationMementos.get(this.id)?.save();
70
}
71
72
reloadMemento(scope: StorageScope): void {
73
let memento: ScopedMemento | undefined;
74
switch (scope) {
75
case StorageScope.APPLICATION:
76
memento = Memento.applicationMementos.get(this.id);
77
break;
78
case StorageScope.PROFILE:
79
memento = Memento.profileMementos.get(this.id);
80
break;
81
case StorageScope.WORKSPACE:
82
memento = Memento.workspaceMementos.get(this.id);
83
break;
84
}
85
86
memento?.reload();
87
}
88
89
static clear(scope: StorageScope): void {
90
switch (scope) {
91
case StorageScope.WORKSPACE:
92
Memento.workspaceMementos.clear();
93
break;
94
case StorageScope.PROFILE:
95
Memento.profileMementos.clear();
96
break;
97
case StorageScope.APPLICATION:
98
Memento.applicationMementos.clear();
99
break;
100
}
101
}
102
}
103
104
class ScopedMemento {
105
106
private mementoObj: MementoObject;
107
108
constructor(private id: string, private scope: StorageScope, private target: StorageTarget, private storageService: IStorageService) {
109
this.mementoObj = this.doLoad();
110
}
111
112
private doLoad(): MementoObject {
113
try {
114
return this.storageService.getObject<MementoObject>(this.id, this.scope, {});
115
} catch (error) {
116
// Seeing reports from users unable to open editors
117
// from memento parsing exceptions. Log the contents
118
// to diagnose further
119
// https://github.com/microsoft/vscode/issues/102251
120
onUnexpectedError(`[memento]: failed to parse contents: ${error} (id: ${this.id}, scope: ${this.scope}, contents: ${this.storageService.get(this.id, this.scope)})`);
121
}
122
123
return {};
124
}
125
126
getMemento(): MementoObject {
127
return this.mementoObj;
128
}
129
130
reload(): void {
131
132
// Clear old
133
for (const name of Object.getOwnPropertyNames(this.mementoObj)) {
134
delete this.mementoObj[name];
135
}
136
137
// Assign new
138
Object.assign(this.mementoObj, this.doLoad());
139
}
140
141
save(): void {
142
if (!isEmptyObject(this.mementoObj)) {
143
this.storageService.store(this.id, this.mementoObj, this.scope, this.target);
144
} else {
145
this.storageService.remove(this.id, this.scope);
146
}
147
}
148
}
149
150