-
Notifications
You must be signed in to change notification settings - Fork 6k
feat(vscode): update to version 1.57.0 #3544
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from 1 commit
Commits
Show all changes
51 commits
Select commit
Hold shift + click to select a range
bb14cfe
Squashed 'lib/vscode/' changes from cfa2e218100..2064d4c301c
92e6bb1
chore(vscode): update to 1.57.0
d7cc072
chore(deps): fixup lockfiles
8c72047
chore: restore .gitignore
ea4705b
fix(vscode): redo extra extension paths
943504b
fix(vscode): add setSocket to PersistentProtocol
8c05721
fix(vscode): restore server files
ddf2616
fix(vscode): restore typings
a02b0ad
fix(vscode): restore proxy_agent.ts symlink
9f524bd
fix(vscode): use ptyHost.getEnv
b88ce55
fix(vscode): uriTransformer refactoring
c9a28aa
fix(vscode): add new terminal listener
f993944
fix(vscode): fix + enable layering lint
8c3c30a
chore: format file
41a72f1
Squashed 'lib/vscode/' changes from 2064d4c301c..b4c1bd0a9b0
0c818a6
Merge commit '41a72f14e8a1f0f7a9d9c7fbf4c24d89f087c733' into vscode-1.57
a4f9ff0
fix(lib/vscode): restore product.json
a07260f
fix(vscode): backport resources hotfix
e41351e
Merge branch 'main' into vscode-1.57
1aaea7e
refactor(lib/vscode): reorganize code to fit vs rules
42794e3
fix(ci): remove stray symlinks
280d609
cleanup(lib/vscode): format .gitignore
b5af44e
chore(vscode): fix formatting
5429bc1
refactor(vscode): remove parsePathArg in envService
62801c8
fix(vscode): add missing terminal commands
180fbfc
fix(vscode): update .eslintignore paths
ef29d56
chore: document uriTransformer hacks
863cf60
fix(lib/vscode): restore patches
3558f5d
fix(lib/vscode): restore more patches
5fd98a5
Squashed 'lib/vscode/' changes from b4c1bd0a9b0..507ce72a446
6a62fe8
Merge commit '5fd98a52efbbbd7ca28922fdc9c7282d9bf1ec3d' into vscode-1.57
60673bd
fmt(docs): remove trailing whitespace
4271b60
fix(test): fix e2e tests
49e9fdd
chore(deps): update vulnerable vscode deps
55dc16b
fix(test): clean up terminal test
b5f408f
Merge branch 'main' into vscode-1.57
4b418f5
Retry menu navigation in e2e tests
code-asher 7c9b1f0
Update VS Code loader with trusted types policy
code-asher 6987dd3
Update build resources with renamed file
code-asher 47d8866
Restore proposed API patch
code-asher 9e46573
Restore async storage write patch
code-asher d8a1f7d
Remove duplicate telemetry service registration
code-asher a445588
Use service in terminal channel instead of interface
code-asher 23594b2
Rename uri transformer using camel case
code-asher 3c95888
Update yarn.lock
code-asher b0e9eff
Restore .yarnrc patch
code-asher 7e3bb46
Remove gulp-tar dependency
code-asher 5e8fe4e
Cancel current menu navigation on retry
code-asher 476fcf3
chore(docs): update docs with patches
ed9c59d
Merge branch 'main' into vscode-1.57
df85813
chore(ci): increase timeout to 15 minutes
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
../../../../typings/ipc.d.ts |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,198 @@ | ||
import * as path from 'vs/base/common/path'; | ||
import { Options } from 'vs/ipc'; | ||
import { localize } from 'vs/nls'; | ||
import { MenuId, MenuRegistry } from 'vs/platform/actions/common/actions'; | ||
import { CommandsRegistry } from 'vs/platform/commands/common/commands'; | ||
import { Extensions, IConfigurationRegistry } from 'vs/platform/configuration/common/configurationRegistry'; | ||
import { ContextKeyExpr, IContextKeyService } from 'vs/platform/contextkey/common/contextkey'; | ||
import { registerSingleton } from 'vs/platform/instantiation/common/extensions'; | ||
import { ServiceCollection } from 'vs/platform/instantiation/common/serviceCollection'; | ||
import { ILogService } from 'vs/platform/log/common/log'; | ||
import { INotificationService, Severity } from 'vs/platform/notification/common/notification'; | ||
import { Registry } from 'vs/platform/registry/common/platform'; | ||
import { IStorageService, StorageScope, StorageTarget } from 'vs/platform/storage/common/storage'; | ||
import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; | ||
import { TelemetryChannelClient } from 'vs/server/common/telemetry'; | ||
import { getOptions } from 'vs/server/common/util'; | ||
import 'vs/workbench/contrib/localizations/browser/localizations.contribution'; | ||
import 'vs/workbench/services/localizations/browser/localizationsService'; | ||
import { IRemoteAgentService } from 'vs/workbench/services/remote/common/remoteAgentService'; | ||
|
||
/** | ||
* All client-side customization to VS Code should live in this file when | ||
* possible. | ||
*/ | ||
|
||
const options = getOptions<Options>(); | ||
|
||
class TelemetryService extends TelemetryChannelClient { | ||
public constructor( | ||
@IRemoteAgentService remoteAgentService: IRemoteAgentService, | ||
) { | ||
super(remoteAgentService.getConnection()!.getChannel('telemetry')); | ||
} | ||
} | ||
|
||
const TELEMETRY_SECTION_ID = 'telemetry'; | ||
Registry.as<IConfigurationRegistry>(Extensions.Configuration).registerConfiguration({ | ||
'id': TELEMETRY_SECTION_ID, | ||
'order': 110, | ||
'type': 'object', | ||
'title': localize('telemetryConfigurationTitle', 'Telemetry'), | ||
'properties': { | ||
'telemetry.enableTelemetry': { | ||
'type': 'boolean', | ||
'description': localize('telemetry.enableTelemetry', 'Enable usage data and errors to be sent to a Microsoft online service.'), | ||
'default': !options.disableTelemetry, | ||
'tags': ['usesOnlineServices'] | ||
} | ||
} | ||
}); | ||
|
||
registerSingleton(ITelemetryService, TelemetryService); | ||
|
||
/** | ||
* This is called by vs/workbench/browser/web.main.ts after the workbench has | ||
* been initialized so we can initialize our own client-side code. | ||
*/ | ||
export const initialize = async (services: ServiceCollection): Promise<void> => { | ||
const event = new CustomEvent('ide-ready'); | ||
window.dispatchEvent(event); | ||
|
||
if (parent) { | ||
// Tell the parent loading has completed. | ||
parent.postMessage({ event: 'loaded' }, '*'); | ||
|
||
// Proxy or stop proxing events as requested by the parent. | ||
const listeners = new Map<string, (event: Event) => void>(); | ||
window.addEventListener('message', (parentEvent) => { | ||
const eventName = parentEvent.data.bind || parentEvent.data.unbind; | ||
if (eventName) { | ||
const oldListener = listeners.get(eventName); | ||
if (oldListener) { | ||
document.removeEventListener(eventName, oldListener); | ||
} | ||
} | ||
|
||
if (parentEvent.data.bind && parentEvent.data.prop) { | ||
const listener = (event: Event) => { | ||
parent.postMessage({ | ||
event: parentEvent.data.event, | ||
[parentEvent.data.prop]: event[parentEvent.data.prop as keyof Event] | ||
}, window.location.origin); | ||
}; | ||
listeners.set(parentEvent.data.bind, listener); | ||
document.addEventListener(parentEvent.data.bind, listener); | ||
} | ||
}); | ||
} | ||
|
||
if (!window.isSecureContext) { | ||
(services.get(INotificationService) as INotificationService).notify({ | ||
severity: Severity.Warning, | ||
message: 'code-server is being accessed over an insecure domain. Web views, the clipboard, and other functionality will not work as expected.', | ||
actions: { | ||
primary: [{ | ||
id: 'understand', | ||
label: 'I understand', | ||
tooltip: '', | ||
class: undefined, | ||
enabled: true, | ||
checked: true, | ||
dispose: () => undefined, | ||
run: () => { | ||
return Promise.resolve(); | ||
} | ||
}], | ||
} | ||
}); | ||
} | ||
|
||
const logService = (services.get(ILogService) as ILogService); | ||
const storageService = (services.get(IStorageService) as IStorageService); | ||
const updateCheckEndpoint = path.join(options.base, '/update/check'); | ||
const getUpdate = async (): Promise<void> => { | ||
logService.debug('Checking for update...'); | ||
|
||
const response = await fetch(updateCheckEndpoint, { | ||
headers: { 'Accept': 'application/json' }, | ||
}); | ||
if (!response.ok) { | ||
throw new Error(response.statusText); | ||
} | ||
const json = await response.json(); | ||
if (json.error) { | ||
throw new Error(json.error); | ||
} | ||
if (json.isLatest) { | ||
return; | ||
} | ||
|
||
const lastNoti = storageService.getNumber('csLastUpdateNotification', StorageScope.GLOBAL); | ||
if (lastNoti) { | ||
// Only remind them again after 1 week. | ||
const timeout = 1000*60*60*24*7; | ||
const threshold = lastNoti + timeout; | ||
if (Date.now() < threshold) { | ||
return; | ||
} | ||
} | ||
|
||
storageService.store('csLastUpdateNotification', Date.now(), StorageScope.GLOBAL, StorageTarget.MACHINE); | ||
(services.get(INotificationService) as INotificationService).notify({ | ||
severity: Severity.Info, | ||
message: `[code-server v${json.latest}](https://github.com/cdr/code-server/releases/tag/v${json.latest}) has been released!`, | ||
}); | ||
}; | ||
|
||
const updateLoop = (): void => { | ||
getUpdate().catch((error) => { | ||
logService.debug(`failed to check for update: ${error}`); | ||
}).finally(() => { | ||
// Check again every 6 hours. | ||
setTimeout(updateLoop, 1000*60*60*6); | ||
}); | ||
}; | ||
|
||
if (!options.disableUpdateCheck) { | ||
updateLoop(); | ||
} | ||
|
||
// This will be used to set the background color while VS Code loads. | ||
const theme = storageService.get('colorThemeData', StorageScope.GLOBAL); | ||
if (theme) { | ||
localStorage.setItem('colorThemeData', theme); | ||
} | ||
|
||
// Use to show or hide logout commands and menu options. | ||
const contextKeyService = (services.get(IContextKeyService) as IContextKeyService); | ||
contextKeyService.createKey('code-server.authed', options.authed); | ||
|
||
// Add a logout command. | ||
const logoutEndpoint = path.join(options.base, '/logout') + `?base=${options.base}`; | ||
const LOGOUT_COMMAND_ID = 'code-server.logout'; | ||
CommandsRegistry.registerCommand( | ||
LOGOUT_COMMAND_ID, | ||
() => { | ||
window.location.href = logoutEndpoint; | ||
}, | ||
); | ||
|
||
// Add logout to command palette. | ||
MenuRegistry.appendMenuItem(MenuId.CommandPalette, { | ||
command: { | ||
id: LOGOUT_COMMAND_ID, | ||
title: localize('logout', "Log out") | ||
}, | ||
when: ContextKeyExpr.has('code-server.authed') | ||
}); | ||
|
||
// Add logout to the (web-only) home menu. | ||
MenuRegistry.appendMenuItem(MenuId.MenubarHomeMenu, { | ||
command: { | ||
id: LOGOUT_COMMAND_ID, | ||
title: localize('logout', "Log out") | ||
}, | ||
when: ContextKeyExpr.has('code-server.authed') | ||
}); | ||
}; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
import { ITelemetryData } from 'vs/base/common/actions'; | ||
import { Event } from 'vs/base/common/event'; | ||
import { IChannel, IServerChannel } from 'vs/base/parts/ipc/common/ipc'; | ||
import { ClassifiedEvent, GDPRClassification, StrictPropertyCheck } from 'vs/platform/telemetry/common/gdprTypings'; | ||
import { ITelemetryInfo, ITelemetryService } from 'vs/platform/telemetry/common/telemetry'; | ||
|
||
export class TelemetryChannel implements IServerChannel { | ||
constructor(private service: ITelemetryService) {} | ||
|
||
listen(_: unknown, event: string): Event<any> { | ||
throw new Error(`Invalid listen ${event}`); | ||
} | ||
|
||
call(_: unknown, command: string, args?: any): Promise<any> { | ||
switch (command) { | ||
case 'publicLog': return this.service.publicLog(args[0], args[1], args[2]); | ||
case 'publicLog2': return this.service.publicLog2(args[0], args[1], args[2]); | ||
case 'publicLogError': return this.service.publicLogError(args[0], args[1]); | ||
case 'publicLogError2': return this.service.publicLogError2(args[0], args[1]); | ||
case 'setEnabled': return Promise.resolve(this.service.setEnabled(args[0])); | ||
case 'getTelemetryInfo': return this.service.getTelemetryInfo(); | ||
case 'setExperimentProperty': return Promise.resolve(this.service.setExperimentProperty(args[0], args[1])); | ||
} | ||
throw new Error(`Invalid call ${command}`); | ||
} | ||
} | ||
|
||
export class TelemetryChannelClient implements ITelemetryService { | ||
_serviceBrand: any; | ||
|
||
// These don't matter; telemetry is sent to the Node side which decides | ||
// whether to send the telemetry event. | ||
public isOptedIn = true; | ||
public sendErrorTelemetry = true; | ||
|
||
constructor(private readonly channel: IChannel) {} | ||
|
||
public publicLog(eventName: string, data?: ITelemetryData, anonymizeFilePaths?: boolean): Promise<void> { | ||
return this.channel.call('publicLog', [eventName, data, anonymizeFilePaths]); | ||
} | ||
|
||
public publicLog2<E extends ClassifiedEvent<T> = never, T extends GDPRClassification<T> = never>(eventName: string, data?: StrictPropertyCheck<T, E>, anonymizeFilePaths?: boolean): Promise<void> { | ||
return this.channel.call('publicLog2', [eventName, data, anonymizeFilePaths]); | ||
} | ||
|
||
public publicLogError(errorEventName: string, data?: ITelemetryData): Promise<void> { | ||
return this.channel.call('publicLogError', [errorEventName, data]); | ||
} | ||
|
||
public publicLogError2<E extends ClassifiedEvent<T> = never, T extends GDPRClassification<T> = never>(eventName: string, data?: StrictPropertyCheck<T, E>): Promise<void> { | ||
return this.channel.call('publicLogError2', [eventName, data]); | ||
} | ||
|
||
public setEnabled(value: boolean): void { | ||
this.channel.call('setEnable', [value]); | ||
} | ||
|
||
public getTelemetryInfo(): Promise<ITelemetryInfo> { | ||
return this.channel.call('getTelemetryInfo'); | ||
} | ||
|
||
public setExperimentProperty(name: string, value: string): void { | ||
this.channel.call('setExperimentProperty', [name, value]); | ||
} | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
../../../../../../src/common/util.ts |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,83 @@ | ||
import { field } from '@coder/logger'; | ||
import { setUnexpectedErrorHandler } from 'vs/base/common/errors'; | ||
import * as proxyAgent from 'vs/base/node/proxy_agent'; | ||
import { CodeServerMessage, VscodeMessage } from 'vs/ipc'; | ||
import { logger } from 'vs/server/node/logger'; | ||
import { enableCustomMarketplace } from 'vs/server/node/marketplace'; | ||
import { Vscode } from 'vs/server/node/server'; | ||
|
||
setUnexpectedErrorHandler((error) => { | ||
logger.warn('Uncaught error', field('error', error instanceof Error ? error.message : error)); | ||
}); | ||
enableCustomMarketplace(); | ||
proxyAgent.monkeyPatch(true); | ||
|
||
/** | ||
* Ensure we control when the process exits. | ||
*/ | ||
const exit = process.exit; | ||
process.exit = function(code?: number) { | ||
logger.warn(`process.exit() was prevented: ${code || 'unknown code'}.`); | ||
} as (code?: number) => never; | ||
|
||
// Kill VS Code if the parent process dies. | ||
if (typeof process.env.CODE_SERVER_PARENT_PID !== 'undefined') { | ||
const parentPid = parseInt(process.env.CODE_SERVER_PARENT_PID, 10); | ||
setInterval(() => { | ||
try { | ||
process.kill(parentPid, 0); // Throws an exception if the process doesn't exist anymore. | ||
} catch (e) { | ||
exit(); | ||
} | ||
}, 5000); | ||
} else { | ||
logger.error('no parent process'); | ||
exit(1); | ||
} | ||
|
||
const vscode = new Vscode(); | ||
const send = (message: VscodeMessage): void => { | ||
if (!process.send) { | ||
throw new Error('not spawned with IPC'); | ||
} | ||
process.send(message); | ||
}; | ||
|
||
// Wait for the init message then start up VS Code. Subsequent messages will | ||
// return new workbench options without starting a new instance. | ||
process.on('message', async (message: CodeServerMessage, socket) => { | ||
logger.debug('got message from code-server', field('type', message.type)); | ||
logger.trace('code-server message content', field('message', message)); | ||
switch (message.type) { | ||
case 'init': | ||
try { | ||
const options = await vscode.initialize(message.options); | ||
send({ type: 'options', id: message.id, options }); | ||
} catch (error) { | ||
logger.error(error.message); | ||
logger.error(error.stack); | ||
exit(1); | ||
} | ||
break; | ||
case 'cli': | ||
try { | ||
await vscode.cli(message.args); | ||
exit(0); | ||
} catch (error) { | ||
logger.error(error.message); | ||
logger.error(error.stack); | ||
exit(1); | ||
} | ||
break; | ||
case 'socket': | ||
vscode.handleWebSocket(socket, message.query, message.permessageDeflate); | ||
break; | ||
} | ||
}); | ||
if (!process.send) { | ||
logger.error('not spawned with IPC'); | ||
exit(1); | ||
} else { | ||
// This lets the parent know the child is ready to receive messages. | ||
send({ type: 'ready' }); | ||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
// This must be a JS file otherwise when it gets compiled it turns into AMD | ||
// syntax which will not work without the right loader. | ||
require('../../bootstrap-amd').load('vs/server/entry'); |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.