mirror of
https://github.com/microsoft/vscode.git
synced 2026-04-22 17:48:56 +01:00
Rearrange files to better separate between workbench/api and workbench/services (#141003)
This commit is contained in:
@@ -8,7 +8,7 @@ import { createApiFactoryAndRegisterActors } from 'vs/workbench/api/common/extHo
|
||||
import { RequireInterceptor } from 'vs/workbench/api/common/extHostRequireInterceptor';
|
||||
import { MainContext } from 'vs/workbench/api/common/extHost.protocol';
|
||||
import { ExtensionActivationTimesBuilder } from 'vs/workbench/api/common/extHostExtensionActivator';
|
||||
import { connectProxyResolver } from 'vs/workbench/services/extensions/node/proxyResolver';
|
||||
import { connectProxyResolver } from 'vs/workbench/api/node/proxyResolver';
|
||||
import { AbstractExtHostExtensionService } from 'vs/workbench/api/common/extHostExtensionService';
|
||||
import { ExtHostDownloadService } from 'vs/workbench/api/node/extHostDownloadService';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
|
||||
@@ -3,6 +3,6 @@
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import { startExtensionHostProcess } from 'vs/workbench/services/extensions/node/extensionHostProcessSetup';
|
||||
import { startExtensionHostProcess } from 'vs/workbench/api/node/extensionHostProcessSetup';
|
||||
|
||||
startExtensionHostProcess().catch((err) => console.log(err));
|
||||
|
||||
372
src/vs/workbench/api/node/extensionHostProcessSetup.ts
Normal file
372
src/vs/workbench/api/node/extensionHostProcessSetup.ts
Normal file
@@ -0,0 +1,372 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as nativeWatchdog from 'native-watchdog';
|
||||
import * as net from 'net';
|
||||
import * as minimist from 'minimist';
|
||||
import * as performance from 'vs/base/common/performance';
|
||||
import { isCancellationError, onUnexpectedError } from 'vs/base/common/errors';
|
||||
import { Event } from 'vs/base/common/event';
|
||||
import { IMessagePassingProtocol } from 'vs/base/parts/ipc/common/ipc';
|
||||
import { PersistentProtocol, ProtocolConstants, BufferedEmitter } from 'vs/base/parts/ipc/common/ipc.net';
|
||||
import { NodeSocket, WebSocketNodeSocket } from 'vs/base/parts/ipc/node/ipc.net';
|
||||
import product from 'vs/platform/product/common/product';
|
||||
import { IInitData } from 'vs/workbench/api/common/extHost.protocol';
|
||||
import { MessageType, createMessageOfType, isMessageOfType, IExtHostSocketMessage, IExtHostReadyMessage, IExtHostReduceGraceTimeMessage, ExtensionHostExitCode } from 'vs/workbench/services/extensions/common/extensionHostProtocol';
|
||||
import { ExtensionHostMain, IExitFn } from 'vs/workbench/api/common/extensionHostMain';
|
||||
import { VSBuffer } from 'vs/base/common/buffer';
|
||||
import { IURITransformer, URITransformer, IRawURITransformer } from 'vs/base/common/uriIpc';
|
||||
import { Promises } from 'vs/base/node/pfs';
|
||||
import { realpath } from 'vs/base/node/extpath';
|
||||
import { IHostUtils } from 'vs/workbench/api/common/extHostExtensionService';
|
||||
import { ProcessTimeRunOnceScheduler } from 'vs/base/common/async';
|
||||
import { boolean } from 'vs/editor/common/config/editorOptions';
|
||||
|
||||
import 'vs/workbench/api/common/extHost.common.services';
|
||||
import 'vs/workbench/api/node/extHost.node.services';
|
||||
|
||||
interface ParsedExtHostArgs {
|
||||
uriTransformerPath?: string;
|
||||
skipWorkspaceStorageLock?: boolean;
|
||||
useHostProxy?: boolean;
|
||||
}
|
||||
|
||||
// workaround for https://github.com/microsoft/vscode/issues/85490
|
||||
// remove --inspect-port=0 after start so that it doesn't trigger LSP debugging
|
||||
(function removeInspectPort() {
|
||||
for (let i = 0; i < process.execArgv.length; i++) {
|
||||
if (process.execArgv[i] === '--inspect-port=0') {
|
||||
process.execArgv.splice(i, 1);
|
||||
i--;
|
||||
}
|
||||
}
|
||||
})();
|
||||
|
||||
const args = minimist(process.argv.slice(2), {
|
||||
string: [
|
||||
'uriTransformerPath'
|
||||
],
|
||||
boolean: [
|
||||
'skipWorkspaceStorageLock',
|
||||
'useHostProxy'
|
||||
]
|
||||
}) as ParsedExtHostArgs;
|
||||
|
||||
// With Electron 2.x and node.js 8.x the "natives" module
|
||||
// can cause a native crash (see https://github.com/nodejs/node/issues/19891 and
|
||||
// https://github.com/electron/electron/issues/10905). To prevent this from
|
||||
// happening we essentially blocklist this module from getting loaded in any
|
||||
// extension by patching the node require() function.
|
||||
(function () {
|
||||
const Module = require.__$__nodeRequire('module') as any;
|
||||
const originalLoad = Module._load;
|
||||
|
||||
Module._load = function (request: string) {
|
||||
if (request === 'natives') {
|
||||
throw new Error('Either the extension or an NPM dependency is using the [unsupported "natives" node module](https://go.microsoft.com/fwlink/?linkid=871887).');
|
||||
}
|
||||
|
||||
return originalLoad.apply(this, arguments);
|
||||
};
|
||||
})();
|
||||
|
||||
// custom process.exit logic...
|
||||
const nativeExit: IExitFn = process.exit.bind(process);
|
||||
function patchProcess(allowExit: boolean) {
|
||||
process.exit = function (code?: number) {
|
||||
if (allowExit) {
|
||||
nativeExit(code);
|
||||
} else {
|
||||
const err = new Error('An extension called process.exit() and this was prevented.');
|
||||
console.warn(err.stack);
|
||||
}
|
||||
} as (code?: number) => never;
|
||||
|
||||
// override Electron's process.crash() method
|
||||
process.crash = function () {
|
||||
const err = new Error('An extension called process.crash() and this was prevented.');
|
||||
console.warn(err.stack);
|
||||
};
|
||||
}
|
||||
|
||||
interface IRendererConnection {
|
||||
protocol: IMessagePassingProtocol;
|
||||
initData: IInitData;
|
||||
}
|
||||
|
||||
// This calls exit directly in case the initialization is not finished and we need to exit
|
||||
// Otherwise, if initialization completed we go to extensionHostMain.terminate()
|
||||
let onTerminate = function (reason: string) {
|
||||
nativeExit();
|
||||
};
|
||||
|
||||
function _createExtHostProtocol(): Promise<PersistentProtocol> {
|
||||
if (process.env.VSCODE_EXTHOST_WILL_SEND_SOCKET) {
|
||||
|
||||
return new Promise<PersistentProtocol>((resolve, reject) => {
|
||||
|
||||
let protocol: PersistentProtocol | null = null;
|
||||
|
||||
let timer = setTimeout(() => {
|
||||
onTerminate('VSCODE_EXTHOST_IPC_SOCKET timeout');
|
||||
}, 60000);
|
||||
|
||||
const reconnectionGraceTime = ProtocolConstants.ReconnectionGraceTime;
|
||||
const reconnectionShortGraceTime = ProtocolConstants.ReconnectionShortGraceTime;
|
||||
const disconnectRunner1 = new ProcessTimeRunOnceScheduler(() => onTerminate('renderer disconnected for too long (1)'), reconnectionGraceTime);
|
||||
const disconnectRunner2 = new ProcessTimeRunOnceScheduler(() => onTerminate('renderer disconnected for too long (2)'), reconnectionShortGraceTime);
|
||||
|
||||
process.on('message', (msg: IExtHostSocketMessage | IExtHostReduceGraceTimeMessage, handle: net.Socket) => {
|
||||
if (msg && msg.type === 'VSCODE_EXTHOST_IPC_SOCKET') {
|
||||
// Disable Nagle's algorithm. We also do this on the server process,
|
||||
// but nodejs doesn't document if this option is transferred with the socket
|
||||
handle.setNoDelay(true);
|
||||
|
||||
const initialDataChunk = VSBuffer.wrap(Buffer.from(msg.initialDataChunk, 'base64'));
|
||||
let socket: NodeSocket | WebSocketNodeSocket;
|
||||
if (msg.skipWebSocketFrames) {
|
||||
socket = new NodeSocket(handle, 'extHost-socket');
|
||||
} else {
|
||||
const inflateBytes = VSBuffer.wrap(Buffer.from(msg.inflateBytes, 'base64'));
|
||||
socket = new WebSocketNodeSocket(new NodeSocket(handle, 'extHost-socket'), msg.permessageDeflate, inflateBytes, false);
|
||||
}
|
||||
if (protocol) {
|
||||
// reconnection case
|
||||
disconnectRunner1.cancel();
|
||||
disconnectRunner2.cancel();
|
||||
protocol.beginAcceptReconnection(socket, initialDataChunk);
|
||||
protocol.endAcceptReconnection();
|
||||
protocol.sendResume();
|
||||
} else {
|
||||
clearTimeout(timer);
|
||||
protocol = new PersistentProtocol(socket, initialDataChunk);
|
||||
protocol.sendResume();
|
||||
protocol.onDidDispose(() => onTerminate('renderer disconnected'));
|
||||
resolve(protocol);
|
||||
|
||||
// Wait for rich client to reconnect
|
||||
protocol.onSocketClose(() => {
|
||||
// The socket has closed, let's give the renderer a certain amount of time to reconnect
|
||||
disconnectRunner1.schedule();
|
||||
});
|
||||
}
|
||||
}
|
||||
if (msg && msg.type === 'VSCODE_EXTHOST_IPC_REDUCE_GRACE_TIME') {
|
||||
if (disconnectRunner2.isScheduled()) {
|
||||
// we are disconnected and already running the short reconnection timer
|
||||
return;
|
||||
}
|
||||
if (disconnectRunner1.isScheduled()) {
|
||||
// we are disconnected and running the long reconnection timer
|
||||
disconnectRunner2.schedule();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Now that we have managed to install a message listener, ask the other side to send us the socket
|
||||
const req: IExtHostReadyMessage = { type: 'VSCODE_EXTHOST_IPC_READY' };
|
||||
if (process.send) {
|
||||
process.send(req);
|
||||
}
|
||||
});
|
||||
|
||||
} else {
|
||||
|
||||
const pipeName = process.env.VSCODE_IPC_HOOK_EXTHOST!;
|
||||
|
||||
return new Promise<PersistentProtocol>((resolve, reject) => {
|
||||
|
||||
const socket = net.createConnection(pipeName, () => {
|
||||
socket.removeListener('error', reject);
|
||||
resolve(new PersistentProtocol(new NodeSocket(socket, 'extHost-renderer')));
|
||||
});
|
||||
socket.once('error', reject);
|
||||
|
||||
socket.on('close', () => {
|
||||
onTerminate('renderer closed the socket');
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
async function createExtHostProtocol(): Promise<IMessagePassingProtocol> {
|
||||
|
||||
const protocol = await _createExtHostProtocol();
|
||||
|
||||
return new class implements IMessagePassingProtocol {
|
||||
|
||||
private readonly _onMessage = new BufferedEmitter<VSBuffer>();
|
||||
readonly onMessage: Event<VSBuffer> = this._onMessage.event;
|
||||
|
||||
private _terminating: boolean;
|
||||
|
||||
constructor() {
|
||||
this._terminating = false;
|
||||
protocol.onMessage((msg) => {
|
||||
if (isMessageOfType(msg, MessageType.Terminate)) {
|
||||
this._terminating = true;
|
||||
onTerminate('received terminate message from renderer');
|
||||
} else {
|
||||
this._onMessage.fire(msg);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
send(msg: any): void {
|
||||
if (!this._terminating) {
|
||||
protocol.send(msg);
|
||||
}
|
||||
}
|
||||
|
||||
drain(): Promise<void> {
|
||||
return protocol.drain();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function connectToRenderer(protocol: IMessagePassingProtocol): Promise<IRendererConnection> {
|
||||
return new Promise<IRendererConnection>((c) => {
|
||||
|
||||
// Listen init data message
|
||||
const first = protocol.onMessage(raw => {
|
||||
first.dispose();
|
||||
|
||||
const initData = <IInitData>JSON.parse(raw.toString());
|
||||
|
||||
const rendererCommit = initData.commit;
|
||||
const myCommit = product.commit;
|
||||
|
||||
if (rendererCommit && myCommit) {
|
||||
// Running in the built version where commits are defined
|
||||
if (rendererCommit !== myCommit) {
|
||||
nativeExit(ExtensionHostExitCode.VersionMismatch);
|
||||
}
|
||||
}
|
||||
|
||||
// Kill oneself if one's parent dies. Much drama.
|
||||
let epermErrors = 0;
|
||||
setInterval(function () {
|
||||
try {
|
||||
process.kill(initData.parentPid, 0); // throws an exception if the main process doesn't exist anymore.
|
||||
epermErrors = 0;
|
||||
} catch (e) {
|
||||
if (e && e.code === 'EPERM') {
|
||||
// Even if the parent process is still alive,
|
||||
// some antivirus software can lead to an EPERM error to be thrown here.
|
||||
// Let's terminate only if we get 3 consecutive EPERM errors.
|
||||
epermErrors++;
|
||||
if (epermErrors >= 3) {
|
||||
onTerminate(`parent process ${initData.parentPid} does not exist anymore (3 x EPERM): ${e.message} (code: ${e.code}) (errno: ${e.errno})`);
|
||||
}
|
||||
} else {
|
||||
onTerminate(`parent process ${initData.parentPid} does not exist anymore: ${e.message} (code: ${e.code}) (errno: ${e.errno})`);
|
||||
}
|
||||
}
|
||||
}, 1000);
|
||||
|
||||
// In certain cases, the event loop can become busy and never yield
|
||||
// e.g. while-true or process.nextTick endless loops
|
||||
// So also use the native node module to do it from a separate thread
|
||||
let watchdog: typeof nativeWatchdog;
|
||||
try {
|
||||
watchdog = require.__$__nodeRequire('native-watchdog');
|
||||
watchdog.start(initData.parentPid);
|
||||
} catch (err) {
|
||||
// no problem...
|
||||
onUnexpectedError(err);
|
||||
}
|
||||
|
||||
// Tell the outside that we are initialized
|
||||
protocol.send(createMessageOfType(MessageType.Initialized));
|
||||
|
||||
c({ protocol, initData });
|
||||
});
|
||||
|
||||
// Tell the outside that we are ready to receive messages
|
||||
protocol.send(createMessageOfType(MessageType.Ready));
|
||||
});
|
||||
}
|
||||
|
||||
export async function startExtensionHostProcess(): Promise<void> {
|
||||
|
||||
// Print a console message when rejection isn't handled within N seconds. For details:
|
||||
// see https://nodejs.org/api/process.html#process_event_unhandledrejection
|
||||
// and https://nodejs.org/api/process.html#process_event_rejectionhandled
|
||||
const unhandledPromises: Promise<any>[] = [];
|
||||
process.on('unhandledRejection', (reason: any, promise: Promise<any>) => {
|
||||
unhandledPromises.push(promise);
|
||||
setTimeout(() => {
|
||||
const idx = unhandledPromises.indexOf(promise);
|
||||
if (idx >= 0) {
|
||||
promise.catch(e => {
|
||||
unhandledPromises.splice(idx, 1);
|
||||
if (!isCancellationError(e)) {
|
||||
console.warn(`rejected promise not handled within 1 second: ${e}`);
|
||||
if (e && e.stack) {
|
||||
console.warn(`stack trace: ${e.stack}`);
|
||||
}
|
||||
if (reason) {
|
||||
onUnexpectedError(reason);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}, 1000);
|
||||
});
|
||||
|
||||
process.on('rejectionHandled', (promise: Promise<any>) => {
|
||||
const idx = unhandledPromises.indexOf(promise);
|
||||
if (idx >= 0) {
|
||||
unhandledPromises.splice(idx, 1);
|
||||
}
|
||||
});
|
||||
|
||||
// Print a console message when an exception isn't handled.
|
||||
process.on('uncaughtException', function (err: Error) {
|
||||
onUnexpectedError(err);
|
||||
});
|
||||
|
||||
performance.mark(`code/extHost/willConnectToRenderer`);
|
||||
const protocol = await createExtHostProtocol();
|
||||
performance.mark(`code/extHost/didConnectToRenderer`);
|
||||
const renderer = await connectToRenderer(protocol);
|
||||
performance.mark(`code/extHost/didWaitForInitData`);
|
||||
const { initData } = renderer;
|
||||
// setup things
|
||||
patchProcess(!!initData.environment.extensionTestsLocationURI); // to support other test frameworks like Jasmin that use process.exit (https://github.com/microsoft/vscode/issues/37708)
|
||||
initData.environment.useHostProxy = !!args.useHostProxy;
|
||||
initData.environment.skipWorkspaceStorageLock = boolean(args.skipWorkspaceStorageLock, false);
|
||||
|
||||
// host abstraction
|
||||
const hostUtils = new class NodeHost implements IHostUtils {
|
||||
declare readonly _serviceBrand: undefined;
|
||||
public readonly pid = process.pid;
|
||||
exit(code: number) { nativeExit(code); }
|
||||
exists(path: string) { return Promises.exists(path); }
|
||||
realpath(path: string) { return realpath(path); }
|
||||
};
|
||||
|
||||
// Attempt to load uri transformer
|
||||
let uriTransformer: IURITransformer | null = null;
|
||||
if (initData.remote.authority && args.uriTransformerPath) {
|
||||
try {
|
||||
const rawURITransformerFactory = <any>require.__$__nodeRequire(args.uriTransformerPath);
|
||||
const rawURITransformer = <IRawURITransformer>rawURITransformerFactory(initData.remote.authority);
|
||||
uriTransformer = new URITransformer(rawURITransformer);
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
}
|
||||
}
|
||||
|
||||
const extensionHostMain = new ExtensionHostMain(
|
||||
renderer.protocol,
|
||||
initData,
|
||||
hostUtils,
|
||||
uriTransformer
|
||||
);
|
||||
|
||||
// rewrite onTerminate-function to be a proper shutdown
|
||||
onTerminate = (reason: string) => extensionHostMain.terminate(reason);
|
||||
}
|
||||
137
src/vs/workbench/api/node/proxyResolver.ts
Normal file
137
src/vs/workbench/api/node/proxyResolver.ts
Normal file
@@ -0,0 +1,137 @@
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
import * as http from 'http';
|
||||
import * as https from 'https';
|
||||
import * as tls from 'tls';
|
||||
|
||||
import { IExtHostWorkspaceProvider } from 'vs/workbench/api/common/extHostWorkspace';
|
||||
import { ExtHostConfigProvider } from 'vs/workbench/api/common/extHostConfiguration';
|
||||
import { MainThreadTelemetryShape, IInitData } from 'vs/workbench/api/common/extHost.protocol';
|
||||
import { ExtHostExtensionService } from 'vs/workbench/api/node/extHostExtensionService';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { ILogService } from 'vs/platform/log/common/log';
|
||||
import { IExtensionDescription } from 'vs/platform/extensions/common/extensions';
|
||||
import { LogLevel, createHttpPatch, ProxyResolveEvent, createProxyResolver, createTlsPatch, ProxySupportSetting } from 'vscode-proxy-agent';
|
||||
|
||||
export function connectProxyResolver(
|
||||
extHostWorkspace: IExtHostWorkspaceProvider,
|
||||
configProvider: ExtHostConfigProvider,
|
||||
extensionService: ExtHostExtensionService,
|
||||
extHostLogService: ILogService,
|
||||
mainThreadTelemetry: MainThreadTelemetryShape,
|
||||
initData: IInitData,
|
||||
) {
|
||||
const useHostProxy = initData.environment.useHostProxy;
|
||||
const doUseHostProxy = typeof useHostProxy === 'boolean' ? useHostProxy : !initData.remote.isRemote;
|
||||
const resolveProxy = createProxyResolver({
|
||||
resolveProxy: url => extHostWorkspace.resolveProxy(url),
|
||||
getHttpProxySetting: () => configProvider.getConfiguration('http').get('proxy'),
|
||||
log: (level, message, ...args) => {
|
||||
switch (level) {
|
||||
case LogLevel.Trace: extHostLogService.trace(message, ...args); break;
|
||||
case LogLevel.Debug: extHostLogService.debug(message, ...args); break;
|
||||
case LogLevel.Info: extHostLogService.info(message, ...args); break;
|
||||
case LogLevel.Warning: extHostLogService.warn(message, ...args); break;
|
||||
case LogLevel.Error: extHostLogService.error(message, ...args); break;
|
||||
case LogLevel.Critical: extHostLogService.critical(message, ...args); break;
|
||||
case LogLevel.Off: break;
|
||||
default: never(level, message, args); break;
|
||||
}
|
||||
function never(level: never, message: string, ...args: any[]) {
|
||||
extHostLogService.error('Unknown log level', level);
|
||||
extHostLogService.error(message, ...args);
|
||||
}
|
||||
},
|
||||
getLogLevel: () => extHostLogService.getLevel(),
|
||||
proxyResolveTelemetry: event => {
|
||||
type ResolveProxyClassification = {
|
||||
count: { classification: 'SystemMetaData', purpose: 'PerformanceAndHealth', isMeasurement: true };
|
||||
duration: { classification: 'SystemMetaData', purpose: 'PerformanceAndHealth', isMeasurement: true };
|
||||
errorCount: { classification: 'SystemMetaData', purpose: 'PerformanceAndHealth', isMeasurement: true };
|
||||
cacheCount: { classification: 'SystemMetaData', purpose: 'PerformanceAndHealth', isMeasurement: true };
|
||||
cacheSize: { classification: 'SystemMetaData', purpose: 'PerformanceAndHealth', isMeasurement: true };
|
||||
cacheRolls: { classification: 'SystemMetaData', purpose: 'PerformanceAndHealth', isMeasurement: true };
|
||||
envCount: { classification: 'SystemMetaData', purpose: 'PerformanceAndHealth', isMeasurement: true };
|
||||
settingsCount: { classification: 'SystemMetaData', purpose: 'PerformanceAndHealth', isMeasurement: true };
|
||||
localhostCount: { classification: 'SystemMetaData', purpose: 'PerformanceAndHealth', isMeasurement: true };
|
||||
envNoProxyCount: { classification: 'SystemMetaData', purpose: 'PerformanceAndHealth', isMeasurement: true };
|
||||
results: { classification: 'SystemMetaData', purpose: 'PerformanceAndHealth' };
|
||||
};
|
||||
mainThreadTelemetry.$publicLog2<ProxyResolveEvent, ResolveProxyClassification>('resolveProxy', event);
|
||||
},
|
||||
useHostProxy: doUseHostProxy,
|
||||
env: process.env,
|
||||
});
|
||||
const lookup = createPatchedModules(configProvider, resolveProxy);
|
||||
return configureModuleLoading(extensionService, lookup);
|
||||
}
|
||||
|
||||
function createPatchedModules(configProvider: ExtHostConfigProvider, resolveProxy: ReturnType<typeof createProxyResolver>) {
|
||||
const proxySetting = {
|
||||
config: configProvider.getConfiguration('http')
|
||||
.get<ProxySupportSetting>('proxySupport') || 'off'
|
||||
};
|
||||
configProvider.onDidChangeConfiguration(e => {
|
||||
proxySetting.config = configProvider.getConfiguration('http')
|
||||
.get<ProxySupportSetting>('proxySupport') || 'off';
|
||||
});
|
||||
const certSetting = {
|
||||
config: !!configProvider.getConfiguration('http')
|
||||
.get<boolean>('systemCertificates')
|
||||
};
|
||||
configProvider.onDidChangeConfiguration(e => {
|
||||
certSetting.config = !!configProvider.getConfiguration('http')
|
||||
.get<boolean>('systemCertificates');
|
||||
});
|
||||
|
||||
return {
|
||||
http: {
|
||||
off: Object.assign({}, http, createHttpPatch(http, resolveProxy, { config: 'off' }, certSetting, true)),
|
||||
on: Object.assign({}, http, createHttpPatch(http, resolveProxy, { config: 'on' }, certSetting, true)),
|
||||
override: Object.assign({}, http, createHttpPatch(http, resolveProxy, { config: 'override' }, certSetting, true)),
|
||||
onRequest: Object.assign({}, http, createHttpPatch(http, resolveProxy, proxySetting, certSetting, true)),
|
||||
default: Object.assign(http, createHttpPatch(http, resolveProxy, proxySetting, certSetting, false)) // run last
|
||||
} as Record<string, typeof http>,
|
||||
https: {
|
||||
off: Object.assign({}, https, createHttpPatch(https, resolveProxy, { config: 'off' }, certSetting, true)),
|
||||
on: Object.assign({}, https, createHttpPatch(https, resolveProxy, { config: 'on' }, certSetting, true)),
|
||||
override: Object.assign({}, https, createHttpPatch(https, resolveProxy, { config: 'override' }, certSetting, true)),
|
||||
onRequest: Object.assign({}, https, createHttpPatch(https, resolveProxy, proxySetting, certSetting, true)),
|
||||
default: Object.assign(https, createHttpPatch(https, resolveProxy, proxySetting, certSetting, false)) // run last
|
||||
} as Record<string, typeof https>,
|
||||
tls: Object.assign(tls, createTlsPatch(tls))
|
||||
};
|
||||
}
|
||||
|
||||
const modulesCache = new Map<IExtensionDescription | undefined, { http?: typeof http, https?: typeof https }>();
|
||||
function configureModuleLoading(extensionService: ExtHostExtensionService, lookup: ReturnType<typeof createPatchedModules>): Promise<void> {
|
||||
return extensionService.getExtensionPathIndex()
|
||||
.then(extensionPaths => {
|
||||
const node_module = <any>require.__$__nodeRequire('module');
|
||||
const original = node_module._load;
|
||||
node_module._load = function load(request: string, parent: { filename: string; }, isMain: boolean) {
|
||||
if (request === 'tls') {
|
||||
return lookup.tls;
|
||||
}
|
||||
|
||||
if (request !== 'http' && request !== 'https') {
|
||||
return original.apply(this, arguments);
|
||||
}
|
||||
|
||||
const modules = lookup[request];
|
||||
const ext = extensionPaths.findSubstr(URI.file(parent.filename));
|
||||
let cache = modulesCache.get(ext);
|
||||
if (!cache) {
|
||||
modulesCache.set(ext, cache = {});
|
||||
}
|
||||
if (!cache[request]) {
|
||||
let mod = modules.default;
|
||||
cache[request] = <any>{ ...mod }; // Copy to work around #93167.
|
||||
}
|
||||
return cache[request];
|
||||
};
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user