Skip to content
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

feat(vscode): update to version 1.57.0 #3544

Merged
merged 51 commits into from
Jul 13, 2021
Merged
Show file tree
Hide file tree
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
Jun 4, 2021
92e6bb1
chore(vscode): update to 1.57.0
Jun 4, 2021
d7cc072
chore(deps): fixup lockfiles
Jun 8, 2021
8c72047
chore: restore .gitignore
Jun 8, 2021
ea4705b
fix(vscode): redo extra extension paths
Jun 8, 2021
943504b
fix(vscode): add setSocket to PersistentProtocol
Jun 8, 2021
8c05721
fix(vscode): restore server files
Jun 8, 2021
ddf2616
fix(vscode): restore typings
Jun 10, 2021
a02b0ad
fix(vscode): restore proxy_agent.ts symlink
Jun 10, 2021
9f524bd
fix(vscode): use ptyHost.getEnv
Jun 10, 2021
b88ce55
fix(vscode): uriTransformer refactoring
Jun 10, 2021
c9a28aa
fix(vscode): add new terminal listener
Jun 10, 2021
f993944
fix(vscode): fix + enable layering lint
Jun 10, 2021
8c3c30a
chore: format file
Jun 10, 2021
41a72f1
Squashed 'lib/vscode/' changes from 2064d4c301c..b4c1bd0a9b0
Jun 10, 2021
0c818a6
Merge commit '41a72f14e8a1f0f7a9d9c7fbf4c24d89f087c733' into vscode-1.57
Jun 10, 2021
a4f9ff0
fix(lib/vscode): restore product.json
Jun 10, 2021
a07260f
fix(vscode): backport resources hotfix
Jun 10, 2021
e41351e
Merge branch 'main' into vscode-1.57
Jun 10, 2021
1aaea7e
refactor(lib/vscode): reorganize code to fit vs rules
Jun 14, 2021
42794e3
fix(ci): remove stray symlinks
Jun 14, 2021
280d609
cleanup(lib/vscode): format .gitignore
Jun 14, 2021
b5af44e
chore(vscode): fix formatting
Jun 14, 2021
5429bc1
refactor(vscode): remove parsePathArg in envService
Jun 14, 2021
62801c8
fix(vscode): add missing terminal commands
Jun 14, 2021
180fbfc
fix(vscode): update .eslintignore paths
Jun 14, 2021
ef29d56
chore: document uriTransformer hacks
Jun 14, 2021
863cf60
fix(lib/vscode): restore patches
Jun 15, 2021
3558f5d
fix(lib/vscode): restore more patches
Jun 21, 2021
5fd98a5
Squashed 'lib/vscode/' changes from b4c1bd0a9b0..507ce72a446
Jun 21, 2021
6a62fe8
Merge commit '5fd98a52efbbbd7ca28922fdc9c7282d9bf1ec3d' into vscode-1.57
Jun 21, 2021
60673bd
fmt(docs): remove trailing whitespace
Jun 21, 2021
4271b60
fix(test): fix e2e tests
Jun 22, 2021
49e9fdd
chore(deps): update vulnerable vscode deps
Jun 22, 2021
55dc16b
fix(test): clean up terminal test
Jun 22, 2021
b5f408f
Merge branch 'main' into vscode-1.57
Jun 29, 2021
4b418f5
Retry menu navigation in e2e tests
code-asher Jun 29, 2021
7c9b1f0
Update VS Code loader with trusted types policy
code-asher Jul 1, 2021
6987dd3
Update build resources with renamed file
code-asher Jul 1, 2021
47d8866
Restore proposed API patch
code-asher Jun 22, 2021
9e46573
Restore async storage write patch
code-asher Jun 22, 2021
d8a1f7d
Remove duplicate telemetry service registration
code-asher Jun 22, 2021
a445588
Use service in terminal channel instead of interface
code-asher Jun 22, 2021
23594b2
Rename uri transformer using camel case
code-asher Jun 22, 2021
3c95888
Update yarn.lock
code-asher Jun 21, 2021
b0e9eff
Restore .yarnrc patch
code-asher Jun 21, 2021
7e3bb46
Remove gulp-tar dependency
code-asher Jul 1, 2021
5e8fe4e
Cancel current menu navigation on retry
code-asher Jul 2, 2021
476fcf3
chore(docs): update docs with patches
Jul 10, 2021
ed9c59d
Merge branch 'main' into vscode-1.57
Jul 13, 2021
df85813
chore(ci): increase timeout to 15 minutes
Jul 13, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions lib/vscode/src/vs/ipc.d.ts
198 changes: 198 additions & 0 deletions lib/vscode/src/vs/server/browser/client.ts
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')
});
oxy marked this conversation as resolved.
Show resolved Hide resolved
};
65 changes: 65 additions & 0 deletions lib/vscode/src/vs/server/common/telemetry.ts
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]);
}
}
1 change: 1 addition & 0 deletions lib/vscode/src/vs/server/common/util.ts
83 changes: 83 additions & 0 deletions lib/vscode/src/vs/server/entry.ts
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' });
}
3 changes: 3 additions & 0 deletions lib/vscode/src/vs/server/fork.js
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');
Loading