src/vs/workbench/api/common/extHostFileSystemConsumer.ts

260 LOC · 45 covered · 215 uncovered · 6 ranges · 38 concepts · 1 introducers · 33 tests

File neighbourhood

The centred file is linked to every concept that introduces one of its ranges, every test that runs code from the file, and the gray connector concepts standing between those tests and the file's own introducer concepts. Undirected links join concepts to every file where they introduce source and concepts to the tests they introduce; arrows show specialization between the displayed concepts and bridge only concepts omitted from this view. Concept colors match the source ranges below; connector concepts have no source color and are shown in gray.

Focused file, its introducer and connector concepts, their introduced files, and tests that run code from the file

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 related-file, concept, and source links on this page.

Focused file, its introducer and connector concepts, their introduced files, and tests that run code from the filesrc/vs/workbench/api/common/extHostAuthentication.ts · 1040 LOCcommon/extHostAuthentica…src/vs/workbench/api/common/extHostExtensionService.ts · 1285 LOCcommon/extHostExtensionS…src/vs/workbench/api/common/extHostLanguageModels.ts · 768 LOCcommon/extHostLanguageMo…src/vs/workbench/api/common/extHostLocalizationService.ts · 109 LOCcommon/extHostLocalizati…src/vs/workbench/api/common/extHostManagedSockets.ts · 121 LOCcommon/extHostManagedSoc…src/vs/workbench/api/common/extHostMemento.ts · 122 LOCcommon/extHostMemento.tssrc/vs/workbench/api/common/extHostProgress.ts · 107 LOCcommon/extHostProgress.t…src/vs/workbench/api/common/extHostSecretState.ts · 42 LOCcommon/extHostSecretStat…src/vs/workbench/api/common/extHostSecrets.ts · 51 LOCcommon/extHostSecrets.tssrc/vs/workbench/api/common/extHostStorage.ts · 75 LOCcommon/extHostStorage.tssrc/vs/workbench/api/common/extHostStoragePaths.ts · 95 LOCcommon/extHostStoragePat…src/vs/workbench/api/common/extHostUrls.ts · 70 LOCcommon/extHostUrls.tssrc/vs/workbench/api/common/extHostWindow.ts · 116 LOCcommon/extHostWindow.tssrc/vs/workbench/api/common/extHostXaaAuthProvider.ts · 402 LOCcommon/extHostXaaAuthPro…src/vs/workbench/services/extensions/common/workspaceContains.ts · 139 LOCcommon/workspaceContains…extHostMcp.test|title=ExtHostMcp IAuthMetadata properties should expose readonly properties|occurrence=1, extHostMcp.test|title=ExtHostMcp createAuthMetadata should create IAuthMetadata with fetched server metadata|occurrence=1 · 0 introduced LOCextHostMcp.test|title=Ex…extHostMcp.ts ×1 · 3 introduced LOCextHostMcp.ts ×1extHostMcp.test|title=ExtHostMcp IAuthMetadata update() should handle multiple Bearer challenges and use first scope|occurrence=1 · 0 introduced LOCextHostMcp.test|title=Ex…extHostMcp.test|title=ExtHostMcp IAuthMetadata update() should return false when scopes are the same|occurrence=1 · 0 introduced LOCextHostMcp.test|title=Ex…extHostMcp.test|title=ExtHostMcp IAuthMetadata update() should return true and update scopes when WWW-Authenticate header contains new scopes|occurrence=1 · 0 introduced LOCextHostMcp.test|title=Ex…extHostMcp.test|title=ExtHostMcp IAuthMetadata update() should return false when scopes are same but in different order|occurrence=1 · 0 introduced LOCextHostMcp.test|title=Ex…extHostMcp.test|title=ExtHostMcp IAuthMetadata update() should return true when updating from defined scopes to undefined (no scope in header)|occurrence=1 · 0 introduced LOCextHostMcp.test|title=Ex…extHostMcp.test|title=ExtHostMcp createAuthMetadata should handle non-401 status codes in update()|occurrence=1 · 0 introduced LOCextHostMcp.test|title=Ex…extHostMcp.test|title=ExtHostMcp IAuthMetadata update() should ignore non-Bearer schemes|occurrence=1 · 0 introduced LOCextHostMcp.test|title=Ex…extHostMcp.test|title=ExtHostMcp IAuthMetadata update() should return true when updating from undefined scopes to defined scopes|occurrence=1 · 0 introduced LOCextHostMcp.test|title=Ex…extHostMcp.ts ×1 · 1 introduced LOCextHostMcp.ts ×1extHostMcp.ts ×1 · 2 introduced LOCextHostMcp.ts ×1extHostMcp.ts ×1 · 6 introduced LOCextHostMcp.ts ×1extHostMcp.ts ×1 · 4 introduced LOCextHostMcp.ts ×1extHostMcp.ts ×2 · 4 introduced LOCextHostMcp.ts ×2extHostMcp.ts ×1 · 1 introduced LOCextHostMcp.ts ×1extHostMcp.test|title=ExtHostMcp createAuthMetadata should fall back to default metadata when server metadata fetch fails|occurrence=1 · 0 introduced LOCextHostMcp.test|title=Ex…extHostMcp.ts ×4 · 6 introduced LOCextHostMcp.ts ×4extHostMcp.test|title=ExtHostMcp createAuthMetadata should use scopes from WWW-Authenticate header when resource metadata has none|occurrence=1, extHostMcp.test|title=ExtHostMcp createAuthMetadata should use scopes from WWW-Authenticate header even when resource metadata has scopes_supported|occurrence=1 · 0 introduced LOCextHostMcp.test|title=Ex…extHostMcp.ts ×1 · 2 introduced LOCextHostMcp.ts ×1extHostMcp.ts ×1 · 6 introduced LOCextHostMcp.ts ×1extHostMcp.ts ×4 · 13 introduced LOCextHostMcp.ts ×4extHostMcpNode.ts ×8 · 45 introduced LOCextHostMcpNode.ts ×8extHostMcp.test|title=ExtHostMcp createAuthMetadata should pass launch headers when fetching metadata from same origin|occurrence=1 · 0 introduced LOCextHostMcp.test|title=Ex…extHostMcp.ts ×5 · 25 introduced LOCextHostMcp.ts ×5extHostMcp.test|title=ExtHostMcp createAuthMetadata should handle invalid JSON in resource metadata response|occurrence=1 · 0 introduced LOCextHostMcp.test|title=Ex…extHostMcp.ts ×3 · 23 introduced LOCextHostMcp.ts ×3extHostMcp.ts ×1 · 2 introduced LOCextHostMcp.ts ×1extHostMcp.ts ×8 · 60 introduced LOCextHostMcp.ts ×8extHostMcp.ts ×43 · 874 introduced LOCextHostMcp.ts ×43extensionHostMain.ts ×1 · 2 introduced LOCextensionHostMain.ts ×1reset prepareStackTrace-callback|occurrence=1, extensionHostMain.test|title=ExtensionHostMain#ErrorHandler - Wrapping prepareStackTrace can cause slowdown and eventual stack overflow #184926 prevent rewrapping|occurrence=1 · 0 introduced LOCreset prepareStackTrace-…extensionHostMain.ts ×5 · 26 introduced LOCextensionHostMain.ts ×5f0f2e182082072efdaf0f8e1537d2cce Restored, too many uses before restoration|occurrence=1 · 0 introduced LOCf0f2e182082072efdaf0f8e1…extensionHostMain.ts ×1 · 3 introduced LOCextensionHostMain.ts ×1extensionHostMain.ts ×1 · 3 introduced LOCextensionHostMain.ts ×1extensionHostMain.ts ×11 · 164 introduced LOCextensionHostMain.ts ×11extHostExtensionService.ts ×64 · 1246 introduced LOCextHostExtensionService.…extHostMcp.test|title=ExtHostMcp IAuthMetadata properties should allow undefined scopes|occurrence=1 · introduced test · mocha:v1|namespace=vscode@05c208e9e28d8c1c723fa08f85e2b7a96092e8e5|file=vs/workbench/api/test/common/extHostMcp.test|title=ExtHostMcp IAuthMetadata properties should allow undefined scopes|occurrence=1extHostMcp.test|title=Ex…extHostMcp.test|title=ExtHostMcp IAuthMetadata properties should expose readonly properties|occurrence=1 · introduced test · mocha:v1|namespace=vscode@05c208e9e28d8c1c723fa08f85e2b7a96092e8e5|file=vs/workbench/api/test/common/extHostMcp.test|title=ExtHostMcp IAuthMetadata properties should expose readonly properties|occurrence=1extHostMcp.test|title=Ex…extHostMcp.test|title=ExtHostMcp IAuthMetadata update() should handle multiple Bearer challenges and use first scope|occurrence=1 · introduced test · mocha:v1|namespace=vscode@05c208e9e28d8c1c723fa08f85e2b7a96092e8e5|file=vs/workbench/api/test/common/extHostMcp.test|title=ExtHostMcp IAuthMetadata update() should handle multiple Bearer challenges and use first scope|occurrence=1extHostMcp.test|title=Ex…extHostMcp.test|title=ExtHostMcp IAuthMetadata update() should ignore non-Bearer schemes|occurrence=1 · introduced test · mocha:v1|namespace=vscode@05c208e9e28d8c1c723fa08f85e2b7a96092e8e5|file=vs/workbench/api/test/common/extHostMcp.test|title=ExtHostMcp IAuthMetadata update() should ignore non-Bearer schemes|occurrence=1extHostMcp.test|title=Ex…extHostMcp.test|title=ExtHostMcp IAuthMetadata update() should return false when no WWW-Authenticate header and scopes are already undefined|occurrence=1 · introduced test · mocha:v1|namespace=vscode@05c208e9e28d8c1c723fa08f85e2b7a96092e8e5|file=vs/workbench/api/test/common/extHostMcp.test|title=ExtHostMcp IAuthMetadata update() should return false when no WWW-Authenticate header and scopes are already undefined|occurrence=1extHostMcp.test|title=Ex…extHostMcp.test|title=ExtHostMcp IAuthMetadata update() should return false when scopes are same but in different order|occurrence=1 · introduced test · mocha:v1|namespace=vscode@05c208e9e28d8c1c723fa08f85e2b7a96092e8e5|file=vs/workbench/api/test/common/extHostMcp.test|title=ExtHostMcp IAuthMetadata update() should return false when scopes are same but in different order|occurrence=1extHostMcp.test|title=Ex…extHostMcp.test|title=ExtHostMcp IAuthMetadata update() should return false when scopes are the same|occurrence=1 · introduced test · mocha:v1|namespace=vscode@05c208e9e28d8c1c723fa08f85e2b7a96092e8e5|file=vs/workbench/api/test/common/extHostMcp.test|title=ExtHostMcp IAuthMetadata update() should return false when scopes are the same|occurrence=1extHostMcp.test|title=Ex…extHostMcp.test|title=ExtHostMcp IAuthMetadata update() should return true and update scopes when WWW-Authenticate header contains new scopes|occurrence=1 · introduced test · mocha:v1|namespace=vscode@05c208e9e28d8c1c723fa08f85e2b7a96092e8e5|file=vs/workbench/api/test/common/extHostMcp.test|title=ExtHostMcp IAuthMetadata update() should return true and update scopes when WWW-Authenticate header contains new scopes|occurrence=1extHostMcp.test|title=Ex…extHostMcp.test|title=ExtHostMcp IAuthMetadata update() should return true when updating from defined scopes to undefined (no scope in header)|occurrence=1 · introduced test · mocha:v1|namespace=vscode@05c208e9e28d8c1c723fa08f85e2b7a96092e8e5|file=vs/workbench/api/test/common/extHostMcp.test|title=ExtHostMcp IAuthMetadata update() should return true when updating from defined scopes to undefined (no scope in header)|occurrence=1extHostMcp.test|title=Ex…extHostMcp.test|title=ExtHostMcp IAuthMetadata update() should return true when updating from undefined scopes to defined scopes|occurrence=1 · introduced test · mocha:v1|namespace=vscode@05c208e9e28d8c1c723fa08f85e2b7a96092e8e5|file=vs/workbench/api/test/common/extHostMcp.test|title=ExtHostMcp IAuthMetadata update() should return true when updating from undefined scopes to defined scopes|occurrence=1extHostMcp.test|title=Ex…extHostMcp.test|title=ExtHostMcp createAuthMetadata should create IAuthMetadata with fetched server metadata|occurrence=1 · introduced test · mocha:v1|namespace=vscode@05c208e9e28d8c1c723fa08f85e2b7a96092e8e5|file=vs/workbench/api/test/common/extHostMcp.test|title=ExtHostMcp createAuthMetadata should create IAuthMetadata with fetched server metadata|occurrence=1extHostMcp.test|title=Ex…extHostMcp.test|title=ExtHostMcp createAuthMetadata should fall back to default metadata when server metadata fetch fails|occurrence=1 · introduced test · mocha:v1|namespace=vscode@05c208e9e28d8c1c723fa08f85e2b7a96092e8e5|file=vs/workbench/api/test/common/extHostMcp.test|title=ExtHostMcp createAuthMetadata should fall back to default metadata when server metadata fetch fails|occurrence=1extHostMcp.test|title=Ex…extHostMcp.test|title=ExtHostMcp createAuthMetadata should handle empty scope string in WWW-Authenticate header|occurrence=1 · introduced test · mocha:v1|namespace=vscode@05c208e9e28d8c1c723fa08f85e2b7a96092e8e5|file=vs/workbench/api/test/common/extHostMcp.test|title=ExtHostMcp createAuthMetadata should handle empty scope string in WWW-Authenticate header|occurrence=1extHostMcp.test|title=Ex…extHostMcp.test|title=ExtHostMcp createAuthMetadata should handle invalid JSON in resource metadata response|occurrence=1 · introduced test · mocha:v1|namespace=vscode@05c208e9e28d8c1c723fa08f85e2b7a96092e8e5|file=vs/workbench/api/test/common/extHostMcp.test|title=ExtHostMcp createAuthMetadata should handle invalid JSON in resource metadata response|occurrence=1extHostMcp.test|title=Ex…extHostMcp.test|title=ExtHostMcp createAuthMetadata should handle malformed WWW-Authenticate header gracefully|occurrence=1 · introduced test · mocha:v1|namespace=vscode@05c208e9e28d8c1c723fa08f85e2b7a96092e8e5|file=vs/workbench/api/test/common/extHostMcp.test|title=ExtHostMcp createAuthMetadata should handle malformed WWW-Authenticate header gracefully|occurrence=1extHostMcp.test|title=Ex…extHostMcp.test|title=ExtHostMcp createAuthMetadata should handle non-401 status codes in update()|occurrence=1 · introduced test · mocha:v1|namespace=vscode@05c208e9e28d8c1c723fa08f85e2b7a96092e8e5|file=vs/workbench/api/test/common/extHostMcp.test|title=ExtHostMcp createAuthMetadata should handle non-401 status codes in update()|occurrence=1extHostMcp.test|title=Ex…extHostMcp.test|title=ExtHostMcp createAuthMetadata should pass launch headers when fetching metadata from same origin|occurrence=1 · introduced test · mocha:v1|namespace=vscode@05c208e9e28d8c1c723fa08f85e2b7a96092e8e5|file=vs/workbench/api/test/common/extHostMcp.test|title=ExtHostMcp createAuthMetadata should pass launch headers when fetching metadata from same origin|occurrence=1extHostMcp.test|title=Ex…extHostMcp.test|title=ExtHostMcp createAuthMetadata should use resource_metadata challenge URL from WWW-Authenticate header|occurrence=1 · introduced test · mocha:v1|namespace=vscode@05c208e9e28d8c1c723fa08f85e2b7a96092e8e5|file=vs/workbench/api/test/common/extHostMcp.test|title=ExtHostMcp createAuthMetadata should use resource_metadata challenge URL from WWW-Authenticate header|occurrence=1extHostMcp.test|title=Ex…extHostMcp.test|title=ExtHostMcp createAuthMetadata should use scopes from WWW-Authenticate header even when resource metadata has scopes_supported|occurrence=1 · introduced test · mocha:v1|namespace=vscode@05c208e9e28d8c1c723fa08f85e2b7a96092e8e5|file=vs/workbench/api/test/common/extHostMcp.test|title=ExtHostMcp createAuthMetadata should use scopes from WWW-Authenticate header even when resource metadata has scopes_supported|occurrence=1extHostMcp.test|title=Ex…extHostMcp.test|title=ExtHostMcp createAuthMetadata should use scopes from WWW-Authenticate header when resource metadata has none|occurrence=1 · introduced test · mocha:v1|namespace=vscode@05c208e9e28d8c1c723fa08f85e2b7a96092e8e5|file=vs/workbench/api/test/common/extHostMcp.test|title=ExtHostMcp createAuthMetadata should use scopes from WWW-Authenticate header when resource metadata has none|occurrence=1extHostMcp.test|title=Ex…extensionHostMain.test|title=ExtensionHostMain#ErrorHandler - Wrapping prepareStackTrace can cause slowdown and eventual stack overflow #184926 basics|occurrence=1 · introduced test · mocha:v1|namespace=vscode@05c208e9e28d8c1c723fa08f85e2b7a96092e8e5|file=vs/workbench/api/test/common/extensionHostMain.test|title=ExtensionHostMain#ErrorHandler - Wrapping prepareStackTrace can cause slowdown and eventual stack overflow #184926 basics|occurrence=1extensionHostMain.test|t…f0f2e182082072efdaf0f8e1537d2cce Never restored, separate operations|occurrence=1 · introduced test · mocha:v1|namespace=vscode@05c208e9e28d8c1c723fa08f85e2b7a96092e8e5|file=vs/workbench/api/test/common/extensionHostMain.test|title=ExtensionHostMain#ErrorHandler - Wrapping prepareStackTrace can cause slowdown and eventual stack overflow #184926 https://gist.github.com/thecrypticace/f0f2e182082072efdaf0f8e1537d2cce Never restored, separate operations|occurrence=1f0f2e182082072efdaf0f8e1…f0f2e182082072efdaf0f8e1537d2cce Restored, separate operations|occurrence=1 · introduced test · mocha:v1|namespace=vscode@05c208e9e28d8c1c723fa08f85e2b7a96092e8e5|file=vs/workbench/api/test/common/extensionHostMain.test|title=ExtensionHostMain#ErrorHandler - Wrapping prepareStackTrace can cause slowdown and eventual stack overflow #184926 https://gist.github.com/thecrypticace/f0f2e182082072efdaf0f8e1537d2cce Restored, separate operations|occurrence=1f0f2e182082072efdaf0f8e1…f0f2e182082072efdaf0f8e1537d2cce Restored, too many uses before restoration|occurrence=1 · introduced test · mocha:v1|namespace=vscode@05c208e9e28d8c1c723fa08f85e2b7a96092e8e5|file=vs/workbench/api/test/common/extensionHostMain.test|title=ExtensionHostMain#ErrorHandler - Wrapping prepareStackTrace can cause slowdown and eventual stack overflow #184926 https://gist.github.com/thecrypticace/f0f2e182082072efdaf0f8e1537d2cce Restored, too many uses before restoration|occurrence=1f0f2e182082072efdaf0f8e1…extensionHostMain.test|title=ExtensionHostMain#ErrorHandler - Wrapping prepareStackTrace can cause slowdown and eventual stack overflow #184926 prevent rewrapping|occurrence=1 · introduced test · mocha:v1|namespace=vscode@05c208e9e28d8c1c723fa08f85e2b7a96092e8e5|file=vs/workbench/api/test/common/extensionHostMain.test|title=ExtensionHostMain#ErrorHandler - Wrapping prepareStackTrace can cause slowdown and eventual stack overflow #184926 prevent rewrapping|occurrence=1extensionHostMain.test|t…reset prepareStackTrace-callback|occurrence=1 · introduced test · mocha:v1|namespace=vscode@05c208e9e28d8c1c723fa08f85e2b7a96092e8e5|file=vs/workbench/api/test/common/extensionHostMain.test|title=ExtensionHostMain#ErrorHandler - Wrapping prepareStackTrace can cause slowdown and eventual stack overflow #184926 set/reset prepareStackTrace-callback|occurrence=1reset prepareStackTrace-…extensionHostMain.test|title=ExtensionHostMain#ErrorHandler - Wrapping prepareStackTrace can cause slowdown and eventual stack overflow #184926 wrap prepareStackTrace-callback|occurrence=1 · introduced test · mocha:v1|namespace=vscode@05c208e9e28d8c1c723fa08f85e2b7a96092e8e5|file=vs/workbench/api/test/common/extensionHostMain.test|title=ExtensionHostMain#ErrorHandler - Wrapping prepareStackTrace can cause slowdown and eventual stack overflow #184926 wrap prepareStackTrace-callback|occurrence=1extensionHostMain.test|t…extHostMcpNode.test|title=extHostMcpNode - escapeCmdArg does not add stray ^ to argument values|occurrence=1 · introduced test · mocha:v1|namespace=vscode@05c208e9e28d8c1c723fa08f85e2b7a96092e8e5|file=vs/workbench/api/test/node/extHostMcpNode.test|title=extHostMcpNode - escapeCmdArg does not add stray ^ to argument values|occurrence=1extHostMcpNode.test|titl…extHostMcpNode.test|title=extHostMcpNode - escapeCmdArg doubles embedded double quotes (cmd.exe convention)|occurrence=1 · introduced test · mocha:v1|namespace=vscode@05c208e9e28d8c1c723fa08f85e2b7a96092e8e5|file=vs/workbench/api/test/node/extHostMcpNode.test|title=extHostMcpNode - escapeCmdArg doubles embedded double quotes (cmd.exe convention)|occurrence=1extHostMcpNode.test|titl…extHostMcpNode.test|title=extHostMcpNode - escapeCmdArg neutralizes cmd.exe metacharacters inside quotes (CVE-2024-27980)|occurrence=1 · introduced test · mocha:v1|namespace=vscode@05c208e9e28d8c1c723fa08f85e2b7a96092e8e5|file=vs/workbench/api/test/node/extHostMcpNode.test|title=extHostMcpNode - escapeCmdArg neutralizes cmd.exe metacharacters inside quotes (CVE-2024-27980)|occurrence=1extHostMcpNode.test|titl…extHostMcpNode.test|title=extHostMcpNode - escapeCmdArg preserves paths with parentheses without injecting ^|occurrence=1 · introduced test · mocha:v1|namespace=vscode@05c208e9e28d8c1c723fa08f85e2b7a96092e8e5|file=vs/workbench/api/test/node/extHostMcpNode.test|title=extHostMcpNode - escapeCmdArg preserves paths with parentheses without injecting ^|occurrence=1extHostMcpNode.test|titl…extHostMcpNode.test|title=extHostMcpNode - escapeCmdArg preserves paths with spaces|occurrence=1 · introduced test · mocha:v1|namespace=vscode@05c208e9e28d8c1c723fa08f85e2b7a96092e8e5|file=vs/workbench/api/test/node/extHostMcpNode.test|title=extHostMcpNode - escapeCmdArg preserves paths with spaces|occurrence=1extHostMcpNode.test|titl…extHostMcpNode.test|title=extHostMcpNode - escapeCmdArg wraps simple values in double quotes|occurrence=1 · introduced test · mocha:v1|namespace=vscode@05c208e9e28d8c1c723fa08f85e2b7a96092e8e5|file=vs/workbench/api/test/node/extHostMcpNode.test|title=extHostMcpNode - escapeCmdArg wraps simple values in double quotes|occurrence=1extHostMcpNode.test|titl…Focused file · src/vs/workbench/api/common/extHostFileSystemConsumer.ts · 260 LOCcommon/extHostFileSystem…

Graph controls are ready.

Interactive rendering requires JavaScript and WebGL. Use the related-file, concept, and source links on this page while the interactive map is unavailable.

1 > /*--------------------------------------------------------------------------------------------- extHostExtensionService.ts ×64
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 { MainContext, MainThreadFileSystemShape } from './extHost.protocol.js';
7 > import type * as vscode from 'vscode';
8 > import * as files from '../../../platform/files/common/files.js';
9 > import { FileSystemError } from './extHostTypes.js';
10 > import { VSBuffer } from '../../../base/common/buffer.js';
11 > import { createDecorator } from '../../../platform/instantiation/common/instantiation.js';
12 > import { IExtHostRpcService } from './extHostRpcService.js';
13 > import { IExtHostFileSystemInfo } from './extHostFileSystemInfo.js';
14 > import { IDisposable, toDisposable } from '../../../base/common/lifecycle.js';
15 > import { ResourceQueue } from '../../../base/common/async.js';
16 > import { IExtUri, extUri, extUriIgnorePathCase } from '../../../base/common/resources.js';
17 > import { Schemas } from '../../../base/common/network.js';
18 > import { IMarkdownString } from '../../../base/common/htmlContent.js';
19 >
20 > export class ExtHostConsumerFileSystem {
21 >
22 > readonly _serviceBrand: undefined;
23 >
24 > readonly value: vscode.FileSystem;
25 >
26 > private readonly _proxy: MainThreadFileSystemShape;
27 > private readonly _fileSystemProvider = new Map<string, { impl: vscode.FileSystemProvider; extUri: IExtUri; isReadonly: boolean }>();
28 >
29 > private readonly _writeQueue = new ResourceQueue();
30 >
31 > constructor(
32 @IExtHostRpcService extHostRpc: IExtHostRpcService,
33 @IExtHostFileSystemInfo fileSystemInfo: IExtHostFileSystemInfo,
34 ) {
35 this._proxy = extHostRpc.getProxy(MainContext.MainThreadFileSystem);
36 const that = this;
37
38 this.value = Object.freeze({
39 async stat(uri: vscode.Uri): Promise<vscode.FileStat> {
40 try {
41 let stat;
42
43 const provider = that._fileSystemProvider.get(uri.scheme);
44 if (provider) {
45 // use shortcut
46 await that._proxy.$ensureActivation(uri.scheme);
47 stat = await provider.impl.stat(uri);
48 } else {
49 stat = await that._proxy.$stat(uri);
50 }
51
52 return {
53 type: stat.type,
54 ctime: stat.ctime,
55 mtime: stat.mtime,
56 size: stat.size,
57 permissions: stat.permissions === files.FilePermission.Readonly ? 1 : undefined
58 };
59 } catch (err) {
60 ExtHostConsumerFileSystem._handleError(err);
61 }
62 },
63 async readDirectory(uri: vscode.Uri): Promise<[string, vscode.FileType][]> {
64 try {
65 const provider = that._fileSystemProvider.get(uri.scheme);
66 if (provider) {
67 // use shortcut
68 await that._proxy.$ensureActivation(uri.scheme);
69 return (await provider.impl.readDirectory(uri)).slice(); // safe-copy
70 } else {
71 return await that._proxy.$readdir(uri);
72 }
73 } catch (err) {
74 return ExtHostConsumerFileSystem._handleError(err);
75 }
76 },
77 async createDirectory(uri: vscode.Uri): Promise<void> {
78 try {
79 const provider = that._fileSystemProvider.get(uri.scheme);
80 if (provider && !provider.isReadonly) {
81 // use shortcut
82 await that._proxy.$ensureActivation(uri.scheme);
83 return await that.mkdirp(provider.impl, provider.extUri, uri);
84 } else {
85 return await that._proxy.$mkdir(uri);
86 }
87 } catch (err) {
88 return ExtHostConsumerFileSystem._handleError(err);
89 }
90 },
91 async readFile(uri: vscode.Uri): Promise<Uint8Array> {
92 try {
93 const provider = that._fileSystemProvider.get(uri.scheme);
94 if (provider) {
95 // use shortcut
96 await that._proxy.$ensureActivation(uri.scheme);
97 return (await provider.impl.readFile(uri)).slice(); // safe-copy
98 } else {
99 const buff = await that._proxy.$readFile(uri);
100 return buff.buffer;
101 }
102 } catch (err) {
103 return ExtHostConsumerFileSystem._handleError(err);
104 }
105 },
106 async writeFile(uri: vscode.Uri, content: Uint8Array): Promise<void> {
107 try {
108 const provider = that._fileSystemProvider.get(uri.scheme);
109 if (provider && !provider.isReadonly) {
110 // use shortcut
111 await that._proxy.$ensureActivation(uri.scheme);
112 await that.mkdirp(provider.impl, provider.extUri, provider.extUri.dirname(uri));
113 return await that._writeQueue.queueFor(uri, () => Promise.resolve(provider.impl.writeFile(uri, content, { create: true, overwrite: true })));
114 } else {
115 return await that._proxy.$writeFile(uri, VSBuffer.wrap(content));
116 }
117 } catch (err) {
118 return ExtHostConsumerFileSystem._handleError(err);
119 }
120 },
121 async delete(uri: vscode.Uri, options?: { recursive?: boolean; useTrash?: boolean }): Promise<void> {
122 try {
123 const provider = that._fileSystemProvider.get(uri.scheme);
124 if (provider && !provider.isReadonly && !options?.useTrash /* no shortcut: use trash */) {
125 // use shortcut
126 await that._proxy.$ensureActivation(uri.scheme);
127 return await provider.impl.delete(uri, { recursive: false, ...options });
128 } else {
129 return await that._proxy.$delete(uri, { recursive: false, useTrash: false, atomic: false, ...options });
130 }
131 } catch (err) {
132 return ExtHostConsumerFileSystem._handleError(err);
133 }
134 },
135 async rename(oldUri: vscode.Uri, newUri: vscode.Uri, options?: { overwrite?: boolean }): Promise<void> {
136 try {
137 // no shortcut: potentially involves different schemes, does mkdirp
138 return await that._proxy.$rename(oldUri, newUri, { ...{ overwrite: false }, ...options });
139 } catch (err) {
140 return ExtHostConsumerFileSystem._handleError(err);
141 }
142 },
143 async copy(source: vscode.Uri, destination: vscode.Uri, options?: { overwrite?: boolean }): Promise<void> {
144 try {
145 // no shortcut: potentially involves different schemes, does mkdirp
146 return await that._proxy.$copy(source, destination, { ...{ overwrite: false }, ...options });
147 } catch (err) {
148 return ExtHostConsumerFileSystem._handleError(err);
149 }
150 },
151 isWritableFileSystem(scheme: string): boolean | undefined {
152 const capabilities = fileSystemInfo.getCapabilities(scheme);
153 if (typeof capabilities === 'number') {
154 return !(capabilities & files.FileSystemProviderCapabilities.Readonly);
155 }
156 return undefined;
157 }
158 });
159 }
161 > private async mkdirp(provider: vscode.FileSystemProvider, providerExtUri: IExtUri, directory: vscode.Uri): Promise<void> {
162 const directoriesToCreate: string[] = [];
163
164 while (!providerExtUri.isEqual(directory, providerExtUri.dirname(directory))) {
165 try {
166 const stat = await provider.stat(directory);
167 if ((stat.type & files.FileType.Directory) === 0) {
168 throw FileSystemError.FileExists(`Unable to create folder '${directory.scheme === Schemas.file ? directory.fsPath : directory.toString(true)}' that already exists but is not a directory`);
169 }
170
171 break; // we have hit a directory that exists -> good
172 } catch (error) {
173 if (files.toFileSystemProviderErrorCode(error) !== files.FileSystemProviderErrorCode.FileNotFound) {
174 throw error;
175 }
176
177 // further go up and remember to create this directory
178 directoriesToCreate.push(providerExtUri.basename(directory));
179 directory = providerExtUri.dirname(directory);
180 }
181 }
182
183 for (let i = directoriesToCreate.length - 1; i >= 0; i--) {
184 directory = providerExtUri.joinPath(directory, directoriesToCreate[i]);
185
186 try {
187 await provider.createDirectory(directory);
188 } catch (error) {
189 if (files.toFileSystemProviderErrorCode(error) !== files.FileSystemProviderErrorCode.FileExists) {
190 // For mkdirp() we tolerate that the mkdir() call fails
191 // in case the folder already exists. This follows node.js
192 // own implementation of fs.mkdir({ recursive: true }) and
193 // reduces the chances of race conditions leading to errors
194 // if multiple calls try to create the same folders
195 // As such, we only throw an error here if it is other than
196 // the fact that the file already exists.
197 // (see also https://github.com/microsoft/vscode/issues/89834)
198 throw error;
199 }
200 }
201 }
202 }
204 > private static _handleError(err: any): never {
205 // desired error type
206 if (err instanceof FileSystemError) {
207 throw err;
208 }
209
210 // file system provider error
211 if (err instanceof files.FileSystemProviderError) {
212 switch (err.code) {
213 case files.FileSystemProviderErrorCode.FileExists: throw FileSystemError.FileExists(err.message);
214 case files.FileSystemProviderErrorCode.FileNotFound: throw FileSystemError.FileNotFound(err.message);
215 case files.FileSystemProviderErrorCode.FileNotADirectory: throw FileSystemError.FileNotADirectory(err.message);
216 case files.FileSystemProviderErrorCode.FileIsADirectory: throw FileSystemError.FileIsADirectory(err.message);
217 case files.FileSystemProviderErrorCode.NoPermissions: throw FileSystemError.NoPermissions(err.message);
218 case files.FileSystemProviderErrorCode.Unavailable: throw FileSystemError.Unavailable(err.message);
219
220 default: throw new FileSystemError(err.message, err.name as files.FileSystemProviderErrorCode);
221 }
222 }
223
224 // generic error
225 if (!(err instanceof Error)) {
226 throw new FileSystemError(String(err));
227 }
228
229 // no provider (unknown scheme) error
230 if (err.name === 'ENOPRO' || err.message.includes('ENOPRO')) {
231 throw FileSystemError.Unavailable(err.message);
232 }
233
234 // file system error
235 switch (err.name) {
236 case files.FileSystemProviderErrorCode.FileExists: throw FileSystemError.FileExists(err.message);
237 case files.FileSystemProviderErrorCode.FileNotFound: throw FileSystemError.FileNotFound(err.message);
238 case files.FileSystemProviderErrorCode.FileNotADirectory: throw FileSystemError.FileNotADirectory(err.message);
239 case files.FileSystemProviderErrorCode.FileIsADirectory: throw FileSystemError.FileIsADirectory(err.message);
240 case files.FileSystemProviderErrorCode.NoPermissions: throw FileSystemError.NoPermissions(err.message);
241 case files.FileSystemProviderErrorCode.Unavailable: throw FileSystemError.Unavailable(err.message);
242
243 default: throw new FileSystemError(err.message, err.name as files.FileSystemProviderErrorCode);
244 }
245 }
247 > // ---
248 >
249 > addFileSystemProvider(scheme: string, provider: vscode.FileSystemProvider, options?: { isCaseSensitive?: boolean; isReadonly?: boolean | IMarkdownString }): IDisposable {
250 this._fileSystemProvider.set(scheme, { impl: provider, extUri: options?.isCaseSensitive ? extUri : extUriIgnorePathCase, isReadonly: !!options?.isReadonly });
251 return toDisposable(() => this._fileSystemProvider.delete(scheme));
252 }
254 > getFileSystemProviderExtUri(scheme: string) {
255 return this._fileSystemProvider.get(scheme)?.extUri ?? extUri;
256 }
258 >
259 > export interface IExtHostConsumerFileSystem extends ExtHostConsumerFileSystem { }
260 > export const IExtHostConsumerFileSystem = createDecorator<IExtHostConsumerFileSystem>('IExtHostConsumerFileSystem');