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

239 LOC · 150 covered · 89 uncovered · 19 ranges · 7 concepts · 5 introducers · 7 tests

File neighbourhood

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

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

In the embedded map, ordinary wheel input scrolls the page; use the visible controls to zoom and drag to pan. Open the full-screen map for canvas navigation: wheel pans, Ctrl/Command plus wheel zooms, and arrow keys pan when this region is focused. On touch screens, open the full-screen map to pan or pinch. If JavaScript or WebGL is unavailable, use the related-file, concept, and source links on this page.

Focused file, its introducer and connector concepts, their introduced files, and tests that run code from the filesrc/vs/base/common/errors.ts · 357 LOCcommon/errors.tssrc/vs/workbench/api/common/extHostApiDeprecationService.ts · 77 LOCcommon/extHostApiDepreca…src/vs/workbench/api/common/extHostExtensionService.ts · 1285 LOCcommon/extHostExtensionS…extensionHostMain.ts ×1 · 2 introduced LOCextensionHostMain.ts ×1reset prepareStackTrace-callback|occurrence=1, extensionHostMain.test|title=ExtensionHostMain#ErrorHandler - Wrapping prepareStackTrace can cause slowdown and eventual stack overflow #184926 prevent rewrapping|occurrence=1 · 0 introduced LOCreset prepareStackTrace-…extensionHostMain.ts ×5 · 26 introduced LOCextensionHostMain.ts ×5f0f2e182082072efdaf0f8e1537d2cce Restored, too many uses before restoration|occurrence=1 · 0 introduced LOCf0f2e182082072efdaf0f8e1…extensionHostMain.ts ×1 · 3 introduced LOCextensionHostMain.ts ×1extensionHostMain.ts ×1 · 3 introduced LOCextensionHostMain.ts ×1extensionHostMain.ts ×11 · 164 introduced LOCextensionHostMain.ts ×11extensionHostMain.test|title=ExtensionHostMain#ErrorHandler - Wrapping prepareStackTrace can cause slowdown and eventual stack overflow #184926 basics|occurrence=1 · introduced test · mocha:v1|namespace=vscode@05c208e9e28d8c1c723fa08f85e2b7a96092e8e5|file=vs/workbench/api/test/common/extensionHostMain.test|title=ExtensionHostMain#ErrorHandler - Wrapping prepareStackTrace can cause slowdown and eventual stack overflow #184926 basics|occurrence=1extensionHostMain.test|t…f0f2e182082072efdaf0f8e1537d2cce Never restored, separate operations|occurrence=1 · introduced test · mocha:v1|namespace=vscode@05c208e9e28d8c1c723fa08f85e2b7a96092e8e5|file=vs/workbench/api/test/common/extensionHostMain.test|title=ExtensionHostMain#ErrorHandler - Wrapping prepareStackTrace can cause slowdown and eventual stack overflow #184926 https://gist.github.com/thecrypticace/f0f2e182082072efdaf0f8e1537d2cce Never restored, separate operations|occurrence=1f0f2e182082072efdaf0f8e1…f0f2e182082072efdaf0f8e1537d2cce Restored, separate operations|occurrence=1 · introduced test · mocha:v1|namespace=vscode@05c208e9e28d8c1c723fa08f85e2b7a96092e8e5|file=vs/workbench/api/test/common/extensionHostMain.test|title=ExtensionHostMain#ErrorHandler - Wrapping prepareStackTrace can cause slowdown and eventual stack overflow #184926 https://gist.github.com/thecrypticace/f0f2e182082072efdaf0f8e1537d2cce Restored, separate operations|occurrence=1f0f2e182082072efdaf0f8e1…f0f2e182082072efdaf0f8e1537d2cce Restored, too many uses before restoration|occurrence=1 · introduced test · mocha:v1|namespace=vscode@05c208e9e28d8c1c723fa08f85e2b7a96092e8e5|file=vs/workbench/api/test/common/extensionHostMain.test|title=ExtensionHostMain#ErrorHandler - Wrapping prepareStackTrace can cause slowdown and eventual stack overflow #184926 https://gist.github.com/thecrypticace/f0f2e182082072efdaf0f8e1537d2cce Restored, too many uses before restoration|occurrence=1f0f2e182082072efdaf0f8e1…extensionHostMain.test|title=ExtensionHostMain#ErrorHandler - Wrapping prepareStackTrace can cause slowdown and eventual stack overflow #184926 prevent rewrapping|occurrence=1 · introduced test · mocha:v1|namespace=vscode@05c208e9e28d8c1c723fa08f85e2b7a96092e8e5|file=vs/workbench/api/test/common/extensionHostMain.test|title=ExtensionHostMain#ErrorHandler - Wrapping prepareStackTrace can cause slowdown and eventual stack overflow #184926 prevent rewrapping|occurrence=1extensionHostMain.test|t…reset prepareStackTrace-callback|occurrence=1 · introduced test · mocha:v1|namespace=vscode@05c208e9e28d8c1c723fa08f85e2b7a96092e8e5|file=vs/workbench/api/test/common/extensionHostMain.test|title=ExtensionHostMain#ErrorHandler - Wrapping prepareStackTrace can cause slowdown and eventual stack overflow #184926 set/reset prepareStackTrace-callback|occurrence=1reset prepareStackTrace-…extensionHostMain.test|title=ExtensionHostMain#ErrorHandler - Wrapping prepareStackTrace can cause slowdown and eventual stack overflow #184926 wrap prepareStackTrace-callback|occurrence=1 · introduced test · mocha:v1|namespace=vscode@05c208e9e28d8c1c723fa08f85e2b7a96092e8e5|file=vs/workbench/api/test/common/extensionHostMain.test|title=ExtensionHostMain#ErrorHandler - Wrapping prepareStackTrace can cause slowdown and eventual stack overflow #184926 wrap prepareStackTrace-callback|occurrence=1extensionHostMain.test|t…Focused file · src/vs/workbench/api/common/extensionHostMain.ts · 239 LOCcommon/extensionHostMain…

Graph controls are ready.

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

1 > /*--------------------------------------------------------------------------------------------- extensionHostMain.ts ×11
2 > * Copyright (c) Microsoft Corporation. All rights reserved.
3 > * Licensed under the MIT License. See License.txt in the project root for license information.
4 > *--------------------------------------------------------------------------------------------*/
5 >
6 > import * as errors from '../../../base/common/errors.js';
7 > import * as performance from '../../../base/common/performance.js';
8 > import { URI } from '../../../base/common/uri.js';
9 > import { IURITransformer } from '../../../base/common/uriIpc.js';
10 > import { IMessagePassingProtocol } from '../../../base/parts/ipc/common/ipc.js';
11 > import { MainContext, MainThreadConsoleShape } from './extHost.protocol.js';
12 > import { IExtensionHostInitData } from '../../services/extensions/common/extensionHostProtocol.js';
13 > import { RPCProtocol } from '../../services/extensions/common/rpcProtocol.js';
14 > import { ExtensionError, ExtensionIdentifier, IExtensionDescription } from '../../../platform/extensions/common/extensions.js';
15 > import { ILogService } from '../../../platform/log/common/log.js';
16 > import { getSingletonServiceDescriptors } from '../../../platform/instantiation/common/extensions.js';
17 > import { ServiceCollection } from '../../../platform/instantiation/common/serviceCollection.js';
18 > import { IExtHostInitDataService } from './extHostInitDataService.js';
19 > import { InstantiationService } from '../../../platform/instantiation/common/instantiationService.js';
20 > import { IInstantiationService, ServicesAccessor } from '../../../platform/instantiation/common/instantiation.js';
21 > import { IExtHostRpcService, ExtHostRpcService } from './extHostRpcService.js';
22 > import { IURITransformerService, URITransformerService } from './extHostUriTransformerService.js';
23 > import { IExtHostExtensionService, IHostUtils } from './extHostExtensionService.js';
24 > import { IExtHostTelemetry } from './extHostTelemetry.js';
25 > import { Mutable } from '../../../base/common/types.js';
26 > import { IExtHostApiDeprecationService } from './extHostApiDeprecationService.js';
27 >
28 > export interface IExitFn {
29 > (code?: number): any;
30 > }
31 >
32 > export interface IConsolePatchFn {
33 > (mainThreadConsole: MainThreadConsoleShape): any;
34 > }
35 >
36 > export abstract class ErrorHandler {
37 >
38 > static async installEarlyHandler(accessor: ServicesAccessor): Promise<void> {
39
40 // increase number of stack frames (from 10, https://github.com/v8/v8/wiki/Stack-Trace-API)
41 Error.stackTraceLimit = 100;
42
43 // does NOT dependent of extension information, can be installed immediately, and simply forwards
44 // to the log service and main thread errors
45 const logService = accessor.get(ILogService);
46 const rpcService = accessor.get(IExtHostRpcService);
47 const mainThreadErrors = rpcService.getProxy(MainContext.MainThreadErrors);
48
49 errors.setUnexpectedErrorHandler(err => {
50 logService.error(err);
51 const data = errors.transformErrorForSerialization(err);
52 mainThreadErrors.$onUnexpectedError(data);
53 });
54 }
56 > static async installFullHandler(accessor: ServicesAccessor): Promise<void> {
57 > // uses extension knowledges to correlate errors with extensions
58 >
59 > const logService = accessor.get(ILogService);
60 > const rpcService = accessor.get(IExtHostRpcService);
61 > const extensionService = accessor.get(IExtHostExtensionService);
62 > const extensionTelemetry = accessor.get(IExtHostTelemetry);
63 > const apiDeprecationService = accessor.get(IExtHostApiDeprecationService);
64 >
65 > const mainThreadExtensions = rpcService.getProxy(MainContext.MainThreadExtensionService);
66 > const mainThreadErrors = rpcService.getProxy(MainContext.MainThreadErrors);
67 >
68 > const extensionsRegistry = await extensionService.getExtensionRegistry();
69 > const extensionsMap = await extensionService.getExtensionPathIndex();
70 > const extensionErrors = new WeakMap<Error, { extensionIdentifier: ExtensionIdentifier | undefined; stack: string }>();
71 >
72 > // PART 1
73 > // set the prepareStackTrace-handle and use it as a side-effect to associate errors
74 > // with extensions - this works by looking up callsites in the extension path index
75 > function prepareStackTraceAndFindExtension(error: Error, stackTrace: errors.V8CallSite[]) {
76 > if (extensionErrors.has(error)) {
77 > return extensionErrors.get(error)!.stack; extensionHostMain.ts ×1
78 > }
79 > let stackTraceMessage = ''; extensionHostMain.ts ×11
80 > let extension: IExtensionDescription | undefined;
81 > let fileName: string | null;
82 > for (const call of stackTrace) {
83 > stackTraceMessage += `\n\tat ${call.toString()}`;
84 > fileName = call.getFileName();
85 > if (!extension && fileName) {
86 > extension = extensionsMap.findSubstr(URI.file(fileName));
87 > }
88 > }
89 > const result = `${error.name || 'Error'}: ${error.message || ''}${stackTraceMessage}`;
90 > extensionErrors.set(error, { extensionIdentifier: extension?.identifier, stack: result });
91 > return result;
92 > }
93 >
94 > const _wasWrapped = Symbol('prepareStackTrace wrapped');
95 > let _prepareStackTrace = prepareStackTraceAndFindExtension;
96 >
97 > Object.defineProperty(Error, 'prepareStackTrace', {
98 > configurable: false,
99 > get() {
100 > return _prepareStackTrace;
101 > },
102 > set(v) {
103 > if (v === prepareStackTraceAndFindExtension || !v || v[_wasWrapped]) {
104 > _prepareStackTrace = v || prepareStackTraceAndFindExtension; extensionHostMain.ts ×1
105 > return;
106 > }
108 > _prepareStackTrace = function (error, stackTrace) {
109 > prepareStackTraceAndFindExtension(error, stackTrace); extensionHostMain.ts ×1
110 > return v.call(Error, error, stackTrace);
111 > };
113 > Object.assign(_prepareStackTrace, { [_wasWrapped]: true });
114 > },
115 > });
116 >
117 > // PART 2
118 > // set the unexpectedErrorHandler and check for extensions that have been identified as
119 > // having caused the error. Note that the runtime order is actually reversed, the code
120 > // below accesses the stack-property which triggers the code above
121 > errors.setUnexpectedErrorHandler(err => {
123 > if (!errors.PendingMigrationError.is(err)) {
124 > logService.error(err);
125 > }
126 >
127 > const errorData = errors.transformErrorForSerialization(err);
128 >
129 > let extension: ExtensionIdentifier | undefined;
130 > if (err instanceof ExtensionError) {
131 extension = err.extension;
132 > } else { extensionHostMain.ts ×5
133 > const stackData = extensionErrors.get(err);
134 > extension = stackData?.extensionIdentifier;
135 > }
136 >
137 > if (!extension) {
138 return;
139 }
141 > if (errors.PendingMigrationError.is(err)) {
142 // report pending migration via the API deprecation service which (1) informs the extensions author during
143 // dev-time and (2) collects telemetry so that we can reach out too
144 const extensionDesc = extensionsRegistry.getExtensionDescription(extension);
145 if (extensionDesc) {
146 apiDeprecationService.report(err.name, extensionDesc, `${err.message}\n FROM: ${err.stack}`);
147 }
148 > } else { extensionHostMain.ts ×5
149 > mainThreadExtensions.$onExtensionRuntimeError(extension, errorData);
150 > const reported = extensionTelemetry.onExtensionError(extension, err);
151 > logService.trace('forwarded error to extension?', reported, extension);
152 > }
154 >
155 > errors.errorHandler.addListener(err => {
156 > mainThreadErrors.$onUnexpectedError(err); extensionHostMain.ts ×5
158 > }
159 > }
160 >
161 > export class ExtensionHostMain {
162 >
163 > private readonly _hostUtils: IHostUtils;
164 > private readonly _rpcProtocol: RPCProtocol;
165 > private readonly _extensionService: IExtHostExtensionService;
166 > private readonly _logService: ILogService;
167 >
168 > constructor(
169 protocol: IMessagePassingProtocol,
170 initData: IExtensionHostInitData,
171 hostUtils: IHostUtils,
172 uriTransformer: IURITransformer | null,
173 messagePorts?: ReadonlyMap<string, MessagePort>
174 ) {
175 this._hostUtils = hostUtils;
176 this._rpcProtocol = new RPCProtocol(protocol, null, uriTransformer);
177
178 // ensure URIs are transformed and revived
179 initData = ExtensionHostMain._transform(initData, this._rpcProtocol);
180
181 // bootstrap services
182 const services = new ServiceCollection(...getSingletonServiceDescriptors());
183 services.set(IExtHostInitDataService, { _serviceBrand: undefined, ...initData, messagePorts });
184 services.set(IExtHostRpcService, new ExtHostRpcService(this._rpcProtocol));
185 services.set(IURITransformerService, new URITransformerService(uriTransformer));
186 services.set(IHostUtils, hostUtils);
187
188 const instaService: IInstantiationService = new InstantiationService(services, true);
189
190 instaService.invokeFunction(ErrorHandler.installEarlyHandler);
191
192 // ugly self - inject
193 this._logService = instaService.invokeFunction(accessor => accessor.get(ILogService));
194
195 performance.mark(`code/extHost/didCreateServices`);
196 if (this._hostUtils.pid) {
197 this._logService.info(`Extension host with pid ${this._hostUtils.pid} started`);
198 } else {
199 this._logService.info(`Extension host started`);
200 }
201 this._logService.trace('initData', initData);
202
203 // ugly self - inject
204 // must call initialize *after* creating the extension service
205 // because `initialize` itself creates instances that depend on it
206 this._extensionService = instaService.invokeFunction(accessor => accessor.get(IExtHostExtensionService));
207 this._extensionService.initialize();
208
209 // install error handler that is extension-aware
210 instaService.invokeFunction(ErrorHandler.installFullHandler);
211 }
213 > async asBrowserUri(uri: URI): Promise<URI> {
214 const mainThreadExtensionsProxy = this._rpcProtocol.getProxy(MainContext.MainThreadExtensionService);
215 return URI.revive(await mainThreadExtensionsProxy.$asBrowserUri(uri));
216 }
218 > terminate(reason: string): void {
219 this._extensionService.terminate(reason);
220 }
222 > private static _transform(initData: IExtensionHostInitData, rpcProtocol: RPCProtocol): IExtensionHostInitData {
223 initData.extensions.allExtensions.forEach((ext) => {
224 (<Mutable<IExtensionDescription>>ext).extensionLocation = URI.revive(rpcProtocol.transformIncomingURIs(ext.extensionLocation));
225 });
226 initData.environment.appRoot = URI.revive(rpcProtocol.transformIncomingURIs(initData.environment.appRoot));
227 const extDevLocs = initData.environment.extensionDevelopmentLocationURI;
228 if (extDevLocs) {
229 initData.environment.extensionDevelopmentLocationURI = extDevLocs.map(url => URI.revive(rpcProtocol.transformIncomingURIs(url)));
230 }
231 initData.environment.extensionTestsLocationURI = URI.revive(rpcProtocol.transformIncomingURIs(initData.environment.extensionTestsLocationURI));
232 initData.environment.globalStorageHome = URI.revive(rpcProtocol.transformIncomingURIs(initData.environment.globalStorageHome));
233 initData.environment.workspaceStorageHome = URI.revive(rpcProtocol.transformIncomingURIs(initData.environment.workspaceStorageHome));
234 initData.nlsBaseUrl = URI.revive(rpcProtocol.transformIncomingURIs(initData.nlsBaseUrl));
235 initData.logsLocation = URI.revive(rpcProtocol.transformIncomingURIs(initData.logsLocation));
236 initData.workspace = rpcProtocol.transformIncomingURIs(initData.workspace);
237 return initData;
238 }