From e28c9ab287f2e1802c0d6ef28e950404e591d615 Mon Sep 17 00:00:00 2001 From: Asher Date: Fri, 6 Nov 2020 22:47:51 -0600 Subject: [PATCH 01/13] Update VS Code to 1.51.1 --- ci/dev/vscode.patch | 186 ++++++++++++++++++++++---------------------- lib/vscode | 2 +- 2 files changed, 92 insertions(+), 96 deletions(-) diff --git a/ci/dev/vscode.patch b/ci/dev/vscode.patch index 83c8d994..7cd67f3c 100644 --- a/ci/dev/vscode.patch +++ b/ci/dev/vscode.patch @@ -12,12 +12,12 @@ index b7f5b58c8ede171be547c56b61ce76f79a3accc3..856fbd8c67460fe099d7fbee1475e906 coverage/ diff --git a/.yarnrc b/.yarnrc deleted file mode 100644 -index 3c6eccfb102f2084d16395d70d65f05a91b6d47b..0000000000000000000000000000000000000000 +index d97527dab46aa4e7aa2df386bda3a8b4f93fcb80..0000000000000000000000000000000000000000 --- a/.yarnrc +++ /dev/null @@ -1,3 +0,0 @@ --disturl "https://atom.io/download/electron" --target "9.2.1" +-disturl "https://electronjs.org/headers" +-target "9.3.3" -runtime "electron" diff --git a/build/gulpfile.reh.js b/build/gulpfile.reh.js index 5f367d1f0777d2cb46ad47e376337900733981b5..ba74af1d61a00ce42020418126e62879397f57bf 100644 @@ -66,10 +66,10 @@ index 64397034461b1661f82007c141cbf4c039a3b722..c53dccf4dc0a99122ed96cf10c2eb632 \ No newline at end of file +console.log(nodePath); diff --git a/build/lib/util.ts b/build/lib/util.ts -index 035c7e95ea3006bb3dabd68bbf54db80de4aaaf2..4ff8dcfe6b21a0ec8064ebc7bb05506b8f1faa91 100644 +index c0a0d9619d736c6558b0b91e6c7537c1a06cc947..48853bc6201a602cadbef47a8f46281be93421e9 100644 --- a/build/lib/util.ts +++ b/build/lib/util.ts -@@ -322,6 +322,7 @@ export function streamToPromise(stream: NodeJS.ReadWriteStream): Promise { +@@ -336,6 +336,7 @@ export function streamToPromise(stream: NodeJS.ReadWriteStream): Promise { } export function getElectronVersion(): string { @@ -223,7 +223,7 @@ index 2d754bf4054713f53beed030f9211b33532c1b4b..708b7e40a662e4ca93420992bf7a5af0 return typeof navigator !== 'undefined' && vscode.env.uiKind === vscode.UIKind.Web; } diff --git a/package.json b/package.json -index 770b44b0c1ff53d903b7680ede27715376df00f2..b27ab71647a3e7c4b6076ba4fdb8fde20fa73bb0 100644 +index 28f8a69a2a91f9cb9f4dbd73ed3e689b2b3afe84..b5f5b10004d3e36092a30f685938a606b333c465 100644 --- a/package.json +++ b/package.json @@ -46,7 +46,11 @@ @@ -236,17 +236,17 @@ index 770b44b0c1ff53d903b7680ede27715376df00f2..b27ab71647a3e7c4b6076ba4fdb8fde2 + "@coder/node-browser": "^1.0.8", + "@coder/requirefs": "^1.1.5", "applicationinsights": "1.0.8", - "chokidar": "3.4.2", + "chokidar": "3.4.3", "graceful-fs": "4.2.3", @@ -60,6 +64,7 @@ "native-keymap": "2.2.0", "native-watchdog": "1.3.0", "node-pty": "0.10.0-beta17", + "rimraf": "^2.2.8", - "semver-umd": "^5.5.7", "spdlog": "^0.11.1", "sudo-prompt": "9.1.1", -@@ -160,7 +165,6 @@ + "tas-client-umd": "0.1.2", +@@ -161,7 +166,6 @@ "pump": "^1.0.1", "queue": "3.0.6", "rcedit": "^1.1.0", @@ -254,7 +254,7 @@ index 770b44b0c1ff53d903b7680ede27715376df00f2..b27ab71647a3e7c4b6076ba4fdb8fde2 "sinon": "^1.17.2", "source-map": "^0.4.4", "style-loader": "^1.0.0", -@@ -192,5 +196,8 @@ +@@ -193,5 +197,8 @@ "windows-foreground-love": "0.2.0", "windows-mutex": "0.3.0", "windows-process-tree": "0.2.4" @@ -264,7 +264,7 @@ index 770b44b0c1ff53d903b7680ede27715376df00f2..b27ab71647a3e7c4b6076ba4fdb8fde2 } } diff --git a/product.json b/product.json -index ecfb44dd74e09fc2ff1e902bea9396c2046fb9e6..026f78c698df50cfd1c2debb9823aacdcb4f7c71 100644 +index 7cab6d1b9f3b84bfc703856e93773a293fd198cf..31d3d5a943192eee791e1121415b436dc1ed3822 100644 --- a/product.json +++ b/product.json @@ -20,7 +20,7 @@ @@ -334,15 +334,13 @@ index 3361d83be5b7c3d08bdbfbe6947942a4695882c6..69ead8484e042bbad7075659f8e47f07 // Native environment diff --git a/src/vs/base/common/processes.ts b/src/vs/base/common/processes.ts -index c52f7b3774f399d3fa161682316b20d807072806..08a87fa970f159f84691c5068cf5e38f0926015c 100644 +index 17895a8510bca40924524dc107c33305c4783c45..ba019b43084e3998ab399108968c3c765a79eb32 100644 --- a/src/vs/base/common/processes.ts +++ b/src/vs/base/common/processes.ts -@@ -110,7 +110,8 @@ export function sanitizeProcessEnvironment(env: IProcessEnvironment, ...preserve - /^ELECTRON_.+$/, - /^GOOGLE_API_KEY$/, +@@ -112,6 +112,7 @@ export function sanitizeProcessEnvironment(env: IProcessEnvironment, ...preserve /^VSCODE_.+$/, -- /^SNAP(|_.*)$/ -+ /^SNAP(|_.*)$/, + /^SNAP(|_.*)$/, + /^GDK_PIXBUF_.+$/, + /^CODE_SERVER_.+$/, ]; const envKeys = Object.keys(env); @@ -529,7 +527,7 @@ index 0ef8b9dc81419b53b27cf111fb206d72ba56bada..62a79602a831bca0dc62ad57dc10a937 // If no workspace is provided through the URL, check for config attribute from server if (!foundWorkspace) { diff --git a/src/vs/platform/environment/common/argv.ts b/src/vs/platform/environment/common/argv.ts -index 2ac99a2120ec461703c2ff85da8b5379125c5d96..77450df65524b0daed61309614941195f5294c1d 100644 +index 409bb7e1960c9c06485a6f6d7f39b2efce451d56..f27b651c49ea3fc92b03e31eb64c1cf27c7e4433 100644 --- a/src/vs/platform/environment/common/argv.ts +++ b/src/vs/platform/environment/common/argv.ts @@ -7,6 +7,8 @@ @@ -542,10 +540,10 @@ index 2ac99a2120ec461703c2ff85da8b5379125c5d96..77450df65524b0daed61309614941195 'folder-uri'?: string[]; // undefined or array of 1 or more 'file-uri'?: string[]; // undefined or array of 1 or more diff --git a/src/vs/platform/environment/common/environment.ts b/src/vs/platform/environment/common/environment.ts -index eebf675762d57ddd7072b3e4182a9864c94ec81c..5c18cd4420c5f85724148bb7df14c62dfe0b34bf 100644 +index 21b4d719cec1a724bbad407aeec38db9eb8d6f5a..edf46f097bf11bfb8883d38d38ee78b735f35b3f 100644 --- a/src/vs/platform/environment/common/environment.ts +++ b/src/vs/platform/environment/common/environment.ts -@@ -111,6 +111,8 @@ export interface INativeEnvironmentService extends IEnvironmentService { +@@ -122,6 +122,8 @@ export interface INativeEnvironmentService extends IEnvironmentService { extensionsPath?: string; extensionsDownloadPath: string; builtinExtensionsPath: string; @@ -555,7 +553,7 @@ index eebf675762d57ddd7072b3e4182a9864c94ec81c..5c18cd4420c5f85724148bb7df14c62d // --- Smoke test support driverHandle?: string; diff --git a/src/vs/platform/environment/node/argv.ts b/src/vs/platform/environment/node/argv.ts -index 662547909e57ba556c10177a29beac775cc86c80..eeaba21664ed5d797d1f08f0bd77ee075354ffe5 100644 +index 149e6ffb41a82f1a69cf37f105a31872ad4af8b4..ed99aab42b31bc2ab804391b6e3f4c7ff67d9259 100644 --- a/src/vs/platform/environment/node/argv.ts +++ b/src/vs/platform/environment/node/argv.ts @@ -54,6 +54,8 @@ export const OPTIONS: OptionDescriptions> = { @@ -567,16 +565,16 @@ index 662547909e57ba556c10177a29beac775cc86c80..eeaba21664ed5d797d1f08f0bd77ee07 'list-extensions': { type: 'boolean', cat: 'e', description: localize('listExtensions', "List the installed extensions.") }, 'show-versions': { type: 'boolean', cat: 'e', description: localize('showVersions', "Show versions of installed extensions, when using --list-extension.") }, 'category': { type: 'string', cat: 'e', description: localize('category', "Filters installed extensions by provided category, when using --list-extension.") }, -@@ -316,4 +318,3 @@ export function buildHelpMessage(productName: string, executableName: string, ve +@@ -318,4 +320,3 @@ export function buildHelpMessage(productName: string, executableName: string, ve export function buildVersionMessage(version: string | undefined, commit: string | undefined): string { return `${version || localize('unknownVersion', "Unknown version")}\n${commit || localize('unknownCommit', "Unknown commit")}\n${process.arch}`; } - diff --git a/src/vs/platform/environment/node/environmentService.ts b/src/vs/platform/environment/node/environmentService.ts -index 16057c43a0807fb894a94d7d658e7d24c9db173a..d8c40c94dce474f441acbbf114e53694e3b101c5 100644 +index 80f68fb1decfd1c4fa1bcc30840900240df83f76..d4478b0000a511af11647876a536b8147163f9f8 100644 --- a/src/vs/platform/environment/node/environmentService.ts +++ b/src/vs/platform/environment/node/environmentService.ts -@@ -145,6 +145,13 @@ export class NativeEnvironmentService implements INativeEnvironmentService { +@@ -138,6 +138,13 @@ export class NativeEnvironmentService implements INativeEnvironmentService { return resources.joinPath(this.userHome, product.dataFolderName, 'extensions').fsPath; } @@ -591,10 +589,10 @@ index 16057c43a0807fb894a94d7d658e7d24c9db173a..d8c40c94dce474f441acbbf114e53694 get extensionDevelopmentLocationURI(): URI[] | undefined { const s = this._args.extensionDevelopmentPath; diff --git a/src/vs/platform/extensionManagement/node/extensionsScanner.ts b/src/vs/platform/extensionManagement/node/extensionsScanner.ts -index e7342348d46cbcafa1b301ca1373ce01c057e70f..408867d2d3b503b46363c5a853e047d396bb7e0a 100644 +index aee65f8eddbfbce3e42362be9590c98d46f2ace5..dc891fba7c7af3ace02b0091ef858bea59e754c6 100644 --- a/src/vs/platform/extensionManagement/node/extensionsScanner.ts +++ b/src/vs/platform/extensionManagement/node/extensionsScanner.ts -@@ -90,7 +90,7 @@ export class ExtensionsScanner extends Disposable { +@@ -91,7 +91,7 @@ export class ExtensionsScanner extends Disposable { } async scanAllUserExtensions(): Promise { @@ -603,7 +601,7 @@ index e7342348d46cbcafa1b301ca1373ce01c057e70f..408867d2d3b503b46363c5a853e047d3 } async extractUserExtension(identifierWithVersion: ExtensionIdentifierWithVersion, zipPath: string, token: CancellationToken): Promise { -@@ -235,7 +235,13 @@ export class ExtensionsScanner extends Disposable { +@@ -236,7 +236,13 @@ export class ExtensionsScanner extends Disposable { private async scanExtensionsInDir(dir: string, type: ExtensionType): Promise { const limiter = new Limiter(10); @@ -618,7 +616,7 @@ index e7342348d46cbcafa1b301ca1373ce01c057e70f..408867d2d3b503b46363c5a853e047d3 const extensions = await Promise.all(extensionsFolders.map(extensionFolder => limiter.queue(() => this.scanExtension(extensionFolder, dir, type)))); return extensions.filter(e => e && e.identifier); } -@@ -265,7 +271,7 @@ export class ExtensionsScanner extends Disposable { +@@ -266,7 +272,7 @@ export class ExtensionsScanner extends Disposable { } private async scanDefaultSystemExtensions(): Promise { @@ -627,7 +625,7 @@ index e7342348d46cbcafa1b301ca1373ce01c057e70f..408867d2d3b503b46363c5a853e047d3 this.logService.trace('Scanned system extensions:', result.length); return result; } -@@ -369,4 +375,9 @@ export class ExtensionsScanner extends Disposable { +@@ -370,4 +376,9 @@ export class ExtensionsScanner extends Disposable { } }); } @@ -638,7 +636,7 @@ index e7342348d46cbcafa1b301ca1373ce01c057e70f..408867d2d3b503b46363c5a853e047d3 + } } diff --git a/src/vs/platform/product/common/product.ts b/src/vs/platform/product/common/product.ts -index 798faa74ae825de7449b74609ed649912531ec0f..487abd285a42407f669ce5f5396423644f822a83 100644 +index 2bea85740cb3e00c955ec0f7aa46d5f9bb8d5dc8..c0953d7b73178fc4a7b030246a5281609c3dfce6 100644 --- a/src/vs/platform/product/common/product.ts +++ b/src/vs/platform/product/common/product.ts @@ -37,6 +37,12 @@ if (isWeb || typeof require === 'undefined' || typeof require.__$__nodeRequire ! @@ -655,7 +653,7 @@ index 798faa74ae825de7449b74609ed649912531ec0f..487abd285a42407f669ce5f539642364 // Native (non-sandboxed) diff --git a/src/vs/platform/product/common/productService.ts b/src/vs/platform/product/common/productService.ts -index 53dc899d48d85d27042600962b27ab97fb68951f..4792fee15e308e7427bb24591b19bcdc97eff600 100644 +index 333e5b24b05c96e8d44e9025b7a777e6989de9e7..b13572327a6e91592eedea9bcb1e580397f5c224 100644 --- a/src/vs/platform/product/common/productService.ts +++ b/src/vs/platform/product/common/productService.ts @@ -32,6 +32,8 @@ export type ConfigurationSyncStore = { @@ -689,10 +687,10 @@ index 3715cbb8e6ee41c3d9b5090918d243b723ae2d00..c65de8ad37e727d66da97a8f8b170cbc - - diff --git a/src/vs/platform/remote/common/remoteAgentConnection.ts b/src/vs/platform/remote/common/remoteAgentConnection.ts -index 18d3d04fd20335975293e37b3b641120dd92da20..4e49f9d63623da6c84624144765f76ec127ea526 100644 +index fdd5890c69f72025b94913380f0d226226e8c8fb..e084236526b38c1144d47b8b3000b367c3207fe8 100644 --- a/src/vs/platform/remote/common/remoteAgentConnection.ts +++ b/src/vs/platform/remote/common/remoteAgentConnection.ts -@@ -92,7 +92,7 @@ async function connectToRemoteExtensionHostAgent(options: ISimpleConnectionOptio +@@ -93,7 +93,7 @@ async function connectToRemoteExtensionHostAgent(options: ISimpleConnectionOptio options.socketFactory.connect( options.host, options.port, @@ -2902,7 +2900,7 @@ index 0000000000000000000000000000000000000000..fa47e993b46802f1a26457649e9e8bc4 + return path.split("/").map((p) => encodeURIComponent(p)).join("/"); +}; diff --git a/src/vs/workbench/api/browser/extensionHost.contribution.ts b/src/vs/workbench/api/browser/extensionHost.contribution.ts -index 9e264fb33b9a282e3a5284bcd857e17a664107a7..a23a44a781cd1f9b7d432d79a46707c93f4008e7 100644 +index a4df8523631563a498c9ab6e51105074616a481a..f03da094e9080544102bbd3f037a71b348e5bd83 100644 --- a/src/vs/workbench/api/browser/extensionHost.contribution.ts +++ b/src/vs/workbench/api/browser/extensionHost.contribution.ts @@ -61,6 +61,7 @@ import './mainThreadComments'; @@ -2914,10 +2912,10 @@ index 9e264fb33b9a282e3a5284bcd857e17a664107a7..a23a44a781cd1f9b7d432d79a46707c9 import './mainThreadAuthentication'; import './mainThreadTimeline'; diff --git a/src/vs/workbench/api/browser/mainThreadStorage.ts b/src/vs/workbench/api/browser/mainThreadStorage.ts -index 7bc3904963bed2925f3640b6bd929347159dd3cf..c6db2368ae9eaca61889efcf3c49763c01ff7459 100644 +index 57abf0e86a5edeeb2bc497af5e140ec13d9b5810..704d0f9ae19d436a7207ff735aabc289c422dd1e 100644 --- a/src/vs/workbench/api/browser/mainThreadStorage.ts +++ b/src/vs/workbench/api/browser/mainThreadStorage.ts -@@ -58,11 +58,11 @@ export class MainThreadStorage implements MainThreadStorageShape { +@@ -62,11 +62,11 @@ export class MainThreadStorage implements MainThreadStorageShape { return JSON.parse(jsonValue); } @@ -2932,7 +2930,7 @@ index 7bc3904963bed2925f3640b6bd929347159dd3cf..c6db2368ae9eaca61889efcf3c49763c return Promise.reject(err); } diff --git a/src/vs/workbench/api/common/extHost.api.impl.ts b/src/vs/workbench/api/common/extHost.api.impl.ts -index 2a0576b68f943f63c010dd496e094311bdc149f0..357c63f0fec08ddfb06b3579460fe1566fa5d852 100644 +index 284c6aff854a747d1202c34581a1419c35e9654f..f0173d80103ca91b5eab144a10935bc0990119c9 100644 --- a/src/vs/workbench/api/common/extHost.api.impl.ts +++ b/src/vs/workbench/api/common/extHost.api.impl.ts @@ -68,6 +68,7 @@ import { IURITransformerService } from 'vs/workbench/api/common/extHostUriTransf @@ -2960,10 +2958,10 @@ index 2a0576b68f943f63c010dd496e094311bdc149f0..357c63f0fec08ddfb06b3579460fe156 rpcProtocol.set(ExtHostContext.ExtHostWindow, extHostWindow); diff --git a/src/vs/workbench/api/common/extHost.protocol.ts b/src/vs/workbench/api/common/extHost.protocol.ts -index 3728f5602dffd0fd4b0cf326c5fa7d6d7c49c53e..2521acff0e692e97b72deef758ce41b4cd54a724 100644 +index 77ef6577821399b150407e980c8fd35e9d005ca6..264e3361accec20e4e1eaae10ae8ca05e47b1fae 100644 --- a/src/vs/workbench/api/common/extHost.protocol.ts +++ b/src/vs/workbench/api/common/extHost.protocol.ts -@@ -807,6 +807,17 @@ export interface MainThreadLabelServiceShape extends IDisposable { +@@ -816,6 +816,17 @@ export interface MainThreadLabelServiceShape extends IDisposable { $unregisterResourceLabelFormatter(handle: number): void; } @@ -2981,7 +2979,7 @@ index 3728f5602dffd0fd4b0cf326c5fa7d6d7c49c53e..2521acff0e692e97b72deef758ce41b4 export interface MainThreadSearchShape extends IDisposable { $registerFileSearchProvider(handle: number, scheme: string): void; $registerTextSearchProvider(handle: number, scheme: string): void; -@@ -1784,6 +1795,7 @@ export const MainContext = { +@@ -1796,6 +1807,7 @@ export const MainContext = { MainThreadWindow: createMainId('MainThreadWindow'), MainThreadLabelService: createMainId('MainThreadLabelService'), MainThreadNotebook: createMainId('MainThreadNotebook'), @@ -2989,7 +2987,7 @@ index 3728f5602dffd0fd4b0cf326c5fa7d6d7c49c53e..2521acff0e692e97b72deef758ce41b4 MainThreadTheming: createMainId('MainThreadTheming'), MainThreadTunnelService: createMainId('MainThreadTunnelService'), MainThreadTimeline: createMainId('MainThreadTimeline') -@@ -1826,6 +1838,7 @@ export const ExtHostContext = { +@@ -1838,6 +1850,7 @@ export const ExtHostContext = { ExtHostOutputService: createMainId('ExtHostOutputService'), ExtHosLabelService: createMainId('ExtHostLabelService'), ExtHostNotebook: createMainId('ExtHostNotebook'), @@ -2998,7 +2996,7 @@ index 3728f5602dffd0fd4b0cf326c5fa7d6d7c49c53e..2521acff0e692e97b72deef758ce41b4 ExtHostTunnelService: createMainId('ExtHostTunnelService'), ExtHostAuthentication: createMainId('ExtHostAuthentication'), diff --git a/src/vs/workbench/api/common/extHostExtensionService.ts b/src/vs/workbench/api/common/extHostExtensionService.ts -index 311b529e5adb46014466bf1852aef05a20b7a724..bc1bbd0196e4baf089c2bc7e0b08ecd771232b5e 100644 +index 328b9327207e4f2068bfab6cf374c622d8c5fc69..38963843095c9116011665027f46d3fb85c30ff8 100644 --- a/src/vs/workbench/api/common/extHostExtensionService.ts +++ b/src/vs/workbench/api/common/extHostExtensionService.ts @@ -31,6 +31,7 @@ import { IExtHostInitDataService } from 'vs/workbench/api/common/extHostInitData @@ -3042,7 +3040,7 @@ index 311b529e5adb46014466bf1852aef05a20b7a724..bc1bbd0196e4baf089c2bc7e0b08ecd7 this._loadExtensionContext(extensionDescription) ]).then(values => { return AbstractExtHostExtensionService._callActivate(this._logService, extensionDescription.identifier, values[0], values[1], activationTimesBuilder); -@@ -753,7 +757,7 @@ export abstract class AbstractExtHostExtensionService extends Disposable impleme +@@ -754,7 +758,7 @@ export abstract class AbstractExtHostExtensionService extends Disposable impleme protected abstract _beforeAlmostReadyToRunExtensions(): Promise; protected abstract _getEntryPoint(extensionDescription: IExtensionDescription): string | undefined; @@ -3070,7 +3068,7 @@ index b3c89e51cfc25a53293a352a2a8ad50d5f26d595..e21abe4e13bc25a5b72f556bbfb61085 registerSingleton(IExtHostTunnelService, ExtHostTunnelService); +registerSingleton(IExtHostNodeProxy, class extends NotImplementedProxy(String(IExtHostNodeProxy)) { whenReady = Promise.resolve(); }); diff --git a/src/vs/workbench/api/node/extHostCLIServer.ts b/src/vs/workbench/api/node/extHostCLIServer.ts -index 7cae126cc0f804273850933468690e0f9f10a5b8..08c2aa5cdae3f3d06bb08b7055dc7e7def260132 100644 +index b3857616f7006127c423dcef7020ae4653da5ff6..1c1b80a2767bf77f30ca5bfee715c337120d3625 100644 --- a/src/vs/workbench/api/node/extHostCLIServer.ts +++ b/src/vs/workbench/api/node/extHostCLIServer.ts @@ -11,6 +11,8 @@ import { IWindowOpenable, IOpenWindowOptions } from 'vs/platform/windows/common/ @@ -3082,10 +3080,10 @@ index 7cae126cc0f804273850933468690e0f9f10a5b8..08c2aa5cdae3f3d06bb08b7055dc7e7d export interface OpenCommandPipeArgs { type: 'open'; -@@ -54,6 +56,11 @@ export class CLIServer { - private async setup(): Promise { - this._ipcHandlePath = generateRandomPipeName(); +@@ -58,6 +60,11 @@ export class CLIServerBase { + } + private async setup(): Promise { + // NOTE@coder: Write this out so we can get the most recent path. + fs.promises.writeFile(join(tmpdir(), "vscode-ipc"), this._ipcHandlePath).catch((error) => { + this.logService.error(error); @@ -3112,18 +3110,18 @@ index 3843fdec386edc09a1d361b63de892a04e0070ed..8aac4df527857e964798362a69f5591b registerSingleton(ILogService, ExtHostLogService); +registerSingleton(IExtHostNodeProxy, ExtHostNodeProxy); diff --git a/src/vs/workbench/api/worker/extHostExtensionService.ts b/src/vs/workbench/api/worker/extHostExtensionService.ts -index a6a149083719d7479268e24eb5339f6cbf93e655..360888dc7dff9437f6c85f7a2043ad9e7c4daf21 100644 +index 021af6e0f8983c492f9cdd048ba2dcae7640bc1d..814dd0ff2fa7737e07833d8092c8f48953c73c47 100644 --- a/src/vs/workbench/api/worker/extHostExtensionService.ts +++ b/src/vs/workbench/api/worker/extHostExtensionService.ts -@@ -10,6 +10,7 @@ import { URI } from 'vs/base/common/uri'; - import { RequireInterceptor } from 'vs/workbench/api/common/extHostRequireInterceptor'; +@@ -11,6 +11,7 @@ import { RequireInterceptor } from 'vs/workbench/api/common/extHostRequireInterc import { IExtensionDescription } from 'vs/platform/extensions/common/extensions'; import { ExtensionRuntime } from 'vs/workbench/api/common/extHostTypes'; + import { timeout } from 'vs/base/common/async'; +import { loadCommonJSModule } from 'vs/server/browser/worker'; class WorkerRequireInterceptor extends RequireInterceptor { -@@ -44,10 +45,15 @@ export class ExtHostExtensionService extends AbstractExtHostExtensionService { +@@ -46,10 +47,15 @@ export class ExtHostExtensionService extends AbstractExtHostExtensionService { } protected _getEntryPoint(extensionDescription: IExtensionDescription): string | undefined { @@ -3157,18 +3155,18 @@ index ced2d815834e40a1543e80516472799075980733..dfcae73e8a042307600c67f163aa00ba .monaco-workbench .activitybar > .content > .home-bar > .home-bar-icon-badge { diff --git a/src/vs/workbench/browser/web.main.ts b/src/vs/workbench/browser/web.main.ts -index 416938f141228faafc95dc765be7d5fbaf610a7e..25ff7f7c881458fbb7b5bd588704930b52f439e8 100644 +index 80544aab34c12bb42a36519885e9872ef2b24158..17b56856a0b3fd936dbc094ff39797d5b8ccaadf 100644 --- a/src/vs/workbench/browser/web.main.ts +++ b/src/vs/workbench/browser/web.main.ts -@@ -42,6 +42,7 @@ import { FileLogService } from 'vs/platform/log/common/fileLogService'; +@@ -43,6 +43,7 @@ import { FileLogService } from 'vs/platform/log/common/fileLogService'; import { toLocalISOString } from 'vs/base/common/date'; import { isWorkspaceToOpen, isFolderToOpen } from 'vs/platform/windows/common/windows'; import { getWorkspaceIdentifier } from 'vs/workbench/services/workspaces/browser/workspaces'; +import { initialize } from 'vs/server/browser/client'; import { coalesce } from 'vs/base/common/arrays'; import { InMemoryFileSystemProvider } from 'vs/platform/files/common/inMemoryFilesystemProvider'; - import { WebResourceIdentityService, IResourceIdentityService } from 'vs/platform/resource/common/resourceIdentityService'; -@@ -94,6 +95,8 @@ class BrowserMain extends Disposable { + import { ICommandService } from 'vs/platform/commands/common/commands'; +@@ -101,6 +102,8 @@ class BrowserMain extends Disposable { // Startup const instantiationService = workbench.startup(); @@ -3200,7 +3198,7 @@ index 94e7e7a4bac154c45078a1b5034e50634a7a43af..8164200dcef1efbc65b50eef9c270af3 this._dirnameKey.set(value ? dirname(value).fsPath : null); this._pathKey.set(value ? value.fsPath : null); diff --git a/src/vs/workbench/contrib/scm/browser/media/scm.css b/src/vs/workbench/contrib/scm/browser/media/scm.css -index ac44ad3bae428def66e22fe9cc1c54648d429f6b..faa63023c4c586b51fa3c2a48ff3641b9cb0e145 100644 +index 74f6922e98b4bb6a7fb100f5aac015afe9fc171b..3243a97c2d378013d96ffbe87e9df6dd4a66776d 100644 --- a/src/vs/workbench/contrib/scm/browser/media/scm.css +++ b/src/vs/workbench/contrib/scm/browser/media/scm.css @@ -149,9 +149,11 @@ @@ -3219,10 +3217,10 @@ index ac44ad3bae428def66e22fe9cc1c54648d429f6b..faa63023c4c586b51fa3c2a48ff3641b .scm-view .monaco-list .monaco-list-row .resource-group > .actions, .scm-view .monaco-list .monaco-list-row .resource > .name > .monaco-icon-label > .actions { diff --git a/src/vs/workbench/electron-sandbox/sandbox.simpleservices.ts b/src/vs/workbench/electron-sandbox/sandbox.simpleservices.ts -index d57009a5a251ac5815c04e4f76bacef3e518a575..e825a8975449e95cf40504057d56579c12918a58 100644 +index ed4f26407391bd62219a9f8245a5cd63a7cb7488..92f26d1b082f80475cf76409a4569e948e9e0bd9 100644 --- a/src/vs/workbench/electron-sandbox/sandbox.simpleservices.ts +++ b/src/vs/workbench/electron-sandbox/sandbox.simpleservices.ts -@@ -127,6 +127,8 @@ export class SimpleNativeWorkbenchEnvironmentService implements INativeWorkbench +@@ -130,6 +130,8 @@ export class SimpleNativeWorkbenchEnvironmentService implements INativeWorkbench extensionsPath?: string | undefined; extensionsDownloadPath: string = undefined!; builtinExtensionsPath: string = undefined!; @@ -3230,12 +3228,12 @@ index d57009a5a251ac5815c04e4f76bacef3e518a575..e825a8975449e95cf40504057d56579c + extraBuiltinExtensionPaths: string[] = undefined!; driverHandle?: string | undefined; - driverVerbose = false; + diff --git a/src/vs/workbench/services/dialogs/browser/dialogService.ts b/src/vs/workbench/services/dialogs/browser/dialogService.ts -index 1360c248eb7ff937c92d08bbf30d2b76ea606dc0..adccf8b88d62381c3ec484df40c6d63142ec9ef5 100644 +index 85d83f37da179a1e39266cf72a02e971f590308e..0659738b36df1747c9afcabf8d9abf26c890990b 100644 --- a/src/vs/workbench/services/dialogs/browser/dialogService.ts +++ b/src/vs/workbench/services/dialogs/browser/dialogService.ts -@@ -124,11 +124,12 @@ export class DialogService implements IDialogService { +@@ -125,11 +125,12 @@ export class DialogService implements IDialogService { async about(): Promise { const detailString = (useAgo: boolean): string => { return nls.localize('aboutDetail', @@ -3251,10 +3249,10 @@ index 1360c248eb7ff937c92d08bbf30d2b76ea606dc0..adccf8b88d62381c3ec484df40c6d631 }; diff --git a/src/vs/workbench/services/environment/browser/environmentService.ts b/src/vs/workbench/services/environment/browser/environmentService.ts -index 8d5e0fb796661c63bf46a377607977f4b1f0b2ad..9f5da5da9435626419be5447577d20dcb408e78d 100644 +index a8d43045ecc8cbe04b3f8440cff16d42aadbcad0..cd589c6f75eccbeefbf364d426ac882396b26fb4 100644 --- a/src/vs/workbench/services/environment/browser/environmentService.ts +++ b/src/vs/workbench/services/environment/browser/environmentService.ts -@@ -112,8 +112,18 @@ export class BrowserWorkbenchEnvironmentService implements IWorkbenchEnvironment +@@ -119,8 +119,18 @@ export class BrowserWorkbenchEnvironmentService implements IWorkbenchEnvironment @memoize get logFile(): URI { return joinPath(this.options.logsPath, 'window.log'); } @@ -3274,7 +3272,7 @@ index 8d5e0fb796661c63bf46a377607977f4b1f0b2ad..9f5da5da9435626419be5447577d20dc @memoize get settingsResource(): URI { return joinPath(this.userRoamingDataHome, 'settings.json'); } -@@ -275,7 +285,12 @@ export class BrowserWorkbenchEnvironmentService implements IWorkbenchEnvironment +@@ -301,7 +311,12 @@ export class BrowserWorkbenchEnvironmentService implements IWorkbenchEnvironment extensionHostDebugEnvironment.params.port = parseInt(value); break; case 'enableProposedApi': @@ -3288,11 +3286,11 @@ index 8d5e0fb796661c63bf46a377607977f4b1f0b2ad..9f5da5da9435626419be5447577d20dc break; } } -diff --git a/src/vs/workbench/services/extensionManagement/common/extensionEnablementService.ts b/src/vs/workbench/services/extensionManagement/common/extensionEnablementService.ts -index 6e7e8c5c9ed18d3a7e9f6d5d886adf0f49038f23..f4b17da7d718a2b60db7a44f936e7d0e93ffff6f 100644 ---- a/src/vs/workbench/services/extensionManagement/common/extensionEnablementService.ts -+++ b/src/vs/workbench/services/extensionManagement/common/extensionEnablementService.ts -@@ -205,7 +205,7 @@ export class ExtensionEnablementService extends Disposable implements IWorkbench +diff --git a/src/vs/workbench/services/extensionManagement/browser/extensionEnablementService.ts b/src/vs/workbench/services/extensionManagement/browser/extensionEnablementService.ts +index 50d4d812b76f09435fcff8148aac4ceeaeb30873..faacf88fcef119f9f959739656d64a84c8f64cbf 100644 +--- a/src/vs/workbench/services/extensionManagement/browser/extensionEnablementService.ts ++++ b/src/vs/workbench/services/extensionManagement/browser/extensionEnablementService.ts +@@ -221,7 +221,7 @@ export class ExtensionEnablementService extends Disposable implements IWorkbench } } } @@ -3302,39 +3300,37 @@ index 6e7e8c5c9ed18d3a7e9f6d5d886adf0f49038f23..f4b17da7d718a2b60db7a44f936e7d0e return false; } diff --git a/src/vs/workbench/services/extensionManagement/common/extensionManagementService.ts b/src/vs/workbench/services/extensionManagement/common/extensionManagementService.ts -index a982b3ecc58c5a2f3a92be7b8cca3a1cacbb7d47..97f9bfcf0e679be683b1b09cd569149e7962f5ad 100644 +index de7e301d3f0c67ce662827f61427a5a7b3616b9f..877ea8e11e6e6d34b9a8fe16287af309e569285e 100644 --- a/src/vs/workbench/services/extensionManagement/common/extensionManagementService.ts +++ b/src/vs/workbench/services/extensionManagement/common/extensionManagementService.ts -@@ -211,8 +211,11 @@ export class ExtensionManagementService extends Disposable implements IExtension - } +@@ -251,7 +251,9 @@ export class ExtensionManagementService extends Disposable implements IWorkbench // Install Language pack on all servers -+ // NOTE@coder: It does not appear language packs can be installed on the web -+ // extension management server at this time. Filter out the web to fix this. if (isLanguagePackExtension(manifest)) { -- return Promise.all(this.servers.map(server => server.extensionManagementService.installFromGallery(gallery))).then(([local]) => local); -+ const servers = this.servers.filter(s => s !== this.extensionManagementServerService.webExtensionManagementServer); -+ return Promise.all(servers.map(server => server.extensionManagementService.installFromGallery(gallery))).then(([local]) => local); - } - - // 1. Install on preferred location -@@ -245,6 +248,11 @@ export class ExtensionManagementService extends Disposable implements IExtension - return this.extensionManagementServerService.webExtensionManagementServer.extensionManagementService.installFromGallery(gallery); +- servers.push(...this.servers); ++ // NOTE@coder: It does not appear language packs can be installed on the web ++ // extension management server at this time. Filter out the web to fix this. ++ servers.push(...this.servers.filter(s => s !== this.extensionManagementServerService.webExtensionManagementServer)); + } else { + const server = this.getExtensionManagementServerToInstall(manifest); + if (server) { +@@ -320,6 +322,11 @@ export class ExtensionManagementService extends Disposable implements IWorkbench + return this.extensionManagementServerService.webExtensionManagementServer; } + // NOTE@coder: Fall back to installing on the remote server. + if (this.extensionManagementServerService.remoteExtensionManagementServer) { -+ return this.extensionManagementServerService.remoteExtensionManagementServer.extensionManagementService.installFromGallery(gallery); ++ return this.extensionManagementServerService.remoteExtensionManagementServer; + } + - if (this.extensionManagementServerService.remoteExtensionManagementServer) { - const error = new Error(localize('cannot be installed', "Cannot install '{0}' because this extension has defined that it cannot run on the remote server.", gallery.displayName || gallery.name)); - error.name = INSTALL_ERROR_NOT_SUPPORTED; + return undefined; + } + diff --git a/src/vs/workbench/services/extensions/browser/extensionService.ts b/src/vs/workbench/services/extensions/browser/extensionService.ts -index 5eaec3499a3bd87ee4026c26a4b0e8c706978859..829514442fe60e2999378af14fd38c71ee92d2b9 100644 +index 1dff19bf177eff24f722b748b79835a653241c4d..0f59ad290c82cc4c9d09c565c1018cc275ca0249 100644 --- a/src/vs/workbench/services/extensions/browser/extensionService.ts +++ b/src/vs/workbench/services/extensions/browser/extensionService.ts -@@ -161,8 +161,10 @@ export class ExtensionService extends AbstractExtensionService implements IExten +@@ -177,8 +177,10 @@ export class ExtensionService extends AbstractExtensionService implements IExten this._remoteAgentService.getEnvironment(), this._remoteAgentService.scanExtensions() ]); @@ -3361,11 +3357,11 @@ index 65e532ee58dfc06ed944846d01b885cb8f260ebc..0b6282fde7ad03c7ea9872a777cbf487 export function getExtensionKind(manifest: IExtensionManifest, productService: IProductService, configurationService: IConfigurationService): ExtensionKind[] { diff --git a/src/vs/workbench/services/extensions/node/extensionHostProcessSetup.ts b/src/vs/workbench/services/extensions/node/extensionHostProcessSetup.ts -index 4eb8204bf5ad61d4d292dad5c2490c25fbff497a..85f6006c1f125da283b2ba615bad2805fa3598fc 100644 +index e39d131fe7b1dd4bd1093fedb8faba8e1fe969e8..94f2f1d7c4a0b3cb46eaaffe1181b3abbf997d7f 100644 --- a/src/vs/workbench/services/extensions/node/extensionHostProcessSetup.ts +++ b/src/vs/workbench/services/extensions/node/extensionHostProcessSetup.ts @@ -16,7 +16,7 @@ import { IInitData } from 'vs/workbench/api/common/extHost.protocol'; - import { MessageType, createMessageOfType, isMessageOfType, IExtHostSocketMessage, IExtHostReadyMessage, IExtHostReduceGraceTimeMessage } from 'vs/workbench/services/extensions/common/extensionHostProtocol'; + import { MessageType, createMessageOfType, isMessageOfType, IExtHostSocketMessage, IExtHostReadyMessage, IExtHostReduceGraceTimeMessage, ExtensionHostExitCode } from 'vs/workbench/services/extensions/common/extensionHostProtocol'; import { ExtensionHostMain, IExitFn } from 'vs/workbench/services/extensions/common/extensionHostMain'; import { VSBuffer } from 'vs/base/common/buffer'; -import { IURITransformer, URITransformer, IRawURITransformer } from 'vs/base/common/uriIpc'; @@ -3461,7 +3457,7 @@ index d7aefde89c74bc6096d6e66c45368c8582594efa..9758f3bb96b48603251336e6a64e270e } diff --git a/src/vs/workbench/workbench.web.main.ts b/src/vs/workbench/workbench.web.main.ts -index 59208b87022c74342489288c1a3c89937aa6d37e..f49153db796e59a5aed0cc56ea5d01c0f10f963e 100644 +index 509f8ac8ce3a689386e439302a53c27e4fdfcef7..2bf9a737bd0dbfa1e604acfc890be45823f02ebe 100644 --- a/src/vs/workbench/workbench.web.main.ts +++ b/src/vs/workbench/workbench.web.main.ts @@ -35,7 +35,8 @@ import 'vs/workbench/services/textfile/browser/browserTextFileService'; @@ -3475,7 +3471,7 @@ index 59208b87022c74342489288c1a3c89937aa6d37e..f49153db796e59a5aed0cc56ea5d01c0 import 'vs/workbench/services/credentials/browser/credentialsService'; import 'vs/workbench/services/url/browser/urlService'; diff --git a/yarn.lock b/yarn.lock -index a38db6751b5bbe5949afeb4c29921e1cb88913ac..c78f065a5587d81427aaf951cbfbc5509e2096d5 100644 +index ff358cb6a10984868ed5a5aed5729ac6eb8ebeb7..69668d95ecad219da26ccc4d837913b9324a0e28 100644 --- a/yarn.lock +++ b/yarn.lock @@ -140,6 +140,23 @@ @@ -3502,7 +3498,7 @@ index a38db6751b5bbe5949afeb4c29921e1cb88913ac..c78f065a5587d81427aaf951cbfbc550 "@electron/get@^1.0.1": version "1.7.2" resolved "https://registry.yarnpkg.com/@electron/get/-/get-1.7.2.tgz#286436a9fb56ff1a1fcdf0e80131fd65f4d1e0fd" -@@ -5383,6 +5400,13 @@ jsprim@^1.2.2: +@@ -5403,6 +5420,13 @@ jsprim@^1.2.2: json-schema "0.2.3" verror "1.10.0" @@ -3516,7 +3512,7 @@ index a38db6751b5bbe5949afeb4c29921e1cb88913ac..c78f065a5587d81427aaf951cbfbc550 just-debounce@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/just-debounce/-/just-debounce-1.0.0.tgz#87fccfaeffc0b68cd19d55f6722943f929ea35ea" -@@ -5963,26 +5987,11 @@ minimatch@0.3: +@@ -5983,26 +6007,11 @@ minimatch@0.3: dependencies: brace-expansion "^1.1.7" @@ -3544,7 +3540,7 @@ index a38db6751b5bbe5949afeb4c29921e1cb88913ac..c78f065a5587d81427aaf951cbfbc550 minipass@^2.2.1, minipass@^2.3.3: version "2.3.3" resolved "https://registry.yarnpkg.com/minipass/-/minipass-2.3.3.tgz#a7dcc8b7b833f5d368759cce544dccb55f50f233" -@@ -6724,6 +6733,11 @@ p-try@^2.0.0: +@@ -6744,6 +6753,11 @@ p-try@^2.0.0: resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.0.0.tgz#85080bb87c64688fa47996fe8f7dfbe8211760b1" integrity sha512-hMp0onDKIajHfIkdRk3P4CdCmErkYAxxDtP3Wx/4nZ3aGlau2VKh3mZpcuFkH27WQkL/3WBCPOktzA9ZOAnMQQ== diff --git a/lib/vscode b/lib/vscode index 93c2f0fb..e5a624b7 160000 --- a/lib/vscode +++ b/lib/vscode @@ -1 +1 @@ -Subproject commit 93c2f0fbf16c5a4b10e4d5f89737d9c2c25488a3 +Subproject commit e5a624b788d92b8d34d1392e4c4d9789406efe8f From 4d276b88c0b2725ae6a262dbaa3e2f73876f8283 Mon Sep 17 00:00:00 2001 From: Asher Date: Fri, 6 Nov 2020 22:49:05 -0600 Subject: [PATCH 02/13] Add new logger service The telemetry service depends on this now. I had to move it into invokeFunction and use accessor.get otherwise getLogger on the service was undefined. I also had to move some the extension management service because it depends on the moved telemetry service. I moved a few other services as well to better match VS Code (sharedProcessMain.ts). I swapped some this.services.get with accessor.get since that seems to be the correct method although for these other services either method seems to work. --- ci/dev/vscode.patch | 69 +++++++++++++++++++++++++-------------------- 1 file changed, 39 insertions(+), 30 deletions(-) diff --git a/ci/dev/vscode.patch b/ci/dev/vscode.patch index 7cd67f3c..0fd51f4f 100644 --- a/ci/dev/vscode.patch +++ b/ci/dev/vscode.patch @@ -2585,10 +2585,10 @@ index 0000000000000000000000000000000000000000..0d9310038c0ca378579652d89bc8ac84 +} diff --git a/src/vs/server/node/server.ts b/src/vs/server/node/server.ts new file mode 100644 -index 0000000000000000000000000000000000000000..45a7bf62a6c07d8771b0257e7c98fae095109eb1 +index 0000000000000000000000000000000000000000..8424965d9c79d34e5513e4cfe543718521ad82c7 --- /dev/null +++ b/src/vs/server/node/server.ts -@@ -0,0 +1,291 @@ +@@ -0,0 +1,300 @@ +import { field } from '@coder/logger'; +import * as fs from 'fs'; +import * as net from 'net'; @@ -2618,8 +2618,9 @@ index 0000000000000000000000000000000000000000..45a7bf62a6c07d8771b0257e7c98fae0 +import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection'; +import { ILocalizationsService } from 'vs/platform/localizations/common/localizations'; +import { LocalizationsService } from 'vs/platform/localizations/node/localizations'; -+import { getLogLevel, ILogService } from 'vs/platform/log/common/log'; ++import { getLogLevel, ILoggerService, ILogService } from 'vs/platform/log/common/log'; +import { LoggerChannel } from 'vs/platform/log/common/logIpc'; ++import { LoggerService } from 'vs/platform/log/node/loggerService'; +import { SpdLogService } from 'vs/platform/log/node/spdlogService'; +import product from 'vs/platform/product/common/product'; +import { IProductService } from 'vs/platform/product/common/productService'; @@ -2630,8 +2631,9 @@ index 0000000000000000000000000000000000000000..45a7bf62a6c07d8771b0257e7c98fae0 +import { RequestService } from 'vs/platform/request/node/requestService'; +import ErrorTelemetry from 'vs/platform/telemetry/browser/errorTelemetry'; +import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; ++import { TelemetryLogAppender } from 'vs/platform/telemetry/common/telemetryLogAppender'; +import { TelemetryService } from 'vs/platform/telemetry/common/telemetryService'; -+import { combinedAppender, LogAppender, NullTelemetryService } from 'vs/platform/telemetry/common/telemetryUtils'; ++import { combinedAppender, NullTelemetryService } from 'vs/platform/telemetry/common/telemetryUtils'; +import { AppInsightsAppender } from 'vs/platform/telemetry/node/appInsightsAppender'; +import { resolveCommonProperties } from 'vs/platform/telemetry/node/commonProperties'; +import { INodeProxyService, NodeProxyChannel } from 'vs/server/common/nodeProxy'; @@ -2820,6 +2822,7 @@ index 0000000000000000000000000000000000000000..45a7bf62a6c07d8771b0257e7c98fae0 + this.services.set(ILogService, logService); + this.services.set(IEnvironmentService, environmentService); + this.services.set(INativeEnvironmentService, environmentService); ++ this.services.set(ILoggerService, new SyncDescriptor(LoggerService)); + + const configurationService = new ConfigurationService(environmentService.settingsResource, fileService); + await configurationService.initialize(); @@ -2828,45 +2831,51 @@ index 0000000000000000000000000000000000000000..45a7bf62a6c07d8771b0257e7c98fae0 + this.services.set(IRequestService, new SyncDescriptor(RequestService)); + this.services.set(IFileService, fileService); + this.services.set(IProductService, { _serviceBrand: undefined, ...product }); -+ this.services.set(IExtensionGalleryService, new SyncDescriptor(ExtensionGalleryService)); -+ this.services.set(IExtensionManagementService, new SyncDescriptor(ExtensionManagementService)); + -+ if (!environmentService.disableTelemetry) { -+ this.services.set(ITelemetryService, new TelemetryService({ -+ appender: combinedAppender( -+ new AppInsightsAppender('code-server', null, () => new TelemetryClient() as any, logService), -+ new LogAppender(logService), -+ ), -+ sendErrorTelemetry: true, -+ commonProperties: resolveCommonProperties( -+ product.commit, product.version, await getMachineId(), -+ [], environmentService.installSourcePath, 'code-server', -+ ), -+ piiPaths, -+ }, configurationService)); -+ } else { -+ this.services.set(ITelemetryService, NullTelemetryService); -+ } ++ const machineId = await getMachineId(); + + await new Promise((resolve) => { + const instantiationService = new InstantiationService(this.services); -+ this.services.set(ILocalizationsService, instantiationService.createInstance(LocalizationsService)); -+ this.services.set(INodeProxyService, instantiationService.createInstance(NodeProxyService)); + -+ instantiationService.invokeFunction(() => { ++ instantiationService.invokeFunction((accessor) => { + instantiationService.createInstance(LogsDataCleaner); -+ const telemetryService = this.services.get(ITelemetryService) as ITelemetryService; ++ ++ let telemetryService: ITelemetryService; ++ if (!environmentService.disableTelemetry) { ++ telemetryService = new TelemetryService({ ++ appender: combinedAppender( ++ new AppInsightsAppender('code-server', null, () => new TelemetryClient() as any), ++ new TelemetryLogAppender(accessor.get(ILoggerService), environmentService) ++ ), ++ sendErrorTelemetry: true, ++ commonProperties: resolveCommonProperties( ++ product.commit, product.version, machineId, ++ [], environmentService.installSourcePath, 'code-server', ++ ), ++ piiPaths, ++ }, configurationService); ++ } else { ++ telemetryService = NullTelemetryService; ++ } ++ ++ this.services.set(ITelemetryService, telemetryService); ++ ++ this.services.set(IExtensionManagementService, new SyncDescriptor(ExtensionManagementService)); ++ this.services.set(IExtensionGalleryService, new SyncDescriptor(ExtensionGalleryService)); ++ this.services.set(ILocalizationsService, new SyncDescriptor(LocalizationsService)); ++ this.services.set(INodeProxyService, new SyncDescriptor(NodeProxyService)); ++ + this.ipc.registerChannel('extensions', new ExtensionManagementChannel( -+ this.services.get(IExtensionManagementService) as IExtensionManagementService, ++ accessor.get(IExtensionManagementService), + (context) => getUriTransformer(context.remoteAuthority), + )); + this.ipc.registerChannel('remoteextensionsenvironment', new ExtensionEnvironmentChannel( + environmentService, logService, telemetryService, '', + )); -+ this.ipc.registerChannel('request', new RequestChannel(this.services.get(IRequestService) as IRequestService)); ++ this.ipc.registerChannel('request', new RequestChannel(accessor.get(IRequestService))); + this.ipc.registerChannel('telemetry', new TelemetryChannel(telemetryService)); -+ this.ipc.registerChannel('nodeProxy', new NodeProxyChannel(this.services.get(INodeProxyService) as INodeProxyService)); -+ this.ipc.registerChannel('localizations', >createChannelReceiver(this.services.get(ILocalizationsService) as ILocalizationsService)); ++ this.ipc.registerChannel('nodeProxy', new NodeProxyChannel(accessor.get(INodeProxyService))); ++ this.ipc.registerChannel('localizations', >createChannelReceiver(accessor.get(ILocalizationsService))); + this.ipc.registerChannel(REMOTE_FILE_SYSTEM_CHANNEL_NAME, new FileProviderChannel(environmentService, logService)); + resolve(new ErrorTelemetry(telemetryService)); + }); From 431137da454a68b758fb0b86a8a7e1fb3371337c Mon Sep 17 00:00:00 2001 From: Asher Date: Fri, 13 Nov 2020 11:31:01 -0600 Subject: [PATCH 03/13] Add new (unimplemented) terminal service --- ci/dev/vscode.patch | 89 ++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 84 insertions(+), 5 deletions(-) diff --git a/ci/dev/vscode.patch b/ci/dev/vscode.patch index 0fd51f4f..65f4a3b5 100644 --- a/ci/dev/vscode.patch +++ b/ci/dev/vscode.patch @@ -1466,10 +1466,10 @@ index 0000000000000000000000000000000000000000..6ce56bec114a6d8daf5dd3ded945ea78 +} diff --git a/src/vs/server/node/channel.ts b/src/vs/server/node/channel.ts new file mode 100644 -index 0000000000000000000000000000000000000000..609c4d1cb43f52f92906b901c14c790f4536468f +index 0000000000000000000000000000000000000000..6fb1ada50628d3826a493c6e1b58f27a8be428bb --- /dev/null +++ b/src/vs/server/node/channel.ts -@@ -0,0 +1,360 @@ +@@ -0,0 +1,437 @@ +import { Server } from '@coder/node-browser'; +import * as path from 'path'; +import { VSBuffer } from 'vs/base/common/buffer'; @@ -1494,6 +1494,8 @@ index 0000000000000000000000000000000000000000..609c4d1cb43f52f92906b901c14c790f +import { getTranslations } from 'vs/server/node/nls'; +import { getUriTransformer } from 'vs/server/node/util'; +import { IFileChangeDto } from 'vs/workbench/api/common/extHost.protocol'; ++import * as terminal from 'vs/workbench/contrib/terminal/common/remoteTerminalChannel'; ++import { ITerminalLaunchError } from 'vs/workbench/contrib/terminal/common/terminal'; +import { ExtensionScanner, ExtensionScannerInput } from 'vs/workbench/services/extensions/node/extensionPoints'; + +/** @@ -1830,6 +1832,81 @@ index 0000000000000000000000000000000000000000..609c4d1cb43f52f92906b901c14c790f + this._$onMessage.fire(message); + } +} ++ ++export class TerminalProviderChannel implements IServerChannel, IDisposable { ++ public listen(_: RemoteAgentConnectionContext, event: string, args?: any): Event { ++ switch (event) { ++ case '$onTerminalProcessEvent': return this.onTerminalProcessEvent(args); ++ } ++ ++ throw new Error(`Invalid listen '${event}'`); ++ } ++ ++ private onTerminalProcessEvent(args: terminal.IOnTerminalProcessEventArguments): Event { ++ throw new Error('not implemented'); ++ } ++ ++ public call(_: unknown, command: string, args?: any): Promise { ++ switch (command) { ++ case '$createTerminalProcess': return this.createTerminalProcess(args); ++ case '$startTerminalProcess': return this.startTerminalProcess(args); ++ case '$sendInputToTerminalProcess': return this.sendInputToTerminalProcess(args); ++ case '$shutdownTerminalProcess': return this.shutdownTerminalProcess(args); ++ case '$resizeTerminalProcess': return this.resizeTerminalProcess(args); ++ case '$getTerminalInitialCwd': return this.getTerminalInitialCwd(args); ++ case '$getTerminalCwd': return this.getTerminalCwd(args); ++ case '$sendCommandResultToTerminalProcess': return this.sendCommandResultToTerminalProcess(args); ++ case '$orphanQuestionReply': return this.orphanQuestionReply(args[0]); ++ case '$listTerminals': return this.listTerminals(args[0]); ++ } ++ ++ throw new Error(`Invalid call '${command}'`); ++ } ++ ++ public dispose(): void { ++ // Nothing yet. ++ } ++ ++ private async createTerminalProcess(args: terminal.ICreateTerminalProcessArguments): Promise { ++ throw new Error(`not implemented`); ++ } ++ ++ private async startTerminalProcess(args: terminal.IStartTerminalProcessArguments): Promise { ++ throw new Error('not implemented'); ++ } ++ ++ private async sendInputToTerminalProcess(args: terminal.ISendInputToTerminalProcessArguments): Promise { ++ throw new Error('not implemented'); ++ } ++ ++ private async shutdownTerminalProcess(args: terminal.IShutdownTerminalProcessArguments): Promise { ++ throw new Error('not implemented'); ++ } ++ ++ private async resizeTerminalProcess(args: terminal.IResizeTerminalProcessArguments): Promise { ++ throw new Error('not implemented'); ++ } ++ ++ private async getTerminalInitialCwd(args: terminal.IGetTerminalInitialCwdArguments): Promise { ++ throw new Error('not implemented'); ++ } ++ ++ private async getTerminalCwd(args: terminal.IGetTerminalCwdArguments): Promise { ++ throw new Error('not implemented'); ++ } ++ ++ private async sendCommandResultToTerminalProcess(args: terminal.ISendCommandResultToTerminalProcessArguments): Promise { ++ throw new Error('not implemented'); ++ } ++ ++ private async orphanQuestionReply(args: terminal.IOrphanQuestionReplyArgs): Promise { ++ throw new Error('not implemented'); ++ } ++ ++ private async listTerminals(args: terminal.IListTerminalsArgs): Promise { ++ throw new Error('not implemented'); ++ } ++} diff --git a/src/vs/server/node/connection.ts b/src/vs/server/node/connection.ts new file mode 100644 index 0000000000000000000000000000000000000000..93062cadc627c61e0829c27a72894b81e6a0e039 @@ -2585,10 +2662,10 @@ index 0000000000000000000000000000000000000000..0d9310038c0ca378579652d89bc8ac84 +} diff --git a/src/vs/server/node/server.ts b/src/vs/server/node/server.ts new file mode 100644 -index 0000000000000000000000000000000000000000..8424965d9c79d34e5513e4cfe543718521ad82c7 +index 0000000000000000000000000000000000000000..ebd3fbdf7554c63d23ad6bd0e51e0a35a94509dd --- /dev/null +++ b/src/vs/server/node/server.ts -@@ -0,0 +1,300 @@ +@@ -0,0 +1,302 @@ +import { field } from '@coder/logger'; +import * as fs from 'fs'; +import * as net from 'net'; @@ -2639,13 +2716,14 @@ index 0000000000000000000000000000000000000000..8424965d9c79d34e5513e4cfe5437185 +import { INodeProxyService, NodeProxyChannel } from 'vs/server/common/nodeProxy'; +import { TelemetryChannel } from 'vs/server/common/telemetry'; +import { Query, VscodeOptions, WorkbenchOptions } from 'vs/server/ipc'; -+import { ExtensionEnvironmentChannel, FileProviderChannel, NodeProxyService } from 'vs/server/node/channel'; ++import { ExtensionEnvironmentChannel, FileProviderChannel, NodeProxyService, TerminalProviderChannel } from 'vs/server/node/channel'; +import { Connection, ExtensionHostConnection, ManagementConnection } from 'vs/server/node/connection'; +import { TelemetryClient } from 'vs/server/node/insights'; +import { logger } from 'vs/server/node/logger'; +import { getLocaleFromConfig, getNlsConfiguration } from 'vs/server/node/nls'; +import { Protocol } from 'vs/server/node/protocol'; +import { getUriTransformer } from 'vs/server/node/util'; ++import { REMOTE_TERMINAL_CHANNEL_NAME } from 'vs/workbench/contrib/terminal/common/remoteTerminalChannel'; +import { REMOTE_FILE_SYSTEM_CHANNEL_NAME } from "vs/workbench/services/remote/common/remoteAgentFileSystemChannel"; +import { RemoteExtensionLogFileName } from 'vs/workbench/services/remote/common/remoteAgentService'; + @@ -2877,6 +2955,7 @@ index 0000000000000000000000000000000000000000..8424965d9c79d34e5513e4cfe5437185 + this.ipc.registerChannel('nodeProxy', new NodeProxyChannel(accessor.get(INodeProxyService))); + this.ipc.registerChannel('localizations', >createChannelReceiver(accessor.get(ILocalizationsService))); + this.ipc.registerChannel(REMOTE_FILE_SYSTEM_CHANNEL_NAME, new FileProviderChannel(environmentService, logService)); ++ this.ipc.registerChannel(REMOTE_TERMINAL_CHANNEL_NAME, new TerminalProviderChannel()); + resolve(new ErrorTelemetry(telemetryService)); + }); + }); From 3f7b91e2e2004263b5db704826b749009e5bc751 Mon Sep 17 00:00:00 2001 From: Asher Date: Tue, 17 Nov 2020 13:26:07 -0600 Subject: [PATCH 04/13] Implement most of remote terminal service It works, at least, but there are still some missing parts. --- ci/dev/vscode.patch | 385 +++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 364 insertions(+), 21 deletions(-) diff --git a/ci/dev/vscode.patch b/ci/dev/vscode.patch index 65f4a3b5..d8a5f2c0 100644 --- a/ci/dev/vscode.patch +++ b/ci/dev/vscode.patch @@ -1466,17 +1466,20 @@ index 0000000000000000000000000000000000000000..6ce56bec114a6d8daf5dd3ded945ea78 +} diff --git a/src/vs/server/node/channel.ts b/src/vs/server/node/channel.ts new file mode 100644 -index 0000000000000000000000000000000000000000..6fb1ada50628d3826a493c6e1b58f27a8be428bb +index 0000000000000000000000000000000000000000..91a932b613c473cd13dfddbde2942aeebf4bb84c --- /dev/null +++ b/src/vs/server/node/channel.ts -@@ -0,0 +1,437 @@ +@@ -0,0 +1,780 @@ ++import { field, logger } from '@coder/logger'; +import { Server } from '@coder/node-browser'; ++import * as os from 'os'; +import * as path from 'path'; +import { VSBuffer } from 'vs/base/common/buffer'; +import { CancellationTokenSource } from 'vs/base/common/cancellation'; +import { Emitter, Event } from 'vs/base/common/event'; +import { IDisposable } from 'vs/base/common/lifecycle'; -+import { OS } from 'vs/base/common/platform'; ++import * as platform from 'vs/base/common/platform'; ++import * as resources from 'vs/base/common/resources'; +import { ReadableStreamEventPayload } from 'vs/base/common/stream'; +import { URI, UriComponents } from 'vs/base/common/uri'; +import { transformOutgoingURIs } from 'vs/base/common/uriIpc'; @@ -1494,8 +1497,17 @@ index 0000000000000000000000000000000000000000..6fb1ada50628d3826a493c6e1b58f27a +import { getTranslations } from 'vs/server/node/nls'; +import { getUriTransformer } from 'vs/server/node/util'; +import { IFileChangeDto } from 'vs/workbench/api/common/extHost.protocol'; ++import { IEnvironmentVariableCollection } from 'vs/workbench/contrib/terminal/common/environmentVariable'; ++import { MergedEnvironmentVariableCollection } from 'vs/workbench/contrib/terminal/common/environmentVariableCollection'; ++import { deserializeEnvironmentVariableCollection } from 'vs/workbench/contrib/terminal/common/environmentVariableShared'; +import * as terminal from 'vs/workbench/contrib/terminal/common/remoteTerminalChannel'; -+import { ITerminalLaunchError } from 'vs/workbench/contrib/terminal/common/terminal'; ++import { IShellLaunchConfig, ITerminalEnvironment, ITerminalLaunchError } from 'vs/workbench/contrib/terminal/common/terminal'; ++import { TerminalDataBufferer } from 'vs/workbench/contrib/terminal/common/terminalDataBuffering'; ++import * as terminalEnvironment from 'vs/workbench/contrib/terminal/common/terminalEnvironment'; ++import { getSystemShell } from 'vs/workbench/contrib/terminal/node/terminal'; ++import { getMainProcessParentEnv } from 'vs/workbench/contrib/terminal/node/terminalEnvironment'; ++import { TerminalProcess } from 'vs/workbench/contrib/terminal/node/terminalProcess'; ++import { AbstractVariableResolverService } from 'vs/workbench/services/configurationResolver/common/variableResolver'; +import { ExtensionScanner, ExtensionScannerInput } from 'vs/workbench/services/extensions/node/extensionPoints'; + +/** @@ -1724,7 +1736,7 @@ index 0000000000000000000000000000000000000000..6fb1ada50628d3826a493c6e1b58f27a + globalStorageHome: this.environment.globalStorageHome, + workspaceStorageHome: this.environment.workspaceStorageHome, + userHome: this.environment.userHome, -+ os: OS, ++ os: platform.OS, + }; + } + @@ -1833,7 +1845,180 @@ index 0000000000000000000000000000000000000000..6fb1ada50628d3826a493c6e1b58f27a + } +} + ++class VariableResolverService extends AbstractVariableResolverService { ++ constructor(folders: terminal.IWorkspaceFolderData[], env: platform.IProcessEnvironment) { ++ super({ ++ getFolderUri: (name: string): URI | undefined => { ++ const folder = folders.find((f) => f.name === name); ++ return folder && URI.revive(folder.uri); ++ }, ++ getWorkspaceFolderCount: (): number => { ++ return folders.length; ++ }, ++ getConfigurationValue: (uri: URI, section: string): string | undefined => { ++ throw new Error("not implemented"); ++ }, ++ getExecPath: (): string | undefined => { ++ return env['VSCODE_EXEC_PATH']; ++ }, ++ getFilePath: (): string | undefined => { ++ throw new Error("not implemented"); ++ }, ++ getSelectedText: (): string | undefined => { ++ throw new Error("not implemented"); ++ }, ++ getLineNumber: (): string | undefined => { ++ throw new Error("not implemented"); ++ } ++ }, undefined, env); ++ } ++} ++ ++class Terminal { ++ private readonly process: TerminalProcess; ++ private _pid: number = -1; ++ private _title: string = ""; ++ public readonly workspaceId: string; ++ public readonly workspaceName: string; ++ ++ private readonly _onDispose = new Emitter(); ++ public get onDispose(): Event { return this._onDispose.event; } ++ ++ private buffering = false; ++ private readonly _onEvent = new Emitter({ ++ // Don't bind to data until something is listening. ++ onFirstListenerAdd: () => { ++ logger.debug('Terminal bound', field('id', this.id)); ++ if (!this.buffering) { ++ this.buffering = true; ++ this.bufferer.startBuffering(this.id, this.process.onProcessData); ++ } ++ }, ++ }); ++ ++ public get onEvent(): Event { return this._onEvent.event; } ++ ++ // Buffer to reduce the number of messages going to the renderer. ++ private readonly bufferer = new TerminalDataBufferer((_, data) => { ++ this._onEvent.fire({ ++ type: 'data', ++ data, ++ }); ++ }); ++ ++ public get pid(): number { ++ return this._pid; ++ } ++ ++ public get title(): string { ++ return this._title; ++ } ++ ++ public constructor( ++ public readonly id: number, ++ config: IShellLaunchConfig & { cwd: string }, ++ args: terminal.ICreateTerminalProcessArguments, ++ env: platform.IProcessEnvironment, ++ logService: ILogService, ++ ) { ++ this.workspaceId = args.workspaceId; ++ this.workspaceName = args.workspaceName; ++ ++ this.process = new TerminalProcess( ++ config, ++ config.cwd, ++ args.cols, ++ args.rows, ++ env, ++ process.env as platform.IProcessEnvironment, // Environment used for `findExecutable`. ++ false, // windowsEnableConpty: boolean, ++ logService, ++ ); ++ ++ // The current pid and title aren't exposed so they have to be tracked. ++ this.process.onProcessReady((event) => { ++ this._pid = event.pid; ++ this._onEvent.fire({ ++ type: 'ready', ++ pid: event.pid, ++ cwd: event.cwd, ++ }); ++ }); ++ ++ this.process.onProcessTitleChanged((title) => { ++ this._title = title; ++ this._onEvent.fire({ ++ type: 'titleChanged', ++ title, ++ }); ++ }); ++ ++ this.process.onProcessExit((exitCode) => { ++ logger.debug('Terminal exited', field('id', this.id), field('code', exitCode)); ++ this._onEvent.fire({ ++ type: 'exit', ++ exitCode, ++ }); ++ this.dispose(); ++ }); ++ ++ // TODO: replay event ++ // type: 'replay'; ++ // events: ReplayEntry[]; ++ ++ // TODO: exec command event ++ // type: 'execCommand'; ++ // reqId: number; ++ // commandId: string; ++ // commandArgs: any[]; ++ ++ // TODO: orphan question event ++ // type: 'orphan?'; ++ } ++ ++ public dispose() { ++ this._onEvent.dispose(); ++ this.bufferer.dispose(); ++ this.process.dispose(); ++ this._onDispose.fire(); ++ this._onDispose.dispose(); ++ } ++ ++ public shutdown(immediate: boolean): void { ++ return this.process.shutdown(immediate); ++ } ++ ++ public getCwd(): Promise { ++ return this.process.getCwd(); ++ } ++ ++ public getInitialCwd(): Promise { ++ return this.process.getInitialCwd(); ++ } ++ ++ public start(): Promise { ++ return this.process.start(); ++ } ++ ++ public input(data: string): void { ++ return this.process.input(data); ++ } ++ ++ public resize(cols: number, rows: number): void { ++ return this.process.resize(cols, rows); ++ } ++} ++ ++// References: - ../../workbench/api/node/extHostTerminalService.ts ++// - ../../workbench/contrib/terminal/browser/terminalProcessManager.ts +export class TerminalProviderChannel implements IServerChannel, IDisposable { ++ private readonly terminals = new Map(); ++ private id = 0; ++ ++ public constructor (private readonly logService: ILogService) { ++ ++ } ++ + public listen(_: RemoteAgentConnectionContext, event: string, args?: any): Event { + switch (event) { + case '$onTerminalProcessEvent': return this.onTerminalProcessEvent(args); @@ -1843,12 +2028,12 @@ index 0000000000000000000000000000000000000000..6fb1ada50628d3826a493c6e1b58f27a + } + + private onTerminalProcessEvent(args: terminal.IOnTerminalProcessEventArguments): Event { -+ throw new Error('not implemented'); ++ return this.getTerminal(args.id).onEvent; + } + -+ public call(_: unknown, command: string, args?: any): Promise { ++ public call(context: RemoteAgentConnectionContext, command: string, args?: any): Promise { + switch (command) { -+ case '$createTerminalProcess': return this.createTerminalProcess(args); ++ case '$createTerminalProcess': return this.createTerminalProcess(context.remoteAuthority, args); + case '$startTerminalProcess': return this.startTerminalProcess(args); + case '$sendInputToTerminalProcess': return this.sendInputToTerminalProcess(args); + case '$shutdownTerminalProcess': return this.shutdownTerminalProcess(args); @@ -1864,35 +2049,182 @@ index 0000000000000000000000000000000000000000..6fb1ada50628d3826a493c6e1b58f27a + } + + public dispose(): void { -+ // Nothing yet. ++ this.terminals.forEach((t) => t.dispose()); + } + -+ private async createTerminalProcess(args: terminal.ICreateTerminalProcessArguments): Promise { -+ throw new Error(`not implemented`); ++ private async createTerminalProcess(remoteAuthority: string, args: terminal.ICreateTerminalProcessArguments): Promise { ++ const terminalId = this.id++; ++ logger.debug('Creating terminal', field('id', terminalId), field("terminals", this.terminals.size)); ++ ++ const shellLaunchConfig: IShellLaunchConfig = { ++ name: args.shellLaunchConfig.name, ++ executable: args.shellLaunchConfig.executable, ++ args: args.shellLaunchConfig.args, ++ cwd: this.transform(remoteAuthority, args.shellLaunchConfig.cwd), ++ env: args.shellLaunchConfig.env, ++ }; ++ ++ // TODO: is this supposed to be the *last* workspace? ++ ++ const activeWorkspaceUri = this.transform(remoteAuthority, args.activeWorkspaceFolder?.uri); ++ const activeWorkspace = activeWorkspaceUri && args.activeWorkspaceFolder ? { ++ ...args.activeWorkspaceFolder, ++ uri: activeWorkspaceUri, ++ toResource: (relativePath: string) => resources.joinPath(activeWorkspaceUri, relativePath), ++ } : undefined; ++ ++ const resolverService = new VariableResolverService(args.workspaceFolders, process.env as platform.IProcessEnvironment); ++ const resolver = terminalEnvironment.createVariableResolver(activeWorkspace, resolverService); ++ ++ const getDefaultShellAndArgs = (): { executable: string; args: string[] | string } => { ++ if (shellLaunchConfig.executable) { ++ const executable = resolverService.resolve(activeWorkspace, shellLaunchConfig.executable); ++ let resolvedArgs: string[] | string = []; ++ if (shellLaunchConfig.args && Array.isArray(shellLaunchConfig.args)) { ++ for (const arg of shellLaunchConfig.args) { ++ resolvedArgs.push(resolverService.resolve(activeWorkspace, arg)); ++ } ++ } else if (shellLaunchConfig.args) { ++ resolvedArgs = resolverService.resolve(activeWorkspace, shellLaunchConfig.args); ++ } ++ return { executable, args: resolvedArgs }; ++ } ++ ++ const executable = terminalEnvironment.getDefaultShell( ++ (key) => args.configuration[key], ++ args.isWorkspaceShellAllowed, ++ getSystemShell(platform.platform), ++ process.env.hasOwnProperty('PROCESSOR_ARCHITEW6432'), ++ process.env.windir, ++ resolver, ++ this.logService, ++ false, // useAutomationShell ++ ); ++ ++ const resolvedArgs = terminalEnvironment.getDefaultShellArgs( ++ (key) => args.configuration[key], ++ args.isWorkspaceShellAllowed, ++ false, // useAutomationShell ++ resolver, ++ this.logService, ++ ); ++ ++ return { executable, args: resolvedArgs }; ++ }; ++ ++ const getInitialCwd = (): string => { ++ return terminalEnvironment.getCwd( ++ shellLaunchConfig, ++ os.homedir(), ++ resolver, ++ activeWorkspaceUri, ++ args.configuration['terminal.integrated.cwd'], ++ this.logService, ++ ); ++ }; ++ ++ // Use a separate var so Typescript recognizes these properties are no ++ // longer undefined. ++ const resolvedShellLaunchConfig = { ++ ...shellLaunchConfig, ++ ...getDefaultShellAndArgs(), ++ cwd: getInitialCwd(), ++ }; ++ ++ logger.debug('Resolved shell launch configuration', field('id', terminalId)); ++ ++ // Use instead of `terminal.integrated.env.${platform}` to make types work. ++ const getEnvFromConfig = (): terminal.ISingleTerminalConfiguration => { ++ if (platform.isWindows) { ++ return args.configuration['terminal.integrated.env.windows']; ++ } else if (platform.isMacintosh) { ++ return args.configuration['terminal.integrated.env.osx']; ++ } ++ return args.configuration['terminal.integrated.env.linux']; ++ }; ++ ++ const getNonInheritedEnv = async (): Promise => { ++ const env = await getMainProcessParentEnv(); ++ env.VSCODE_IPC_HOOK_CLI = process.env['VSCODE_IPC_HOOK_CLI']!; ++ return env; ++ }; ++ ++ const env = terminalEnvironment.createTerminalEnvironment( ++ shellLaunchConfig, ++ getEnvFromConfig(), ++ resolver, ++ args.isWorkspaceShellAllowed, ++ product.version, ++ args.configuration['terminal.integrated.detectLocale'], ++ args.configuration['terminal.integrated.inheritEnv'] !== false ++ ? process.env as platform.IProcessEnvironment ++ : await getNonInheritedEnv() ++ ); ++ ++ // Apply extension environment variable collections to the environment. ++ if (!shellLaunchConfig.strictEnv) { ++ // They come in an array and in serialized format. ++ const envVariableCollections = new Map(); ++ for (const [k, v] of args.envVariableCollections) { ++ envVariableCollections.set(k, { map: deserializeEnvironmentVariableCollection(v) }); ++ } ++ const mergedCollection = new MergedEnvironmentVariableCollection(envVariableCollections); ++ mergedCollection.applyToProcessEnvironment(env); ++ } ++ ++ logger.debug('Resolved terminal environment', field('id', terminalId)); ++ ++ const terminal = new Terminal(terminalId, resolvedShellLaunchConfig, args, env, this.logService); ++ this.terminals.set(terminalId, terminal); ++ logger.debug('Created terminal', field('id', terminalId)); ++ terminal.onDispose(() => this.terminals.delete(terminalId)); ++ ++ return { ++ terminalId, ++ resolvedShellLaunchConfig, ++ }; ++ } ++ ++ private transform(remoteAuthority: string, uri: UriComponents | undefined): URI | undefined ++ private transform(remoteAuthority: string, uri: string | UriComponents | undefined): string | URI | undefined ++ private transform(remoteAuthority: string, uri: string | UriComponents | undefined): string | URI | undefined { ++ if (typeof uri === 'string') { ++ return uri; ++ } ++ const transformer = getUriTransformer(remoteAuthority); ++ return uri ? URI.revive(transformer.transformIncoming(uri)) : uri; ++ } ++ ++ private getTerminal(id: number): Terminal { ++ const terminal = this.terminals.get(id); ++ if (!terminal) { ++ throw new Error(`terminal with id ${id} does not exist`); ++ } ++ return terminal; + } + + private async startTerminalProcess(args: terminal.IStartTerminalProcessArguments): Promise { -+ throw new Error('not implemented'); ++ return this.getTerminal(args.id).start(); + } + + private async sendInputToTerminalProcess(args: terminal.ISendInputToTerminalProcessArguments): Promise { -+ throw new Error('not implemented'); ++ return this.getTerminal(args.id).input(args.data); + } + + private async shutdownTerminalProcess(args: terminal.IShutdownTerminalProcessArguments): Promise { -+ throw new Error('not implemented'); ++ return this.getTerminal(args.id).shutdown(args.immediate); + } + + private async resizeTerminalProcess(args: terminal.IResizeTerminalProcessArguments): Promise { -+ throw new Error('not implemented'); ++ return this.getTerminal(args.id).resize(args.cols, args.rows); + } + + private async getTerminalInitialCwd(args: terminal.IGetTerminalInitialCwdArguments): Promise { -+ throw new Error('not implemented'); ++ return this.getTerminal(args.id).getInitialCwd(); + } + + private async getTerminalCwd(args: terminal.IGetTerminalCwdArguments): Promise { -+ throw new Error('not implemented'); ++ return this.getTerminal(args.id).getCwd(); + } + + private async sendCommandResultToTerminalProcess(args: terminal.ISendCommandResultToTerminalProcessArguments): Promise { @@ -1903,8 +2235,19 @@ index 0000000000000000000000000000000000000000..6fb1ada50628d3826a493c6e1b58f27a + throw new Error('not implemented'); + } + -+ private async listTerminals(args: terminal.IListTerminalsArgs): Promise { -+ throw new Error('not implemented'); ++ private async listTerminals(_: terminal.IListTerminalsArgs): Promise { ++ // TODO: args.isInitialization ++ return Promise.all(Array.from(this.terminals).map(async ([id, terminal]) => { ++ const cwd = await terminal.getCwd(); ++ return { ++ id, ++ pid: terminal.pid, ++ title: terminal.title, ++ cwd, ++ workspaceId: "0", ++ workspaceName: "test", ++ }; ++ })); + } +} diff --git a/src/vs/server/node/connection.ts b/src/vs/server/node/connection.ts @@ -2662,7 +3005,7 @@ index 0000000000000000000000000000000000000000..0d9310038c0ca378579652d89bc8ac84 +} diff --git a/src/vs/server/node/server.ts b/src/vs/server/node/server.ts new file mode 100644 -index 0000000000000000000000000000000000000000..ebd3fbdf7554c63d23ad6bd0e51e0a35a94509dd +index 0000000000000000000000000000000000000000..c10a5a3a6771a94b2cbcb699bb1261051c71e08b --- /dev/null +++ b/src/vs/server/node/server.ts @@ -0,0 +1,302 @@ @@ -2955,7 +3298,7 @@ index 0000000000000000000000000000000000000000..ebd3fbdf7554c63d23ad6bd0e51e0a35 + this.ipc.registerChannel('nodeProxy', new NodeProxyChannel(accessor.get(INodeProxyService))); + this.ipc.registerChannel('localizations', >createChannelReceiver(accessor.get(ILocalizationsService))); + this.ipc.registerChannel(REMOTE_FILE_SYSTEM_CHANNEL_NAME, new FileProviderChannel(environmentService, logService)); -+ this.ipc.registerChannel(REMOTE_TERMINAL_CHANNEL_NAME, new TerminalProviderChannel()); ++ this.ipc.registerChannel(REMOTE_TERMINAL_CHANNEL_NAME, new TerminalProviderChannel(logService)); + resolve(new ErrorTelemetry(telemetryService)); + }); + }); From 4de251116264052867427bcd732fd5af2f942901 Mon Sep 17 00:00:00 2001 From: Asher Date: Tue, 17 Nov 2020 17:03:15 -0600 Subject: [PATCH 05/13] Implement terminal replay event --- ci/dev/vscode.patch | 71 ++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 63 insertions(+), 8 deletions(-) diff --git a/ci/dev/vscode.patch b/ci/dev/vscode.patch index d8a5f2c0..49058f4f 100644 --- a/ci/dev/vscode.patch +++ b/ci/dev/vscode.patch @@ -1466,10 +1466,10 @@ index 0000000000000000000000000000000000000000..6ce56bec114a6d8daf5dd3ded945ea78 +} diff --git a/src/vs/server/node/channel.ts b/src/vs/server/node/channel.ts new file mode 100644 -index 0000000000000000000000000000000000000000..91a932b613c473cd13dfddbde2942aeebf4bb84c +index 0000000000000000000000000000000000000000..cb3a45fda10a6bcbff73275b5734641b3319cc9b --- /dev/null +++ b/src/vs/server/node/channel.ts -@@ -0,0 +1,780 @@ +@@ -0,0 +1,828 @@ +import { field, logger } from '@coder/logger'; +import { Server } from '@coder/node-browser'; +import * as os from 'os'; @@ -1884,6 +1884,14 @@ index 0000000000000000000000000000000000000000..91a932b613c473cd13dfddbde2942aee + private readonly _onDispose = new Emitter(); + public get onDispose(): Event { return this._onDispose.event; } + ++ // These are replayed when a client reconnects. ++ private cols: number; ++ private rows: number; ++ private replayData: string[] = []; ++ // This is based on string length and is pretty arbitrary. ++ private readonly maxReplayData = 10000; ++ private totalReplayData = 0; ++ + private buffering = false; + private readonly _onEvent = new Emitter({ + // Don't bind to data until something is listening. @@ -1894,6 +1902,23 @@ index 0000000000000000000000000000000000000000..91a932b613c473cd13dfddbde2942aee + this.bufferer.startBuffering(this.id, this.process.onProcessData); + } + }, ++ ++ // Replay stored events. ++ onFirstListenerDidAdd: () => { ++ if (this.replayData.length === 0) { ++ return; ++ } ++ ++ logger.debug('Terminal replaying', field('id', this.id)); ++ this._onEvent.fire({ ++ type: 'replay', ++ events: [{ ++ cols: this.cols, ++ rows: this.rows, ++ data: this.replayData.join(""), ++ }] ++ }); ++ } + }); + + public get onEvent(): Event { return this._onEvent.event; } @@ -1904,6 +1929,33 @@ index 0000000000000000000000000000000000000000..91a932b613c473cd13dfddbde2942aee + type: 'data', + data, + }); ++ ++ this.replayData.push(data); ++ this.totalReplayData += data.length; ++ ++ let overflow = this.totalReplayData - this.maxReplayData; ++ if (overflow <= 0) { ++ return; ++ } ++ ++ // Drop events until doing so would put us under budget. ++ let deleteCount = 0; ++ for (; deleteCount < this.replayData.length ++ && this.replayData[deleteCount].length <= overflow; ++deleteCount) { ++ overflow -= this.replayData[deleteCount].length; ++ } ++ ++ if (deleteCount > 0) { ++ this.replayData.splice(0, deleteCount); ++ } ++ ++ // Dropping any more events would put us under budget; trim the first event ++ // instead if still over budget. ++ if (overflow > 0 && this.replayData.length > 0) { ++ this.replayData[0] = this.replayData[0].substring(overflow); ++ } ++ ++ this.totalReplayData = this.replayData.reduce((p, c) => p + c.length, 0); + }); + + public get pid(): number { @@ -1924,11 +1976,14 @@ index 0000000000000000000000000000000000000000..91a932b613c473cd13dfddbde2942aee + this.workspaceId = args.workspaceId; + this.workspaceName = args.workspaceName; + ++ this.cols = args.cols; ++ this.rows = args.rows; ++ + this.process = new TerminalProcess( + config, + config.cwd, -+ args.cols, -+ args.rows, ++ this.cols, ++ this.rows, + env, + process.env as platform.IProcessEnvironment, // Environment used for `findExecutable`. + false, // windowsEnableConpty: boolean, @@ -1962,10 +2017,6 @@ index 0000000000000000000000000000000000000000..91a932b613c473cd13dfddbde2942aee + this.dispose(); + }); + -+ // TODO: replay event -+ // type: 'replay'; -+ // events: ReplayEntry[]; -+ + // TODO: exec command event + // type: 'execCommand'; + // reqId: number; @@ -1977,9 +2028,11 @@ index 0000000000000000000000000000000000000000..91a932b613c473cd13dfddbde2942aee + } + + public dispose() { ++ logger.debug('Terminal disposing', field('id', this.id)); + this._onEvent.dispose(); + this.bufferer.dispose(); + this.process.dispose(); ++ this.process.shutdown(true); + this._onDispose.fire(); + this._onDispose.dispose(); + } @@ -2005,6 +2058,8 @@ index 0000000000000000000000000000000000000000..91a932b613c473cd13dfddbde2942aee + } + + public resize(cols: number, rows: number): void { ++ this.cols = cols; ++ this.rows = rows; + return this.process.resize(cols, rows); + } +} From 8311cf5657c7264c71373f1f15e0016da9336364 Mon Sep 17 00:00:00 2001 From: Asher Date: Tue, 17 Nov 2020 17:51:17 -0600 Subject: [PATCH 06/13] Handle non-persistent terminals --- ci/dev/vscode.patch | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/ci/dev/vscode.patch b/ci/dev/vscode.patch index 49058f4f..949bed3f 100644 --- a/ci/dev/vscode.patch +++ b/ci/dev/vscode.patch @@ -1880,6 +1880,7 @@ index 0000000000000000000000000000000000000000..cb3a45fda10a6bcbff73275b5734641b + private _title: string = ""; + public readonly workspaceId: string; + public readonly workspaceName: string; ++ private readonly persist: boolean; + + private readonly _onDispose = new Emitter(); + public get onDispose(): Event { return this._onDispose.event; } @@ -1918,6 +1919,13 @@ index 0000000000000000000000000000000000000000..cb3a45fda10a6bcbff73275b5734641b + data: this.replayData.join(""), + }] + }); ++ }, ++ ++ onLastListenerRemove: () => { ++ logger.debug('Terminal unbound', field('id', this.id)); ++ if (!this.persist) { // Used by debug consoles. ++ this.dispose(); ++ } + } + }); + @@ -1979,6 +1987,8 @@ index 0000000000000000000000000000000000000000..cb3a45fda10a6bcbff73275b5734641b + this.cols = args.cols; + this.rows = args.rows; + ++ this.persist = args.shouldPersistTerminal; ++ + this.process = new TerminalProcess( + config, + config.cwd, From 182aca649064bb54e8d00ac02e6667ee7702d0bb Mon Sep 17 00:00:00 2001 From: Asher Date: Thu, 19 Nov 2020 10:58:04 -0600 Subject: [PATCH 07/13] Only replay terminals when detached --- ci/dev/vscode.patch | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/ci/dev/vscode.patch b/ci/dev/vscode.patch index 949bed3f..7bf38f34 100644 --- a/ci/dev/vscode.patch +++ b/ci/dev/vscode.patch @@ -1466,10 +1466,10 @@ index 0000000000000000000000000000000000000000..6ce56bec114a6d8daf5dd3ded945ea78 +} diff --git a/src/vs/server/node/channel.ts b/src/vs/server/node/channel.ts new file mode 100644 -index 0000000000000000000000000000000000000000..cb3a45fda10a6bcbff73275b5734641b3319cc9b +index 0000000000000000000000000000000000000000..b65bf283739a2b05c82fe38a038d2a10957c0d40 --- /dev/null +++ b/src/vs/server/node/channel.ts -@@ -0,0 +1,828 @@ +@@ -0,0 +1,848 @@ +import { field, logger } from '@coder/logger'; +import { Server } from '@coder/node-browser'; +import * as os from 'os'; @@ -1893,6 +1893,7 @@ index 0000000000000000000000000000000000000000..cb3a45fda10a6bcbff73275b5734641b + private readonly maxReplayData = 10000; + private totalReplayData = 0; + ++ private detached = false; + private buffering = false; + private readonly _onEvent = new Emitter({ + // Don't bind to data until something is listening. @@ -1906,10 +1907,11 @@ index 0000000000000000000000000000000000000000..cb3a45fda10a6bcbff73275b5734641b + + // Replay stored events. + onFirstListenerDidAdd: () => { -+ if (this.replayData.length === 0) { ++ if (!this.detached) { + return; + } + ++ this.detached = false; + logger.debug('Terminal replaying', field('id', this.id)); + this._onEvent.fire({ + type: 'replay', @@ -1922,6 +1924,7 @@ index 0000000000000000000000000000000000000000..cb3a45fda10a6bcbff73275b5734641b + }, + + onLastListenerRemove: () => { ++ this.detached = true; + logger.debug('Terminal unbound', field('id', this.id)); + if (!this.persist) { // Used by debug consoles. + this.dispose(); From 1feb30a7ff18149f94ad171f42edc82a8844cfef Mon Sep 17 00:00:00 2001 From: Asher Date: Thu, 19 Nov 2020 11:11:46 -0600 Subject: [PATCH 08/13] Send back workspace ID and name in terminal list This makes it re-connect automatically. --- ci/dev/vscode.patch | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ci/dev/vscode.patch b/ci/dev/vscode.patch index 7bf38f34..00c05d9d 100644 --- a/ci/dev/vscode.patch +++ b/ci/dev/vscode.patch @@ -1466,7 +1466,7 @@ index 0000000000000000000000000000000000000000..6ce56bec114a6d8daf5dd3ded945ea78 +} diff --git a/src/vs/server/node/channel.ts b/src/vs/server/node/channel.ts new file mode 100644 -index 0000000000000000000000000000000000000000..b65bf283739a2b05c82fe38a038d2a10957c0d40 +index 0000000000000000000000000000000000000000..40779e80aa56d6b802d39f7170c9c94a997393ef --- /dev/null +++ b/src/vs/server/node/channel.ts @@ -0,0 +1,848 @@ @@ -2312,8 +2312,8 @@ index 0000000000000000000000000000000000000000..b65bf283739a2b05c82fe38a038d2a10 + pid: terminal.pid, + title: terminal.title, + cwd, -+ workspaceId: "0", -+ workspaceName: "test", ++ workspaceId: terminal.workspaceId, ++ workspaceName: terminal.workspaceName, + }; + })); + } From a6f884000995b85cdbec3e857eae893fd59b67b5 Mon Sep 17 00:00:00 2001 From: Asher Date: Thu, 19 Nov 2020 11:21:15 -0600 Subject: [PATCH 09/13] Add timeout for disposing detached terminals --- ci/dev/vscode.patch | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/ci/dev/vscode.patch b/ci/dev/vscode.patch index 00c05d9d..3d763375 100644 --- a/ci/dev/vscode.patch +++ b/ci/dev/vscode.patch @@ -1466,10 +1466,10 @@ index 0000000000000000000000000000000000000000..6ce56bec114a6d8daf5dd3ded945ea78 +} diff --git a/src/vs/server/node/channel.ts b/src/vs/server/node/channel.ts new file mode 100644 -index 0000000000000000000000000000000000000000..40779e80aa56d6b802d39f7170c9c94a997393ef +index 0000000000000000000000000000000000000000..95d0d3c51e4a25a9d7d0cada90d031c79bd86380 --- /dev/null +++ b/src/vs/server/node/channel.ts -@@ -0,0 +1,848 @@ +@@ -0,0 +1,860 @@ +import { field, logger } from '@coder/logger'; +import { Server } from '@coder/node-browser'; +import * as os from 'os'; @@ -1893,7 +1893,12 @@ index 0000000000000000000000000000000000000000..40779e80aa56d6b802d39f7170c9c94a + private readonly maxReplayData = 10000; + private totalReplayData = 0; + -+ private detached = false; ++ // According to the release notes the terminals are supposed to dispose after ++ // a short timeout; in our case we'll use 48 hours so you can get them back ++ // the next day or over the weekend. ++ private disposeTimeout: NodeJS.Timeout | undefined; ++ private disposeDelay = 48 * 60 * 60 * 1000; ++ + private buffering = false; + private readonly _onEvent = new Emitter({ + // Don't bind to data until something is listening. @@ -1907,11 +1912,15 @@ index 0000000000000000000000000000000000000000..40779e80aa56d6b802d39f7170c9c94a + + // Replay stored events. + onFirstListenerDidAdd: () => { -+ if (!this.detached) { ++ // We only need to replay if the terminal is being reconnected which is ++ // true if there is a dispose timeout. ++ if (typeof this.disposeTimeout !== "undefined") { + return; + } + -+ this.detached = false; ++ clearTimeout(this.disposeTimeout); ++ this.disposeTimeout = undefined; ++ + logger.debug('Terminal replaying', field('id', this.id)); + this._onEvent.fire({ + type: 'replay', @@ -1924,10 +1933,13 @@ index 0000000000000000000000000000000000000000..40779e80aa56d6b802d39f7170c9c94a + }, + + onLastListenerRemove: () => { -+ this.detached = true; + logger.debug('Terminal unbound', field('id', this.id)); + if (!this.persist) { // Used by debug consoles. + this.dispose(); ++ } else { ++ this.disposeTimeout = setTimeout(() => { ++ this.dispose(); ++ }, this.disposeDelay); + } + } + }); From 8ffe5997965e2be5c30ef5c8ecd9717fb286a61d Mon Sep 17 00:00:00 2001 From: Asher Date: Thu, 19 Nov 2020 11:24:52 -0600 Subject: [PATCH 10/13] Add notes on unimplemented terminal events --- ci/dev/vscode.patch | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/ci/dev/vscode.patch b/ci/dev/vscode.patch index 3d763375..17ee4130 100644 --- a/ci/dev/vscode.patch +++ b/ci/dev/vscode.patch @@ -1466,10 +1466,10 @@ index 0000000000000000000000000000000000000000..6ce56bec114a6d8daf5dd3ded945ea78 +} diff --git a/src/vs/server/node/channel.ts b/src/vs/server/node/channel.ts new file mode 100644 -index 0000000000000000000000000000000000000000..95d0d3c51e4a25a9d7d0cada90d031c79bd86380 +index 0000000000000000000000000000000000000000..7081bbf178c660803830675a4d8d596c5d0b7821 --- /dev/null +++ b/src/vs/server/node/channel.ts -@@ -0,0 +1,860 @@ +@@ -0,0 +1,869 @@ +import { field, logger } from '@coder/logger'; +import { Server } from '@coder/node-browser'; +import * as os from 'os'; @@ -2042,13 +2042,17 @@ index 0000000000000000000000000000000000000000..95d0d3c51e4a25a9d7d0cada90d031c7 + this.dispose(); + }); + -+ // TODO: exec command event ++ // TODO: I think `execCommand` must have something to do with running ++ // commands on the terminal that will do things in VS Code but we already ++ // have that functionality via a socket so I'm not sure what this is for. + // type: 'execCommand'; + // reqId: number; + // commandId: string; + // commandArgs: any[]; + -+ // TODO: orphan question event ++ // TODO: Maybe this is to ask if the terminal is currently attached to ++ // anything? But we already know that on account of whether anything is ++ // listening to our event emitter. + // type: 'orphan?'; + } + @@ -2307,16 +2311,21 @@ index 0000000000000000000000000000000000000000..95d0d3c51e4a25a9d7d0cada90d031c7 + return this.getTerminal(args.id).getCwd(); + } + -+ private async sendCommandResultToTerminalProcess(args: terminal.ISendCommandResultToTerminalProcessArguments): Promise { ++ private async sendCommandResultToTerminalProcess(_: terminal.ISendCommandResultToTerminalProcessArguments): Promise { ++ // NOTE: Not required unless we implement the `execCommand` event, see above. + throw new Error('not implemented'); + } + -+ private async orphanQuestionReply(args: terminal.IOrphanQuestionReplyArgs): Promise { ++ private async orphanQuestionReply(_: terminal.IOrphanQuestionReplyArgs): Promise { ++ // NOTE: Not required unless we implement the `orphan?` event, see above. + throw new Error('not implemented'); + } + + private async listTerminals(_: terminal.IListTerminalsArgs): Promise { -+ // TODO: args.isInitialization ++ // TODO: args.isInitialization. Maybe this is to have slightly different ++ // behavior when first listing terminals but I don't know what you'd want to ++ // do differently. Maybe it's to reset the terminal dispose timeouts or ++ // something like that, but why not do it each time you list? + return Promise.all(Array.from(this.terminals).map(async ([id, terminal]) => { + const cwd = await terminal.getCwd(); + return { From fa59156a2aa30fc9d3e4332046a0dab749f6bc7e Mon Sep 17 00:00:00 2001 From: Asher Date: Thu, 19 Nov 2020 12:26:31 -0600 Subject: [PATCH 11/13] Implement remaining resolver methods --- ci/dev/vscode.patch | 70 ++++++++++++++++++++++++++++----------------- 1 file changed, 44 insertions(+), 26 deletions(-) diff --git a/ci/dev/vscode.patch b/ci/dev/vscode.patch index 17ee4130..4ec8b266 100644 --- a/ci/dev/vscode.patch +++ b/ci/dev/vscode.patch @@ -1466,10 +1466,10 @@ index 0000000000000000000000000000000000000000..6ce56bec114a6d8daf5dd3ded945ea78 +} diff --git a/src/vs/server/node/channel.ts b/src/vs/server/node/channel.ts new file mode 100644 -index 0000000000000000000000000000000000000000..7081bbf178c660803830675a4d8d596c5d0b7821 +index 0000000000000000000000000000000000000000..7619b02f04b6e61e86e741b09b542d86fab97e3d --- /dev/null +++ b/src/vs/server/node/channel.ts -@@ -0,0 +1,869 @@ +@@ -0,0 +1,887 @@ +import { field, logger } from '@coder/logger'; +import { Server } from '@coder/node-browser'; +import * as os from 'os'; @@ -1846,30 +1846,51 @@ index 0000000000000000000000000000000000000000..7081bbf178c660803830675a4d8d596c +} + +class VariableResolverService extends AbstractVariableResolverService { -+ constructor(folders: terminal.IWorkspaceFolderData[], env: platform.IProcessEnvironment) { ++ constructor( ++ remoteAuthority: string, ++ args: terminal.ICreateTerminalProcessArguments, ++ env: platform.IProcessEnvironment, ++ ) { + super({ + getFolderUri: (name: string): URI | undefined => { -+ const folder = folders.find((f) => f.name === name); ++ const folder = args.workspaceFolders.find((f) => f.name === name); + return folder && URI.revive(folder.uri); + }, + getWorkspaceFolderCount: (): number => { -+ return folders.length; ++ return args.workspaceFolders.length; + }, -+ getConfigurationValue: (uri: URI, section: string): string | undefined => { -+ throw new Error("not implemented"); ++ // In ../../workbench/contrib/terminal/common/remoteTerminalChannel.ts it ++ // looks like there are `config:` entries which must be for this? Not sure ++ // how/if the URI comes into play though. ++ getConfigurationValue: (_: URI, section: string): string | undefined => { ++ return args.resolvedVariables[`config:${section}`]; + }, + getExecPath: (): string | undefined => { + return env['VSCODE_EXEC_PATH']; + }, ++ // This is just a guess; this is the only file-related thing we're sent ++ // and none of these resolver methods seem to get called so I don't know ++ // how to test. + getFilePath: (): string | undefined => { -+ throw new Error("not implemented"); ++ const resource = transformIncoming(remoteAuthority, args.activeFileResource); ++ if (!resource) { ++ return undefined; ++ } ++ // See ../../editor/standalone/browser/simpleServices.ts; ++ // `BaseConfigurationResolverService` calls `getUriLabel` from there. ++ if (resource.scheme === 'file') { ++ return resource.fsPath; ++ } ++ return resource.path; + }, ++ // It looks like these are set here although they aren't on the types: ++ // ../../workbench/contrib/terminal/common/remoteTerminalChannel.ts + getSelectedText: (): string | undefined => { -+ throw new Error("not implemented"); ++ return args.resolvedVariables.selectedText; + }, + getLineNumber: (): string | undefined => { -+ throw new Error("not implemented"); -+ } ++ return args.resolvedVariables.selectedText; ++ }, + }, undefined, env); + } +} @@ -2144,20 +2165,22 @@ index 0000000000000000000000000000000000000000..7081bbf178c660803830675a4d8d596c + name: args.shellLaunchConfig.name, + executable: args.shellLaunchConfig.executable, + args: args.shellLaunchConfig.args, -+ cwd: this.transform(remoteAuthority, args.shellLaunchConfig.cwd), ++ // TODO: Should we transform if it's a string as well? The incoming ++ // transform only takes `UriComponents` so I suspect it's not necessary. ++ cwd: typeof args.shellLaunchConfig.cwd !== "string" ++ ? transformIncoming(remoteAuthority, args.shellLaunchConfig.cwd) ++ : args.shellLaunchConfig.cwd, + env: args.shellLaunchConfig.env, + }; + -+ // TODO: is this supposed to be the *last* workspace? -+ -+ const activeWorkspaceUri = this.transform(remoteAuthority, args.activeWorkspaceFolder?.uri); ++ const activeWorkspaceUri = transformIncoming(remoteAuthority, args.activeWorkspaceFolder?.uri); + const activeWorkspace = activeWorkspaceUri && args.activeWorkspaceFolder ? { + ...args.activeWorkspaceFolder, + uri: activeWorkspaceUri, + toResource: (relativePath: string) => resources.joinPath(activeWorkspaceUri, relativePath), + } : undefined; + -+ const resolverService = new VariableResolverService(args.workspaceFolders, process.env as platform.IProcessEnvironment); ++ const resolverService = new VariableResolverService(remoteAuthority, args, process.env as platform.IProcessEnvironment); + const resolver = terminalEnvironment.createVariableResolver(activeWorkspace, resolverService); + + const getDefaultShellAndArgs = (): { executable: string; args: string[] | string } => { @@ -2269,16 +2292,6 @@ index 0000000000000000000000000000000000000000..7081bbf178c660803830675a4d8d596c + }; + } + -+ private transform(remoteAuthority: string, uri: UriComponents | undefined): URI | undefined -+ private transform(remoteAuthority: string, uri: string | UriComponents | undefined): string | URI | undefined -+ private transform(remoteAuthority: string, uri: string | UriComponents | undefined): string | URI | undefined { -+ if (typeof uri === 'string') { -+ return uri; -+ } -+ const transformer = getUriTransformer(remoteAuthority); -+ return uri ? URI.revive(transformer.transformIncoming(uri)) : uri; -+ } -+ + private getTerminal(id: number): Terminal { + const terminal = this.terminals.get(id); + if (!terminal) { @@ -2339,6 +2352,11 @@ index 0000000000000000000000000000000000000000..7081bbf178c660803830675a4d8d596c + })); + } +} ++ ++function transformIncoming(remoteAuthority: string, uri: UriComponents | undefined): URI | undefined { ++ const transformer = getUriTransformer(remoteAuthority); ++ return uri ? URI.revive(transformer.transformIncoming(uri)) : uri; ++} diff --git a/src/vs/server/node/connection.ts b/src/vs/server/node/connection.ts new file mode 100644 index 0000000000000000000000000000000000000000..93062cadc627c61e0829c27a72894b81e6a0e039 From d0f6cbb02d73cc80ca42390c87bd6386b4390f00 Mon Sep 17 00:00:00 2001 From: Asher Date: Thu, 19 Nov 2020 12:42:59 -0600 Subject: [PATCH 12/13] Use resolverEnv to get exec path This is the last unused variable in the create terminal payload. --- ci/dev/vscode.patch | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/ci/dev/vscode.patch b/ci/dev/vscode.patch index 4ec8b266..0bcec08e 100644 --- a/ci/dev/vscode.patch +++ b/ci/dev/vscode.patch @@ -1466,10 +1466,10 @@ index 0000000000000000000000000000000000000000..6ce56bec114a6d8daf5dd3ded945ea78 +} diff --git a/src/vs/server/node/channel.ts b/src/vs/server/node/channel.ts new file mode 100644 -index 0000000000000000000000000000000000000000..7619b02f04b6e61e86e741b09b542d86fab97e3d +index 0000000000000000000000000000000000000000..769d57953e782b7a72519599274630236114b17d --- /dev/null +++ b/src/vs/server/node/channel.ts -@@ -0,0 +1,887 @@ +@@ -0,0 +1,889 @@ +import { field, logger } from '@coder/logger'; +import { Server } from '@coder/node-browser'; +import * as os from 'os'; @@ -1866,7 +1866,9 @@ index 0000000000000000000000000000000000000000..7619b02f04b6e61e86e741b09b542d86 + return args.resolvedVariables[`config:${section}`]; + }, + getExecPath: (): string | undefined => { -+ return env['VSCODE_EXEC_PATH']; ++ // Assuming that resolverEnv is just for use in the resolver and not for ++ // the terminal itself. ++ return (args.resolverEnv && args.resolverEnv['VSCODE_EXEC_PATH']) || env['VSCODE_EXEC_PATH']; + }, + // This is just a guess; this is the only file-related thing we're sent + // and none of these resolver methods seem to get called so I don't know From 42390da0978b544679fdcd0be5c4573631d52c34 Mon Sep 17 00:00:00 2001 From: Asher Date: Thu, 19 Nov 2020 15:13:46 -0600 Subject: [PATCH 13/13] Don't persist terminals for now --- ci/dev/vscode.patch | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/ci/dev/vscode.patch b/ci/dev/vscode.patch index 0bcec08e..f6af1c22 100644 --- a/ci/dev/vscode.patch +++ b/ci/dev/vscode.patch @@ -1466,10 +1466,10 @@ index 0000000000000000000000000000000000000000..6ce56bec114a6d8daf5dd3ded945ea78 +} diff --git a/src/vs/server/node/channel.ts b/src/vs/server/node/channel.ts new file mode 100644 -index 0000000000000000000000000000000000000000..769d57953e782b7a72519599274630236114b17d +index 0000000000000000000000000000000000000000..693174ee0d21353c3a08a42fd30eaad1e95c3b9d --- /dev/null +++ b/src/vs/server/node/channel.ts -@@ -0,0 +1,889 @@ +@@ -0,0 +1,897 @@ +import { field, logger } from '@coder/logger'; +import { Server } from '@coder/node-browser'; +import * as os from 'os'; @@ -1976,6 +1976,11 @@ index 0000000000000000000000000000000000000000..769d57953e782b7a7251959927463023 + data, + }); + ++ // No need to store data if we aren't persisting. ++ if (!this.persist) { ++ return; ++ } ++ + this.replayData.push(data); + this.totalReplayData += data.length; + @@ -2025,7 +2030,10 @@ index 0000000000000000000000000000000000000000..769d57953e782b7a7251959927463023 + this.cols = args.cols; + this.rows = args.rows; + -+ this.persist = args.shouldPersistTerminal; ++ // TODO: Don't persist terminals until we make it work with things like ++ // htop, vim, etc. ++ // this.persist = args.shouldPersistTerminal; ++ this.persist = false; + + this.process = new TerminalProcess( + config,