stateService.ts ×16

Frontier kind: Code frontier

unlabeled · c_491a810ffe56

7 tests · 14218 LOC · 68 files · introduces 0 tests · 141 LOC · 2 files

Introduces — evidence that enters the hierarchy at this concept

Code
18 ranges141 lines · 2 files
Tests
0 tests

Contains — complete concept membership

All code (extent)
2158 ranges14218 lines · 68 files · Browse complete extent
All tests (intent)
7 testsBrowse complete intent

Neighbourhood graph

The orange circle is the focus. Violet and green circles are every ancestor and descendant, broader and narrower, at any distance; blue squares and pink diamonds are the introduced files and exact introduced tests of every visible concept, not only the focus's. Arrows point from broader to narrower concepts and bridge only concepts omitted from this view. Undirected links show source or test introduction. Concept and file size follows LOC; exact test nodes use test-count units.

Introduced files, introduced tests, and structurally relevant concept specialization

In the embedded map, ordinary wheel input scrolls the page; use the visible controls to zoom and drag to pan. Open the full-screen map for canvas navigation: wheel pans, Ctrl/Command plus wheel zooms, and arrow keys pan when this region is focused. On touch screens, open the full-screen map to pan or pinch. If JavaScript or WebGL is unavailable, use the native relationship evidence on this page.

Graph controls are ready.

Interactive rendering requires JavaScript and WebGL. Use the native relationship evidence on this page while the interactive map is unavailable.

Native relationship evidence

Every exact file and test below is linked only from the concept that introduces it.

Introduced tests

Every collected test enters the hierarchy at exactly one concept.

No tests are introduced at this concept. Its intent tests are introduced by other concepts.

Introduced code

Every collected source range enters the hierarchy at exactly one concept.

2 files ranked by introduced lines: 141 introduced LOC across 18 ranges. Expand a file to inspect source; the > gutter marks introduced lines.

src/vs/platform/state/node/stateService.ts 126 introduced LOC · 16 ranges

Open complete file

1 > /*--------------------------------------------------------------------------------------------- stateService.ts
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 { ThrottledDelayer } from '../../../base/common/async.js';
7 > import { VSBuffer } from '../../../base/common/buffer.js';
8 > import { Disposable } from '../../../base/common/lifecycle.js';
9 > import { isUndefined, isUndefinedOrNull } from '../../../base/common/types.js';
10 > import { URI } from '../../../base/common/uri.js';
11 > import { IEnvironmentService } from '../../environment/common/environment.js';
12 > import { FileOperationError, FileOperationResult, IFileService } from '../../files/common/files.js';
13 > import { ILogService } from '../../log/common/log.js';
14 > import { IStateReadService, IStateService } from './state.js';
15 >
16 > type StorageDatabase = { [key: string]: unknown };
17 >
18 > export const enum SaveStrategy {
19 > IMMEDIATE,
20 > DELAYED
21 > }
22 >
23 > export class FileStorage extends Disposable {
24 >
25 > private storage: StorageDatabase = Object.create(null);
26 > private lastSavedStorageContents = '';
27 >
28 > private readonly flushDelayer: ThrottledDelayer<void>;
29 >
30 > private initializing: Promise<void> | undefined = undefined;
31 > private closing: Promise<void> | undefined = undefined;
32 >
33 > constructor(
34 > private readonly storagePath: URI,
35 > saveStrategy: SaveStrategy,
36 > private readonly logService: ILogService,
37 > private readonly fileService: IFileService,
38 > ) {
39 > super();
40 >
41 > this.flushDelayer = this._register(new ThrottledDelayer<void>(saveStrategy === SaveStrategy.IMMEDIATE ? 0 : 100 /* buffer saves over a short time */));
42 > }
43 >
44 > init(): Promise<void> {
45 if (!this.initializing) {
46 this.initializing = this.doInit();
49 return this.initializing;
50 }
52 > private async doInit(): Promise<void> {
53 try {
54 this.lastSavedStorageContents = (await this.fileService.readFile(this.storagePath)).value.toString();
60 }
61 }
63 > getItem<T>(key: string, defaultValue: T): T;
64 > getItem<T>(key: string, defaultValue?: T): T | undefined;
65 > getItem<T>(key: string, defaultValue?: T): T | undefined {
66 const res = this.storage[key];
67 if (isUndefinedOrNull(res)) {
71 return res as T;
72 }
74 > setItem(key: string, data?: object | string | number | boolean | undefined | null): void {
75 > this.setItems([{ key, data }]);
76 > }
77 >
78 > setItems(items: readonly { key: string; data?: object | string | number | boolean | undefined | null }[]): void {
79 > let save = false;
80 >
81 > for (const { key, data } of items) {
82 >
83 > // Shortcut for data that did not change
84 > if (this.storage[key] === data) {
85 continue;
86 }
88 > // Remove items when they are undefined or null
89 > if (isUndefinedOrNull(data)) {
90 if (!isUndefined(this.storage[key])) {
91 this.storage[key] = undefined;
93 }
94 }
96 > // Otherwise add an item
97 > else {
98 > this.storage[key] = data;
99 > save = true;
100 > }
101 > }
102 >
103 > if (save) {
104 > this.save();
105 > }
106 > }
107 >
108 > removeItem(key: string): void {
109
110 // Only update if the key is actually present (not undefined)
114 }
115 }
117 > private async save(): Promise<void> {
118 > if (this.closing) {
119 return; // already about to close
120 }
122 > return this.flushDelayer.trigger(() => this.doSave());
123 > }
124 >
125 > private async doSave(): Promise<void> {
126 > if (!this.initializing) {
127 return; // if we never initialized, we should not save our state
128 }
144 this.logService.error(error);
145 }
146 > } stateService.ts
147 >
148 > async close(): Promise<void> {
149 > if (!this.closing) {
150 > this.closing = this.flushDelayer.trigger(() => this.doSave(), 0 /* as soon as possible */);
151 > }
152 >
153 > return this.closing;
154 > }
155 > }
156 >
157 > export class StateReadonlyService extends Disposable implements IStateReadService {
158 >
159 > declare readonly _serviceBrand: undefined;
160 >
161 > protected readonly fileStorage: FileStorage;
162 >
163 > constructor(
164 saveStrategy: SaveStrategy,
165 @IEnvironmentService environmentService: IEnvironmentService,
171 this.fileStorage = this._register(new FileStorage(environmentService.stateResource, saveStrategy, logService, fileService));
172 }
174 > async init(): Promise<void> {
175 await this.fileStorage.init();
176 }
178 > getItem<T>(key: string, defaultValue: T): T;
179 > getItem<T>(key: string, defaultValue?: T): T | undefined;
180 > getItem<T>(key: string, defaultValue?: T): T | undefined {
181 return this.fileStorage.getItem(key, defaultValue);
182 }
183 > } stateService.ts
184 >
185 > export class StateService extends StateReadonlyService implements IStateService {
186 >
187 > declare readonly _serviceBrand: undefined;
188 >
189 > setItem(key: string, data?: object | string | number | boolean | undefined | null): void {
190 this.fileStorage.setItem(key, data);
191 }
193 > setItems(items: readonly { key: string; data?: object | string | number | boolean | undefined | null }[]): void {
194 this.fileStorage.setItems(items);
195 }
197 > removeItem(key: string): void {
198 this.fileStorage.removeItem(key);
199 }
201 > close(): Promise<void> {
202 return this.fileStorage.close();
203 }
204 > } stateService.ts
src/vs/base/node/pfs.ts 15 introduced LOC · 2 ranges

Open complete file

454 return fs.writeFileSync(path, data, { mode: ensuredOptions.mode, flag: ensuredOptions.flag });
455 }
456 > pfs.ts
457 > // Open the file with same flags and mode as fs.writeFile()
458 > const fd = fs.openSync(path, ensuredOptions.flag, ensuredOptions.mode);
459 >
460 > try {
461 >
462 > // It is valid to pass a fd handle to fs.writeFile() and this will keep the handle open!
463 > fs.writeFileSync(fd, data);
464 >
465 > // Flush contents (not metadata) of the file to disk
466 > try {
467 > fs.fdatasyncSync(fd); // https://github.com/microsoft/vscode/issues/9589
468 > } catch (syncError) {
469 console.warn('[node.js fs] fdatasyncSync is now disabled for this session because it failed: ', syncError);
470 configureFlushOnWrite(false);
471 }
472 } finally {
473 > fs.closeSync(fd); pfs.ts
474 > }
475 }
476