mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-16 10:58:30 -05:00
Merge from vscode c58aaab8a1cc22a7139b761166a0d4f37d41e998 (#7880)
* Merge from vscode c58aaab8a1cc22a7139b761166a0d4f37d41e998 * fix pipelines * fix strict-null-checks * add missing files
This commit is contained in:
@@ -9,13 +9,13 @@ import { IDisposable, toDisposable, combinedDisposable } from 'vs/base/common/li
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||
import { IDialogService } from 'vs/platform/dialogs/common/dialogs';
|
||||
import { IExtensionGalleryService, IExtensionIdentifier, IExtensionManagementService } from 'vs/platform/extensionManagement/common/extensionManagement';
|
||||
import { IExtensionGalleryService, IExtensionIdentifier, IExtensionManagementService, ExtensionsLabel } from 'vs/platform/extensionManagement/common/extensionManagement';
|
||||
import { IExtensionEnablementService, EnablementState } from 'vs/workbench/services/extensionManagement/common/extensionManagement';
|
||||
import { areSameExtensions } from 'vs/platform/extensionManagement/common/extensionManagementUtil';
|
||||
import { createDecorator } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { INotificationHandle, INotificationService, Severity } from 'vs/platform/notification/common/notification';
|
||||
import { IStorageService, StorageScope } from 'vs/platform/storage/common/storage';
|
||||
import { IURLHandler, IURLService } from 'vs/platform/url/common/url';
|
||||
import { IURLHandler, IURLService, IOpenURLOptions } from 'vs/platform/url/common/url';
|
||||
import { IHostService } from 'vs/workbench/services/host/browser/host';
|
||||
import { IExtensionService } from 'vs/workbench/services/extensions/common/extensions';
|
||||
import { ExtensionIdentifier } from 'vs/platform/extensions/common/extensions';
|
||||
@@ -23,16 +23,47 @@ import { registerSingleton } from 'vs/platform/instantiation/common/extensions';
|
||||
import { Registry } from 'vs/platform/registry/common/platform';
|
||||
import { IWorkbenchContribution, Extensions as WorkbenchExtensions, IWorkbenchContributionsRegistry } from 'vs/workbench/common/contributions';
|
||||
import { LifecyclePhase } from 'vs/platform/lifecycle/common/lifecycle';
|
||||
import { IWorkbenchActionRegistry, Extensions as WorkbenchActionExtensions } from 'vs/workbench/common/actions';
|
||||
import { SyncActionDescriptor } from 'vs/platform/actions/common/actions';
|
||||
import { IQuickInputService, IQuickPickItem } from 'vs/platform/quickinput/common/quickInput';
|
||||
|
||||
const FIVE_MINUTES = 5 * 60 * 1000;
|
||||
const THIRTY_SECONDS = 30 * 1000;
|
||||
const URL_TO_HANDLE = 'extensionUrlHandler.urlToHandle';
|
||||
const CONFIRMED_EXTENSIONS_CONFIGURATION_KEY = 'extensions.confirmedUriHandlerExtensionIds';
|
||||
const CONFIRMED_EXTENSIONS_STORAGE_KEY = 'extensionUrlHandler.confirmedExtensions';
|
||||
|
||||
function isExtensionId(value: string): boolean {
|
||||
return /^[a-z0-9][a-z0-9\-]*\.[a-z0-9][a-z0-9\-]*$/i.test(value);
|
||||
}
|
||||
|
||||
class ConfirmedExtensionIdStorage {
|
||||
|
||||
get extensions(): string[] {
|
||||
const confirmedExtensionIdsJson = this.storageService.get(CONFIRMED_EXTENSIONS_STORAGE_KEY, StorageScope.GLOBAL, '[]');
|
||||
|
||||
try {
|
||||
return JSON.parse(confirmedExtensionIdsJson);
|
||||
} catch {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
constructor(private storageService: IStorageService) { }
|
||||
|
||||
has(id: string): boolean {
|
||||
return this.extensions.indexOf(id) > -1;
|
||||
}
|
||||
|
||||
add(id: string): void {
|
||||
this.set([...this.extensions, id]);
|
||||
}
|
||||
|
||||
set(ids: string[]): void {
|
||||
this.storageService.store(CONFIRMED_EXTENSIONS_STORAGE_KEY, JSON.stringify(ids), StorageScope.GLOBAL);
|
||||
}
|
||||
}
|
||||
|
||||
export const IExtensionUrlHandler = createDecorator<IExtensionUrlHandler>('extensionUrlHandler');
|
||||
|
||||
export interface IExtensionUrlHandler {
|
||||
@@ -56,6 +87,7 @@ class ExtensionUrlHandler implements IExtensionUrlHandler, IURLHandler {
|
||||
|
||||
private extensionHandlers = new Map<string, IURLHandler>();
|
||||
private uriBuffer = new Map<string, { timestamp: number, uri: URI }[]>();
|
||||
private storage: ConfirmedExtensionIdStorage;
|
||||
private disposable: IDisposable;
|
||||
|
||||
constructor(
|
||||
@@ -70,11 +102,13 @@ class ExtensionUrlHandler implements IExtensionUrlHandler, IURLHandler {
|
||||
@IStorageService private readonly storageService: IStorageService,
|
||||
@IConfigurationService private readonly configurationService: IConfigurationService
|
||||
) {
|
||||
this.storage = new ConfirmedExtensionIdStorage(storageService);
|
||||
|
||||
const interval = setInterval(() => this.garbageCollect(), THIRTY_SECONDS);
|
||||
const urlToHandleValue = this.storageService.get(URL_TO_HANDLE, StorageScope.WORKSPACE);
|
||||
if (urlToHandleValue) {
|
||||
this.storageService.remove(URL_TO_HANDLE, StorageScope.WORKSPACE);
|
||||
this.handleURL(URI.revive(JSON.parse(urlToHandleValue)), true);
|
||||
this.handleURL(URI.revive(JSON.parse(urlToHandleValue)), { trusted: true });
|
||||
}
|
||||
|
||||
this.disposable = combinedDisposable(
|
||||
@@ -86,7 +120,7 @@ class ExtensionUrlHandler implements IExtensionUrlHandler, IURLHandler {
|
||||
setTimeout(() => cache.forEach(uri => this.handleURL(uri)));
|
||||
}
|
||||
|
||||
async handleURL(uri: URI, confirmed?: boolean): Promise<boolean> {
|
||||
async handleURL(uri: URI, options?: IOpenURLOptions): Promise<boolean> {
|
||||
if (!isExtensionId(uri.authority)) {
|
||||
return false;
|
||||
}
|
||||
@@ -100,12 +134,14 @@ class ExtensionUrlHandler implements IExtensionUrlHandler, IURLHandler {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!confirmed) {
|
||||
const confirmedExtensionIds = this.getConfirmedExtensionIds();
|
||||
confirmed = confirmedExtensionIds.has(ExtensionIdentifier.toKey(extensionId));
|
||||
let showConfirm: boolean;
|
||||
if (options && options.trusted) {
|
||||
showConfirm = false;
|
||||
} else {
|
||||
showConfirm = !this.isConfirmed(ExtensionIdentifier.toKey(extensionId));
|
||||
}
|
||||
|
||||
if (!confirmed) {
|
||||
if (showConfirm) {
|
||||
let uriString = uri.toString();
|
||||
|
||||
// {{SQL CARBON EDIT}} - Begin
|
||||
@@ -135,7 +171,7 @@ class ExtensionUrlHandler implements IExtensionUrlHandler, IURLHandler {
|
||||
}
|
||||
|
||||
if (result.checkboxChecked) {
|
||||
await this.addConfirmedExtensionIdToStorage(extensionId);
|
||||
this.storage.add(ExtensionIdentifier.toKey(extensionId));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -144,7 +180,7 @@ class ExtensionUrlHandler implements IExtensionUrlHandler, IURLHandler {
|
||||
if (handler) {
|
||||
if (!wasHandlerAvailable) {
|
||||
// forward it directly
|
||||
return await handler.handleURL(uri);
|
||||
return await handler.handleURL(uri, options);
|
||||
}
|
||||
|
||||
// let the ExtensionUrlHandler instance handle this
|
||||
@@ -296,11 +332,12 @@ class ExtensionUrlHandler implements IExtensionUrlHandler, IURLHandler {
|
||||
this.uriBuffer = uriBuffer;
|
||||
}
|
||||
|
||||
private getConfirmedExtensionIds(): Set<string> {
|
||||
const ids = this.getConfirmedExtensionIdsFromConfiguration()
|
||||
.map(extensionId => ExtensionIdentifier.toKey(extensionId));
|
||||
private isConfirmed(id: string): boolean {
|
||||
if (this.storage.has(id)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return new Set(ids);
|
||||
return this.getConfirmedExtensionIdsFromConfiguration().indexOf(id) > -1;
|
||||
}
|
||||
|
||||
private getConfirmedExtensionIdsFromConfiguration(): Array<string> {
|
||||
@@ -313,14 +350,6 @@ class ExtensionUrlHandler implements IExtensionUrlHandler, IURLHandler {
|
||||
return confirmedExtensionIds;
|
||||
}
|
||||
|
||||
private async addConfirmedExtensionIdToStorage(extensionId: string): Promise<void> {
|
||||
const confirmedExtensionIds = this.configurationService.getValue<Array<string>>(CONFIRMED_EXTENSIONS_CONFIGURATION_KEY);
|
||||
const set = new Set(confirmedExtensionIds);
|
||||
set.add(extensionId);
|
||||
|
||||
await this.configurationService.updateValue(CONFIRMED_EXTENSIONS_CONFIGURATION_KEY, [...set.values()]);
|
||||
}
|
||||
|
||||
dispose(): void {
|
||||
this.disposable.dispose();
|
||||
this.extensionHandlers.clear();
|
||||
@@ -351,11 +380,52 @@ class ExtensionUrlBootstrapHandler implements IWorkbenchContribution, IURLHandle
|
||||
ExtensionUrlBootstrapHandler.disposable = urlService.registerHandler(this);
|
||||
}
|
||||
|
||||
handleURL(uri: URI): Promise<boolean> {
|
||||
async handleURL(uri: URI): Promise<boolean> {
|
||||
if (!isExtensionId(uri.authority)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ExtensionUrlBootstrapHandler._cache.push(uri);
|
||||
return Promise.resolve(true);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
const workbenchRegistry = Registry.as<IWorkbenchContributionsRegistry>(WorkbenchExtensions.Workbench);
|
||||
workbenchRegistry.registerWorkbenchContribution(ExtensionUrlBootstrapHandler, LifecyclePhase.Ready);
|
||||
|
||||
export class ManageAuthorizedExtensionURIsAction extends Action {
|
||||
|
||||
static readonly ID = 'workbench.extensions.action.manageAuthorizedExtensionURIs';
|
||||
static readonly LABEL = localize('manage', "Manage Authorized Extension URIs...");
|
||||
|
||||
private storage: ConfirmedExtensionIdStorage;
|
||||
|
||||
constructor(
|
||||
id = ManageAuthorizedExtensionURIsAction.ID,
|
||||
label = ManageAuthorizedExtensionURIsAction.LABEL,
|
||||
@IStorageService readonly storageService: IStorageService,
|
||||
@IQuickInputService private readonly quickInputService: IQuickInputService
|
||||
) {
|
||||
super(id, label, undefined, true);
|
||||
this.storage = new ConfirmedExtensionIdStorage(storageService);
|
||||
}
|
||||
|
||||
async run(): Promise<void> {
|
||||
const items = this.storage.extensions.map(label => ({ label, picked: true } as IQuickPickItem));
|
||||
|
||||
if (items.length === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
const result = await this.quickInputService.pick(items, { canPickMany: true });
|
||||
|
||||
if (!result) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.storage.set(result.map(item => item.label));
|
||||
}
|
||||
}
|
||||
|
||||
const actionRegistry = Registry.as<IWorkbenchActionRegistry>(WorkbenchActionExtensions.WorkbenchActions);
|
||||
actionRegistry.registerWorkbenchAction(new SyncActionDescriptor(ManageAuthorizedExtensionURIsAction, ManageAuthorizedExtensionURIsAction.ID, ManageAuthorizedExtensionURIsAction.LABEL), `Extensions: Manage Authorized Extension URIs...`, ExtensionsLabel);
|
||||
|
||||
@@ -113,6 +113,10 @@ export class WebWorkerExtensionHostStarter implements IExtensionHostStarter {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
enableInspectPort(): Promise<boolean> {
|
||||
return Promise.resolve(false);
|
||||
}
|
||||
|
||||
private async _createExtHostInitData(): Promise<IInitData> {
|
||||
const [telemetryInfo, extensionDescriptions] = await Promise.all([this._telemetryService.getTelemetryInfo(), this._extensions]);
|
||||
const workspace = this._contextService.getWorkspace();
|
||||
|
||||
@@ -256,8 +256,8 @@ export abstract class AbstractExtensionService extends Disposable implements IEx
|
||||
return result;
|
||||
}
|
||||
|
||||
public getInspectPort(): number {
|
||||
return 0;
|
||||
public getInspectPort(_tryEnableInspector: boolean): Promise<number> {
|
||||
return Promise.resolve(0);
|
||||
}
|
||||
|
||||
public async setRemoteEnvironment(env: { [key: string]: string | null }): Promise<void> {
|
||||
@@ -459,9 +459,10 @@ class ProposedApiController {
|
||||
// Make enabled proposed API be lowercase for case insensitive comparison
|
||||
this.enableProposedApiFor = (environmentService.args['enable-proposed-api'] || []).map(id => id.toLowerCase());
|
||||
|
||||
this.enableProposedApiForAll = !environmentService.isBuilt ||
|
||||
(!!environmentService.extensionDevelopmentLocationURI && productService.nameLong !== 'Visual Studio Code') ||
|
||||
(this.enableProposedApiFor.length === 0 && 'enable-proposed-api' in environmentService.args);
|
||||
this.enableProposedApiForAll =
|
||||
!environmentService.isBuilt || // always allow proposed API when running out of sources
|
||||
(!!environmentService.extensionDevelopmentLocationURI && productService.quality !== 'stable') || // do not allow proposed API against stable builds when developing an extension
|
||||
(this.enableProposedApiFor.length === 0 && 'enable-proposed-api' in environmentService.args); // always allow proposed API if --enable-proposed-api is provided without extension ID
|
||||
|
||||
this.productAllowProposedApi = new Set<string>();
|
||||
if (isNonEmptyArray(productService.extensionAllowedProposedApi)) {
|
||||
|
||||
@@ -118,12 +118,7 @@ export class ExtensionDescriptionRegistry {
|
||||
|
||||
hasOnlyGoodArcs(id: string, good: Set<string>): boolean {
|
||||
const dependencies = G.getArcs(id);
|
||||
for (let i = 0; i < dependencies.length; i++) {
|
||||
if (!good.has(dependencies[i])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
return dependencies.every(dependency => good.has(dependency));
|
||||
}
|
||||
|
||||
getNodes(): string[] {
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
import { timeout } from 'vs/base/common/async';
|
||||
import * as errors from 'vs/base/common/errors';
|
||||
import { DisposableStore } from 'vs/base/common/lifecycle';
|
||||
import { URI, setUriThrowOnMissingScheme } from 'vs/base/common/uri';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { IURITransformer } from 'vs/base/common/uriIpc';
|
||||
import { IMessagePassingProtocol } from 'vs/base/parts/ipc/common/ipc';
|
||||
import { IInitData, MainContext, MainThreadConsoleShape } from 'vs/workbench/api/common/extHost.protocol';
|
||||
@@ -22,10 +22,6 @@ import { IExtHostRpcService, ExtHostRpcService } from 'vs/workbench/api/common/e
|
||||
import { IURITransformerService, URITransformerService } from 'vs/workbench/api/common/extHostUriTransformerService';
|
||||
import { IExtHostExtensionService, IHostUtils } from 'vs/workbench/api/common/extHostExtensionService';
|
||||
|
||||
// we don't (yet) throw when extensions parse
|
||||
// uris that have no scheme
|
||||
setUriThrowOnMissingScheme(false);
|
||||
|
||||
export interface IExitFn {
|
||||
(code?: number): any;
|
||||
}
|
||||
|
||||
@@ -240,8 +240,11 @@ export class ExtensionHostProcessManager extends Disposable {
|
||||
});
|
||||
}
|
||||
|
||||
public getInspectPort(): number {
|
||||
public async getInspectPort(tryEnableInspector: boolean): Promise<number> {
|
||||
if (this._extensionHostProcessWorker) {
|
||||
if (tryEnableInspector) {
|
||||
await this._extensionHostProcessWorker.enableInspectPort();
|
||||
}
|
||||
let port = this._extensionHostProcessWorker.getInspectPort();
|
||||
if (port) {
|
||||
return port;
|
||||
@@ -250,10 +253,6 @@ export class ExtensionHostProcessManager extends Disposable {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public canProfileExtensionHost(): boolean {
|
||||
return this._extensionHostProcessWorker && Boolean(this._extensionHostProcessWorker.getInspectPort());
|
||||
}
|
||||
|
||||
public async resolveAuthority(remoteAuthority: string): Promise<ResolverResult> {
|
||||
const authorityPlusIndex = remoteAuthority.indexOf('+');
|
||||
if (authorityPlusIndex === -1) {
|
||||
|
||||
@@ -89,6 +89,7 @@ export interface IExtensionHostStarter {
|
||||
|
||||
start(): Promise<IMessagePassingProtocol> | null;
|
||||
getInspectPort(): number | undefined;
|
||||
enableInspectPort(): Promise<boolean>;
|
||||
dispose(): void;
|
||||
}
|
||||
|
||||
@@ -212,7 +213,7 @@ export interface IExtensionService {
|
||||
* Return the inspect port or `0`, the latter means inspection
|
||||
* is not possible.
|
||||
*/
|
||||
getInspectPort(): number;
|
||||
getInspectPort(tryEnableInspector: boolean): Promise<number>;
|
||||
|
||||
/**
|
||||
* Restarts the extension host.
|
||||
@@ -270,7 +271,7 @@ export class NullExtensionService implements IExtensionService {
|
||||
getExtension() { return Promise.resolve(undefined); }
|
||||
readExtensionPointContributions<T>(_extPoint: IExtensionPoint<T>): Promise<ExtensionPointContribution<T>[]> { return Promise.resolve(Object.create(null)); }
|
||||
getExtensionsStatus(): { [id: string]: IExtensionsStatus; } { return Object.create(null); }
|
||||
getInspectPort(): number { return 0; }
|
||||
getInspectPort(_tryEnableInspector: boolean): Promise<number> { return Promise.resolve(0); }
|
||||
restartExtensionHost(): void { }
|
||||
async setRemoteEnvironment(_env: { [key: string]: string | null }): Promise<void> { }
|
||||
canAddExtension(): boolean { return false; }
|
||||
|
||||
@@ -226,6 +226,10 @@ export class RemoteExtensionHostClient extends Disposable implements IExtensionH
|
||||
return undefined;
|
||||
}
|
||||
|
||||
enableInspectPort(): Promise<boolean> {
|
||||
return Promise.resolve(false);
|
||||
}
|
||||
|
||||
dispose(): void {
|
||||
super.dispose();
|
||||
|
||||
|
||||
@@ -58,7 +58,7 @@ const noop = () => { };
|
||||
|
||||
export class RPCProtocol extends Disposable implements IRPCProtocol {
|
||||
|
||||
private static UNRESPONSIVE_TIME = 3 * 1000; // 3s
|
||||
private static readonly UNRESPONSIVE_TIME = 3 * 1000; // 3s
|
||||
|
||||
private readonly _onDidChangeResponsiveState: Emitter<ResponsiveState> = this._register(new Emitter<ResponsiveState>());
|
||||
public readonly onDidChangeResponsiveState: Event<ResponsiveState> = this._onDidChangeResponsiveState.event;
|
||||
@@ -588,12 +588,7 @@ class MessageBuffer {
|
||||
class MessageIO {
|
||||
|
||||
private static _arrayContainsBuffer(arr: any[]): boolean {
|
||||
for (let i = 0, len = arr.length; i < len; i++) {
|
||||
if (arr[i] instanceof VSBuffer) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
return arr.some(value => value instanceof VSBuffer);
|
||||
}
|
||||
|
||||
public static serializeRequest(req: number, rpcId: number, method: string, args: any[], usesCancellationToken: boolean, replacer: JSONStringifyReplacer | null): VSBuffer {
|
||||
|
||||
@@ -16,7 +16,7 @@ import * as platform from 'vs/base/common/platform';
|
||||
import { URI } from 'vs/base/common/uri';
|
||||
import { IRemoteConsoleLog, log } from 'vs/base/common/console';
|
||||
import { logRemoteEntry } from 'vs/workbench/services/extensions/common/remoteConsoleUtil';
|
||||
import { findFreePort, randomPort } from 'vs/base/node/ports';
|
||||
import { findFreePort } from 'vs/base/node/ports';
|
||||
import { IMessagePassingProtocol } from 'vs/base/parts/ipc/common/ipc';
|
||||
import { PersistentProtocol } from 'vs/base/parts/ipc/common/ipc.net';
|
||||
import { generateRandomPipeName, NodeSocket } from 'vs/base/parts/ipc/node/ipc.net';
|
||||
@@ -45,6 +45,8 @@ export class ExtensionHostProcessWorker implements IExtensionHostStarter {
|
||||
private readonly _onExit: Emitter<[number, string]> = new Emitter<[number, string]>();
|
||||
public readonly onExit: Event<[number, string]> = this._onExit.event;
|
||||
|
||||
private readonly _onDidSetInspectPort = new Emitter<void>();
|
||||
|
||||
private readonly _toDispose = new DisposableStore();
|
||||
|
||||
private readonly _isExtensionDevHost: boolean;
|
||||
@@ -127,10 +129,10 @@ export class ExtensionHostProcessWorker implements IExtensionHostStarter {
|
||||
if (!this._messageProtocol) {
|
||||
this._messageProtocol = Promise.all([
|
||||
this._tryListenOnPipe(),
|
||||
!this._environmentService.args['disable-inspect'] ? this._tryFindDebugPort() : Promise.resolve(null)
|
||||
this._tryFindDebugPort()
|
||||
]).then(data => {
|
||||
const pipeName = data[0];
|
||||
const portData = data[1];
|
||||
const portNumber = data[1];
|
||||
|
||||
const opts = {
|
||||
env: objects.mixin(objects.deepClone(process.env), {
|
||||
@@ -151,16 +153,11 @@ export class ExtensionHostProcessWorker implements IExtensionHostStarter {
|
||||
silent: true
|
||||
};
|
||||
|
||||
if (portData && portData.actual) {
|
||||
if (portNumber !== 0) {
|
||||
opts.execArgv = [
|
||||
'--nolazy',
|
||||
(this._isExtensionDevDebugBrk ? '--inspect-brk=' : '--inspect=') + portData.actual
|
||||
(this._isExtensionDevDebugBrk ? '--inspect-brk=' : '--inspect=') + portNumber
|
||||
];
|
||||
if (!portData.expected) {
|
||||
// No one asked for 'inspect' or 'inspect-brk', only us. We add another
|
||||
// option such that the extension host can manipulate the execArgv array
|
||||
opts.env.VSCODE_PREVENT_FOREIGN_INSPECT = true;
|
||||
}
|
||||
}
|
||||
|
||||
const crashReporterOptions = undefined; // TODO@electron pass this in as options to the extension host after verifying this actually works
|
||||
@@ -198,6 +195,7 @@ export class ExtensionHostProcessWorker implements IExtensionHostStarter {
|
||||
}
|
||||
if (!this._inspectPort) {
|
||||
this._inspectPort = Number(inspectorUrlMatch[2]);
|
||||
this._onDidSetInspectPort.fire();
|
||||
}
|
||||
} else {
|
||||
console.group('Extension Host');
|
||||
@@ -218,11 +216,12 @@ export class ExtensionHostProcessWorker implements IExtensionHostStarter {
|
||||
this._extensionHostProcess.on('exit', (code: number, signal: string) => this._onExtHostProcessExit(code, signal));
|
||||
|
||||
// Notify debugger that we are ready to attach to the process if we run a development extension
|
||||
if (portData) {
|
||||
if (this._isExtensionDevHost && portData.actual && this._isExtensionDevDebug && this._environmentService.debugExtensionHost.debugId) {
|
||||
this._extensionHostDebugService.attachSession(this._environmentService.debugExtensionHost.debugId, portData.actual);
|
||||
if (portNumber) {
|
||||
if (this._isExtensionDevHost && portNumber && this._isExtensionDevDebug && this._environmentService.debugExtensionHost.debugId) {
|
||||
this._extensionHostDebugService.attachSession(this._environmentService.debugExtensionHost.debugId, portNumber);
|
||||
}
|
||||
this._inspectPort = portData.actual;
|
||||
this._inspectPort = portNumber;
|
||||
this._onDidSetInspectPort.fire();
|
||||
}
|
||||
|
||||
// Help in case we fail to start it
|
||||
@@ -275,29 +274,31 @@ export class ExtensionHostProcessWorker implements IExtensionHostStarter {
|
||||
/**
|
||||
* Find a free port if extension host debugging is enabled.
|
||||
*/
|
||||
private _tryFindDebugPort(): Promise<{ expected: number; actual: number }> {
|
||||
let expected: number;
|
||||
let startPort = randomPort();
|
||||
if (typeof this._environmentService.debugExtensionHost.port === 'number') {
|
||||
startPort = expected = this._environmentService.debugExtensionHost.port;
|
||||
private async _tryFindDebugPort(): Promise<number> {
|
||||
|
||||
if (typeof this._environmentService.debugExtensionHost.port !== 'number') {
|
||||
return 0;
|
||||
}
|
||||
return new Promise(resolve => {
|
||||
return findFreePort(startPort, 10 /* try 10 ports */, 5000 /* try up to 5 seconds */).then(port => {
|
||||
if (!port) {
|
||||
console.warn('%c[Extension Host] %cCould not find a free port for debugging', 'color: blue', 'color:');
|
||||
} else {
|
||||
if (expected && port !== expected) {
|
||||
console.warn(`%c[Extension Host] %cProvided debugging port ${expected} is not free, using ${port} instead.`, 'color: blue', 'color:');
|
||||
}
|
||||
if (this._isExtensionDevDebugBrk) {
|
||||
console.warn(`%c[Extension Host] %cSTOPPED on first line for debugging on port ${port}`, 'color: blue', 'color:');
|
||||
} else {
|
||||
console.info(`%c[Extension Host] %cdebugger listening on port ${port}`, 'color: blue', 'color:');
|
||||
}
|
||||
}
|
||||
return resolve({ expected, actual: port });
|
||||
});
|
||||
});
|
||||
|
||||
const expected = this._environmentService.debugExtensionHost.port;
|
||||
const port = await findFreePort(expected, 10 /* try 10 ports */, 5000 /* try up to 5 seconds */);
|
||||
|
||||
if (!port) {
|
||||
console.warn('%c[Extension Host] %cCould not find a free port for debugging', 'color: blue', 'color:');
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (port !== expected) {
|
||||
console.warn(`%c[Extension Host] %cProvided debugging port ${expected} is not free, using ${port} instead.`, 'color: blue', 'color:');
|
||||
}
|
||||
if (this._isExtensionDevDebugBrk) {
|
||||
console.warn(`%c[Extension Host] %cSTOPPED on first line for debugging on port ${port}`, 'color: blue', 'color:');
|
||||
} else {
|
||||
console.info(`%c[Extension Host] %cdebugger listening on port ${port}`, 'color: blue', 'color:');
|
||||
}
|
||||
return port;
|
||||
|
||||
|
||||
}
|
||||
|
||||
private _tryExtHostHandshake(): Promise<PersistentProtocol> {
|
||||
@@ -467,6 +468,37 @@ export class ExtensionHostProcessWorker implements IExtensionHostStarter {
|
||||
this._onExit.fire([code, signal]);
|
||||
}
|
||||
|
||||
public async enableInspectPort(): Promise<boolean> {
|
||||
if (typeof this._inspectPort === 'number') {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!this._extensionHostProcess) {
|
||||
return false;
|
||||
}
|
||||
|
||||
interface ProcessExt {
|
||||
_debugProcess?(n: number): any;
|
||||
}
|
||||
|
||||
if (typeof (<ProcessExt>process)._debugProcess === 'function') {
|
||||
// use (undocumented) _debugProcess feature of node
|
||||
(<ProcessExt>process)._debugProcess!(this._extensionHostProcess.pid);
|
||||
await Promise.race([Event.toPromise(this._onDidSetInspectPort.event), timeout(1000)]);
|
||||
return typeof this._inspectPort === 'number';
|
||||
|
||||
} else if (!platform.isWindows) {
|
||||
// use KILL USR1 on non-windows platforms (fallback)
|
||||
this._extensionHostProcess.kill('SIGUSR1');
|
||||
await Promise.race([Event.toPromise(this._onDidSetInspectPort.event), timeout(1000)]);
|
||||
return typeof this._inspectPort === 'number';
|
||||
|
||||
} else {
|
||||
// not supported...
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public getInspectPort(): number | undefined {
|
||||
return withNullAsUndefined(this._inspectPort);
|
||||
}
|
||||
|
||||
@@ -542,9 +542,9 @@ export class ExtensionService extends AbstractExtensionService implements IExten
|
||||
this._doHandleExtensionPoints(this._registry.getAllExtensionDescriptions());
|
||||
}
|
||||
|
||||
public getInspectPort(): number {
|
||||
public async getInspectPort(tryEnableInspector: boolean): Promise<number> {
|
||||
if (this._extensionHostProcessManagers.length > 0) {
|
||||
return this._extensionHostProcessManagers[0].getInspectPort();
|
||||
return this._extensionHostProcessManagers[0].getInspectPort(tryEnableInspector);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -222,7 +222,7 @@ function connectToRenderer(protocol: IMessagePassingProtocol): Promise<IRenderer
|
||||
promise.catch(e => {
|
||||
unhandledPromises.splice(idx, 1);
|
||||
console.warn(`rejected promise not handled within 1 second: ${e}`);
|
||||
if (e.stack) {
|
||||
if (e && e.stack) {
|
||||
console.warn(`stack trace: ${e.stack}`);
|
||||
}
|
||||
onUnexpectedError(reason);
|
||||
@@ -275,20 +275,6 @@ function connectToRenderer(protocol: IMessagePassingProtocol): Promise<IRenderer
|
||||
});
|
||||
}
|
||||
|
||||
// patchExecArgv:
|
||||
(function () {
|
||||
// when encountering the prevent-inspect flag we delete this
|
||||
// and the prior flag
|
||||
if (process.env.VSCODE_PREVENT_FOREIGN_INSPECT) {
|
||||
for (let i = 0; i < process.execArgv.length; i++) {
|
||||
if (process.execArgv[i].match(/--inspect-brk=\d+|--inspect=\d+/)) {
|
||||
process.execArgv.splice(i, 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
})();
|
||||
|
||||
export async function startExtensionHostProcess(): Promise<void> {
|
||||
|
||||
const protocol = await createExtHostProtocol();
|
||||
|
||||
@@ -51,7 +51,7 @@ class ExtensionManifestParser extends ExtensionManifestHandler {
|
||||
return pfs.readFile(this._absoluteManifestPath).then((manifestContents) => {
|
||||
const errors: json.ParseError[] = [];
|
||||
const manifest = json.parse(manifestContents.toString(), errors);
|
||||
if (errors.length === 0) {
|
||||
if (!!manifest && errors.length === 0) {
|
||||
if (manifest.__metadata) {
|
||||
manifest.uuid = manifest.__metadata.id;
|
||||
}
|
||||
@@ -397,15 +397,7 @@ class ExtensionManifestValidator extends ExtensionManifestHandler {
|
||||
}
|
||||
|
||||
private static _isStringArray(arr: string[]): boolean {
|
||||
if (!Array.isArray(arr)) {
|
||||
return false;
|
||||
}
|
||||
for (let i = 0, len = arr.length; i < len; i++) {
|
||||
if (typeof arr[i] !== 'string') {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
return Array.isArray(arr) && arr.every(value => typeof value === 'string');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -35,9 +35,6 @@ self.postMessage = () => console.trace(`'postMessage' has been blocked`);
|
||||
const nativeAddEventLister = addEventListener.bind(self);
|
||||
self.addEventLister = () => console.trace(`'addEventListener' has been blocked`);
|
||||
|
||||
self.indexedDB.open = () => console.trace(`'indexedDB.open' has been blocked`);
|
||||
self.caches.open = () => console.trace(`'indexedDB.caches' has been blocked`);
|
||||
|
||||
//#endregion ---
|
||||
|
||||
const hostUtil = new class implements IHostUtils {
|
||||
|
||||
Reference in New Issue
Block a user