Skip to content

Commit

Permalink
prefix stack with extension id, #32766
Browse files Browse the repository at this point in the history
  • Loading branch information
jrieken committed Aug 18, 2017
1 parent d30567b commit 69c9ede
Show file tree
Hide file tree
Showing 4 changed files with 68 additions and 28 deletions.
18 changes: 18 additions & 0 deletions src/vs/base/common/errors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,24 @@ export function transformErrorForSerialization(error: any): any {
return error;
}

// see https://github.com/v8/v8/wiki/Stack%20Trace%20API#basic-stack-traces
export interface V8CallSite {
getThis(): any;
getTypeName(): string;
getFunction(): string;
getFunctionName(): string;
getMethodName(): string;
getFileName(): string;
getLineNumber(): number;
getColumnNumber(): number;
getEvalOrigin(): string;
isToplevel(): boolean;
isEval(): boolean;
isNative(): boolean;
isConstructor(): boolean;
toString(): string;
}

const canceledName = 'Canceled';

/**
Expand Down
26 changes: 1 addition & 25 deletions src/vs/workbench/api/node/extHost.api.impl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,6 @@ import { ITelemetryService } from 'vs/platform/telemetry/common/telemetry';
import { CancellationTokenSource } from 'vs/base/common/cancellation';
import * as vscode from 'vscode';
import * as paths from 'vs/base/common/paths';
import { realpath } from 'fs';
import { MainContext, ExtHostContext, IInitData } from './extHost.protocol';
import * as languageConfiguration from 'vs/editor/common/modes/languageConfiguration';
import { TextEditorCursorStyle } from 'vs/editor/common/config/editorOptions';
Expand Down Expand Up @@ -621,30 +620,7 @@ class Extension<T> implements vscode.Extension<T> {
}

export function initializeExtensionApi(extensionService: ExtHostExtensionService, apiFactory: IExtensionApiFactory): TPromise<void> {
return createExtensionPathIndex(extensionService).then(trie => defineAPI(apiFactory, trie));
}

function createExtensionPathIndex(extensionService: ExtHostExtensionService): TPromise<TrieMap<IExtensionDescription>> {

// create trie to enable fast 'filename -> extension id' look up
const trie = new TrieMap<IExtensionDescription>();
const extensions = extensionService.getAllExtensionDescriptions().map(ext => {
if (!ext.main) {
return undefined;
}
return new TPromise((resolve, reject) => {
realpath(ext.extensionFolderPath, (err, path) => {
if (err) {
reject(err);
} else {
trie.insert(path, ext);
resolve(void 0);
}
});
});
});

return TPromise.join(extensions).then(() => trie);
return extensionService.getExtensionPathIndex().then(trie => defineAPI(apiFactory, trie));
}

function defineAPI(factory: IExtensionApiFactory, extensionPaths: TrieMap<IExtensionDescription>): void {
Expand Down
29 changes: 28 additions & 1 deletion src/vs/workbench/api/node/extHostExtensionService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ import { MainContext, MainThreadExtensionServiceShape, IWorkspaceData, IEnvironm
import { IExtensionMemento, ExtensionsActivator, ActivatedExtension, IExtensionAPI, IExtensionContext, EmptyExtension, IExtensionModule } from "vs/workbench/api/node/extHostExtensionActivator";
import { Barrier } from "vs/workbench/services/extensions/node/barrier";
import { ExtHostThreadService } from "vs/workbench/services/thread/node/extHostThreadService";
import { realpath } from 'fs';
import { TrieMap } from "vs/base/common/map";

class ExtensionMemento implements IExtensionMemento {

Expand Down Expand Up @@ -115,7 +117,7 @@ export class ExtHostExtensionService implements ExtHostExtensionServiceShape {
private readonly _storagePath: ExtensionStoragePath;
private readonly _proxy: MainThreadExtensionServiceShape;
private _activator: ExtensionsActivator;

private _extensionPathIndex: TPromise<TrieMap<IExtensionDescription>>;
/**
* This class is constructed manually because it is a service, so it doesn't use any ctor injection
*/
Expand Down Expand Up @@ -202,6 +204,31 @@ export class ExtHostExtensionService implements ExtHostExtensionServiceShape {
}
}

// create trie to enable fast 'filename -> extension id' look up
public getExtensionPathIndex(): TPromise<TrieMap<IExtensionDescription>> {
if (!this._extensionPathIndex) {
const trie = new TrieMap<IExtensionDescription>();
const extensions = this.getAllExtensionDescriptions().map(ext => {
if (!ext.main) {
return undefined;
}
return new TPromise((resolve, reject) => {
realpath(ext.extensionFolderPath, (err, path) => {
if (err) {
reject(err);
} else {
trie.insert(path, ext);
resolve(void 0);
}
});
});
});
this._extensionPathIndex = TPromise.join(extensions).then(() => trie);
}
return this._extensionPathIndex;
}


public deactivate(extensionId: string): TPromise<void> {
let result: TPromise<void> = TPromise.as(void 0);

Expand Down
23 changes: 21 additions & 2 deletions src/vs/workbench/node/extensionHostMain.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { join } from 'path';
import { RPCProtocol } from 'vs/workbench/services/extensions/node/rpcProtocol';
import { ExtHostExtensionService } from 'vs/workbench/api/node/extHostExtensionService';
import { ExtHostThreadService } from 'vs/workbench/services/thread/node/extHostThreadService';
import { IExtensionDescription } from "vs/platform/extensions/common/extensions";
import { QueryType, ISearchQuery } from 'vs/platform/search/common/search';
import { DiskSearch } from 'vs/workbench/services/search/node/searchService';
import { RemoteTelemetryService } from 'vs/workbench/api/node/extHostTelemetry';
Expand Down Expand Up @@ -49,9 +50,27 @@ export class ExtensionHostMain {
const telemetryService = new RemoteTelemetryService('pluginHostTelemetry', threadService);
this._extensionService = new ExtHostExtensionService(initData, threadService, telemetryService);

// Error forwarding
// error forwarding and stack trace scanning
this._extensionService.getExtensionPathIndex().then(map => {
(<any>Error).prepareStackTrace = (error: Error, stackTrace: errors.V8CallSite[]) => {
let stackTraceMessage = '';
let extension: IExtensionDescription;
for (const call of stackTrace) {
stackTraceMessage += `\n\tat ${call.toString()}`;
extension = extension || map.findSubstr(stackTrace[0].getFileName());
}
let name = error.name || 'Error';
if (extension) {
name = `[${extension.id}] ${name}`;
}
return `${name}: ${error.message}${stackTraceMessage}`;
};
});
const mainThreadErrors = threadService.get(MainContext.MainThreadErrors);
errors.setUnexpectedErrorHandler(err => mainThreadErrors.$onUnexpectedExtHostError(errors.transformErrorForSerialization(err)));
errors.setUnexpectedErrorHandler(err => {
const data = errors.transformErrorForSerialization(err);
mainThreadErrors.$onUnexpectedExtHostError(data);
});

// Configure the watchdog to kill our process if the JS event loop is unresponsive for more than 10s
if (!initData.environment.isExtensionDevelopmentDebug) {
Expand Down

0 comments on commit 69c9ede

Please sign in to comment.