Merge from vscode e558dc6ea73a75bd69d7a0b485f0e7e4194c66bf (#6864)

This commit is contained in:
Anthony Dresser
2019-08-21 20:44:59 -07:00
committed by GitHub
parent d2ae0f0154
commit 985bfae8a0
107 changed files with 2260 additions and 814 deletions

View File

@@ -275,7 +275,7 @@ export class EditorService extends Disposable implements EditorServiceImpl {
// Respect option to reveal an editor if it is already visible in any group
if (options && options.revealIfVisible) {
for (const group of groupsByLastActive) {
if (input.matches(group.activeEditor)) {
if (group.isActive(input)) {
targetGroup = group;
break;
}
@@ -283,11 +283,16 @@ export class EditorService extends Disposable implements EditorServiceImpl {
}
// Respect option to reveal an editor if it is open (not necessarily visible)
if ((options && options.revealIfOpened) || this.configurationService.getValue<boolean>('workbench.editor.revealIfOpen')) {
for (const group of groupsByLastActive) {
if (group.isOpened(input)) {
targetGroup = group;
break;
if (!targetGroup) {
if ((options && options.revealIfOpened) || this.configurationService.getValue<boolean>('workbench.editor.revealIfOpen')) {
for (const group of groupsByLastActive) {
if (group.isOpened(input) && group.isActive(input)) {
targetGroup = group;
break;
}
if (group.isOpened(input) && !targetGroup) {
targetGroup = group;
}
}
}
}

View File

@@ -62,11 +62,9 @@ export class BrowserWindowConfiguration implements IWindowConfiguration {
termProgram?: string;
}
export interface IBrowserWindowConfiguration {
interface IBrowserWorkbenchEnvironemntConstructionOptions extends IWorkbenchConstructionOptions {
workspaceId: string;
remoteAuthority?: string;
webviewEndpoint?: string;
connectionToken?: string;
logsPath: URI;
}
export class BrowserWorkbenchEnvironmentService implements IWorkbenchEnvironmentService {
@@ -75,8 +73,10 @@ export class BrowserWorkbenchEnvironmentService implements IWorkbenchEnvironment
readonly configuration: IWindowConfiguration = new BrowserWindowConfiguration();
constructor(workspaceId: string, public readonly options: IWorkbenchConstructionOptions) {
constructor(readonly options: IBrowserWorkbenchEnvironemntConstructionOptions) {
this.args = { _: [] };
this.logsPath = options.logsPath.path;
this.logFile = joinPath(options.logsPath, 'window.log');
this.appRoot = '/web/';
this.appNameLong = 'Visual Studio Code - Web';
@@ -88,10 +88,8 @@ export class BrowserWorkbenchEnvironmentService implements IWorkbenchEnvironment
this.keyboardLayoutResource = joinPath(this.userRoamingDataHome, 'keyboardLayout.json');
this.localeResource = joinPath(this.userRoamingDataHome, 'locale.json');
this.backupHome = joinPath(this.userRoamingDataHome, BACKUPS);
this.configuration.backupWorkspaceResource = joinPath(this.backupHome, workspaceId);
this.configuration.connectionToken = options.connectionToken || this.getConnectionTokenFromLocation();
this.logsPath = '/web/logs';
this.configuration.backupWorkspaceResource = joinPath(this.backupHome, options.workspaceId);
this.configuration.connectionToken = options.connectionToken || getCookieValue('vscode-tkn');
this.debugExtensionHost = {
port: null,
@@ -183,6 +181,7 @@ export class BrowserWorkbenchEnvironmentService implements IWorkbenchEnvironment
driverVerbose: boolean;
webviewEndpoint?: string;
galleryMachineIdResource?: URI;
readonly logFile: URI;
get webviewResourceRoot(): string {
return this.webviewEndpoint ? this.webviewEndpoint + '/vscode-resource{{resource}}' : 'vscode-resource:{{resource}}';
@@ -191,21 +190,12 @@ export class BrowserWorkbenchEnvironmentService implements IWorkbenchEnvironment
get webviewCspSource(): string {
return this.webviewEndpoint ? this.webviewEndpoint : 'vscode-resource:';
}
private getConnectionTokenFromLocation(): string | undefined {
// TODO: Check with @alexd where the token will be: search or hash?
let connectionToken: string | undefined = undefined;
if (document.location.search) {
connectionToken = this.getConnectionToken(document.location.search);
}
if (!connectionToken && document.location.hash) {
connectionToken = this.getConnectionToken(document.location.hash);
}
return connectionToken;
}
private getConnectionToken(str: string): string | undefined {
const m = str.match(/[#&?]tkn=([^&]+)/);
return m ? m[1] : undefined;
}
}
/**
* See https://stackoverflow.com/a/25490531
*/
function getCookieValue(name: string): string | undefined {
const m = document.cookie.match('(^|[^;]+)\\s*' + name + '\\s*=\\s*([^;]+)');
return m ? m.pop() : undefined;
}

View File

@@ -7,6 +7,7 @@ import { createDecorator, ServiceIdentifier } from 'vs/platform/instantiation/co
import { IWindowConfiguration } from 'vs/platform/windows/common/windows';
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
import { IWorkbenchConstructionOptions } from 'vs/workbench/workbench.web.api';
import { URI } from 'vs/base/common/uri';
export const IWorkbenchEnvironmentService = createDecorator<IWorkbenchEnvironmentService>('environmentService');
@@ -16,5 +17,7 @@ export interface IWorkbenchEnvironmentService extends IEnvironmentService {
readonly configuration: IWindowConfiguration;
readonly logFile: URI;
readonly options?: IWorkbenchConstructionOptions;
}

View File

@@ -11,6 +11,7 @@ import { URI } from 'vs/base/common/uri';
import { Schemas } from 'vs/base/common/network';
import { toBackupWorkspaceResource } from 'vs/workbench/services/backup/common/backup';
import { ServiceIdentifier } from 'vs/platform/instantiation/common/instantiation';
import { join } from 'vs/base/common/path';
export class WorkbenchEnvironmentService extends EnvironmentService implements IWorkbenchEnvironmentService {
@@ -31,4 +32,7 @@ export class WorkbenchEnvironmentService extends EnvironmentService implements I
@memoize
get userRoamingDataHome(): URI { return this.appSettingsHome.with({ scheme: Schemas.userData }); }
@memoize
get logFile(): URI { return URI.file(join(this.logsPath, `renderer${this.configuration.windowId}.log`)); }
}

View File

@@ -86,7 +86,7 @@ export class ExtensionService extends AbstractExtensionService implements IExten
const result: ExtensionHostProcessManager[] = [];
const webExtensions = this.getExtensions().then(extensions => extensions.filter(ext => isWebExtension(ext, this._configService)));
const webHostProcessWorker = this._instantiationService.createInstance(WebWorkerExtensionHostStarter, true, webExtensions, URI.parse('empty:value')); //todo@joh
const webHostProcessWorker = this._instantiationService.createInstance(WebWorkerExtensionHostStarter, true, webExtensions, URI.file(this._environmentService.logsPath).with({ scheme: this._environmentService.logFile.scheme }));
const webHostProcessManager = this._instantiationService.createInstance(ExtensionHostProcessManager, false, webHostProcessWorker, null, initialActivationEvents);
result.push(webHostProcessManager);

View File

@@ -176,6 +176,7 @@ export class BrowserKeyboardMapperFactoryBase {
}
setActiveKeyMapping(keymap: IKeyboardMapping | null) {
let keymapUpdated = false;
let matchedKeyboardLayout = this.getMatchedKeymapInfo(keymap);
if (matchedKeyboardLayout) {
// let score = matchedKeyboardLayout.score;
@@ -209,18 +210,21 @@ export class BrowserKeyboardMapperFactoryBase {
if (!this._activeKeymapInfo) {
this._activeKeymapInfo = matchedKeyboardLayout.result;
keymapUpdated = true;
} else if (keymap) {
if (matchedKeyboardLayout.result.getScore(keymap) > this._activeKeymapInfo.getScore(keymap)) {
this._activeKeymapInfo = matchedKeyboardLayout.result;
keymapUpdated = true;
}
}
}
if (!this._activeKeymapInfo) {
this._activeKeymapInfo = this.getUSStandardLayout();
keymapUpdated = true;
}
if (!this._activeKeymapInfo) {
if (!this._activeKeymapInfo || !keymapUpdated) {
return;
}

View File

@@ -40,12 +40,12 @@ suite('keyboard layout loader', () => {
let commandService = instantiationService.stub(ICommandService, {});
let instance = new TestKeyboardMapperFactory(notitifcationService, storageService, commandService);
test.skip('load default US keyboard layout', () => {
test('load default US keyboard layout', () => {
assert.notEqual(instance.activeKeyboardLayout, null);
assert.equal(instance.activeKeyboardLayout!.isUSStandard, true);
});
test.skip('isKeyMappingActive', () => {
test('isKeyMappingActive', () => {
instance.setUSKeyboardLayout();
assert.equal(instance.isKeyMappingActive({
KeyA: {
value: 'a',

View File

@@ -0,0 +1,98 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { KeyValueLogProvider } from 'vs/workbench/services/log/common/keyValueLogProvider';
export const INDEXEDDB_LOG_SCHEME = 'vscode-logs-indexedbd';
export const INDEXEDDB_LOGS_DB = 'vscode-logs-db';
export const INDEXEDDB_LOGS_OBJECT_STORE = 'vscode-logs-store';
export class IndexedDBLogProvider extends KeyValueLogProvider {
private readonly database: Promise<IDBDatabase>;
constructor(
) {
super(INDEXEDDB_LOG_SCHEME);
this.database = this.openDatabase(1);
}
private openDatabase(version: number): Promise<IDBDatabase> {
return new Promise((c, e) => {
const request = window.indexedDB.open(INDEXEDDB_LOGS_DB, version);
request.onerror = (err) => e(request.error);
request.onsuccess = () => {
const db = request.result;
if (db.objectStoreNames.contains(INDEXEDDB_LOGS_OBJECT_STORE)) {
c(db);
}
};
request.onupgradeneeded = () => {
const db = request.result;
if (!db.objectStoreNames.contains(INDEXEDDB_LOGS_OBJECT_STORE)) {
db.createObjectStore(INDEXEDDB_LOGS_OBJECT_STORE);
}
c(db);
};
});
}
protected async getAllKeys(): Promise<string[]> {
return new Promise(async (c, e) => {
const db = await this.database;
const transaction = db.transaction([INDEXEDDB_LOGS_OBJECT_STORE]);
const objectStore = transaction.objectStore(INDEXEDDB_LOGS_OBJECT_STORE);
const request = objectStore.getAllKeys();
request.onerror = () => e(request.error);
request.onsuccess = () => c(<string[]>request.result);
});
}
protected hasKey(key: string): Promise<boolean> {
return new Promise<boolean>(async (c, e) => {
const db = await this.database;
const transaction = db.transaction([INDEXEDDB_LOGS_OBJECT_STORE]);
const objectStore = transaction.objectStore(INDEXEDDB_LOGS_OBJECT_STORE);
const request = objectStore.getKey(key);
request.onerror = () => e(request.error);
request.onsuccess = () => {
c(!!request.result);
};
});
}
protected getValue(key: string): Promise<string> {
return new Promise(async (c, e) => {
const db = await this.database;
const transaction = db.transaction([INDEXEDDB_LOGS_OBJECT_STORE]);
const objectStore = transaction.objectStore(INDEXEDDB_LOGS_OBJECT_STORE);
const request = objectStore.get(key);
request.onerror = () => e(request.error);
request.onsuccess = () => c(request.result || '');
});
}
protected setValue(key: string, value: string): Promise<void> {
return new Promise(async (c, e) => {
const db = await this.database;
const transaction = db.transaction([INDEXEDDB_LOGS_OBJECT_STORE], 'readwrite');
const objectStore = transaction.objectStore(INDEXEDDB_LOGS_OBJECT_STORE);
const request = objectStore.put(value, key);
request.onerror = () => e(request.error);
request.onsuccess = () => c();
});
}
protected deleteKey(key: string): Promise<void> {
return new Promise(async (c, e) => {
const db = await this.database;
const transaction = db.transaction([INDEXEDDB_LOGS_OBJECT_STORE], 'readwrite');
const objectStore = transaction.objectStore(INDEXEDDB_LOGS_OBJECT_STORE);
const request = objectStore.delete(key);
request.onerror = () => e(request.error);
request.onsuccess = () => c();
});
}
}

View File

@@ -0,0 +1,40 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { KeyValueLogProvider } from 'vs/workbench/services/log/common/keyValueLogProvider';
import { keys } from 'vs/base/common/map';
export const INMEMORY_LOG_SCHEME = 'vscode-logs-inmemory';
export class InMemoryLogProvider extends KeyValueLogProvider {
private readonly logs: Map<string, string> = new Map<string, string>();
constructor(
) {
super(INMEMORY_LOG_SCHEME);
}
protected async getAllKeys(): Promise<string[]> {
return keys(this.logs);
}
protected async hasKey(key: string): Promise<boolean> {
return this.logs.has(key);
}
protected async getValue(key: string): Promise<string> {
return this.logs.get(key) || '';
}
protected async setValue(key: string, value: string): Promise<void> {
this.logs.set(key, value);
}
protected async deleteKey(key: string): Promise<void> {
this.logs.delete(key);
}
}

View File

@@ -0,0 +1,129 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the Source EULA. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
import { URI } from 'vs/base/common/uri';
import { IFileSystemProviderWithFileReadWriteCapability, FileSystemProviderCapabilities, IFileChange, IWatchOptions, IStat, FileOverwriteOptions, FileType, FileDeleteOptions, FileWriteOptions, FileChangeType, FileSystemProviderErrorCode } from 'vs/platform/files/common/files';
import { Disposable, IDisposable } from 'vs/base/common/lifecycle';
import { Event, Emitter } from 'vs/base/common/event';
import { VSBuffer } from 'vs/base/common/buffer';
import { FileSystemError } from 'vs/workbench/api/common/extHostTypes';
import { isEqualOrParent, joinPath, relativePath } from 'vs/base/common/resources';
import { values } from 'vs/base/common/map';
export abstract class KeyValueLogProvider extends Disposable implements IFileSystemProviderWithFileReadWriteCapability {
readonly capabilities: FileSystemProviderCapabilities = FileSystemProviderCapabilities.FileReadWrite;
readonly onDidChangeCapabilities: Event<void> = Event.None;
private readonly _onDidChangeFile: Emitter<IFileChange[]> = this._register(new Emitter<IFileChange[]>());
readonly onDidChangeFile: Event<IFileChange[]> = this._onDidChangeFile.event;
private readonly versions: Map<string, number> = new Map<string, number>();
constructor(private readonly scheme: string) {
super();
}
watch(resource: URI, opts: IWatchOptions): IDisposable {
return Disposable.None;
}
async mkdir(resource: URI): Promise<void> {
}
async stat(resource: URI): Promise<IStat> {
try {
const content = await this.readFile(resource);
return {
type: FileType.File,
ctime: 0,
mtime: this.versions.get(resource.toString()) || 0,
size: content.byteLength
};
} catch (e) {
}
const files = await this.readdir(resource);
if (files.length) {
return {
type: FileType.Directory,
ctime: 0,
mtime: 0,
size: 0
};
}
return Promise.reject(new FileSystemError(resource, FileSystemProviderErrorCode.FileNotFound));
}
async readdir(resource: URI): Promise<[string, FileType][]> {
const hasKey = await this.hasKey(resource.path);
if (hasKey) {
return Promise.reject(new FileSystemError(resource, FileSystemProviderErrorCode.FileNotADirectory));
}
const keys = await this.getAllKeys();
const files: Map<string, [string, FileType]> = new Map<string, [string, FileType]>();
for (const key of keys) {
const keyResource = this.toResource(key);
if (isEqualOrParent(keyResource, resource, false)) {
const path = relativePath(resource, keyResource, false);
if (path) {
const keySegments = path.split('/');
files.set(keySegments[0], [keySegments[0], keySegments.length === 1 ? FileType.File : FileType.Directory]);
}
}
}
return values(files);
}
async readFile(resource: URI): Promise<Uint8Array> {
const hasKey = await this.hasKey(resource.path);
if (!hasKey) {
return Promise.reject(new FileSystemError(resource, FileSystemProviderErrorCode.FileNotFound));
}
const value = await this.getValue(resource.path);
return VSBuffer.fromString(value).buffer;
}
async writeFile(resource: URI, content: Uint8Array, opts: FileWriteOptions): Promise<void> {
const hasKey = await this.hasKey(resource.path);
if (!hasKey) {
const files = await this.readdir(resource);
if (files.length) {
return Promise.reject(new FileSystemError(resource, FileSystemProviderErrorCode.FileIsADirectory));
}
}
await this.setValue(resource.path, VSBuffer.wrap(content).toString());
this.versions.set(resource.toString(), (this.versions.get(resource.toString()) || 0) + 1);
this._onDidChangeFile.fire([{ resource, type: FileChangeType.UPDATED }]);
}
async delete(resource: URI, opts: FileDeleteOptions): Promise<void> {
const hasKey = await this.hasKey(resource.path);
if (hasKey) {
await this.deleteKey(resource.path);
this.versions.delete(resource.path);
this._onDidChangeFile.fire([{ resource, type: FileChangeType.DELETED }]);
return;
}
if (opts.recursive) {
const files = await this.readdir(resource);
await Promise.all(files.map(([key]) => this.delete(joinPath(resource, key), opts)));
}
}
rename(from: URI, to: URI, opts: FileOverwriteOptions): Promise<void> {
return Promise.reject(new Error('Not Supported'));
}
private toResource(key: string): URI {
return URI.file(key).with({ scheme: this.scheme });
}
protected abstract getAllKeys(): Promise<string[]>;
protected abstract hasKey(key: string): Promise<boolean>;
protected abstract getValue(key: string): Promise<string>;
protected abstract setValue(key: string, value: string): Promise<void>;
protected abstract deleteKey(key: string): Promise<void>;
}

View File

@@ -47,7 +47,7 @@ suite('FileUserDataProvider', () => {
userDataResource = URI.file(userDataPath).with({ scheme: Schemas.userData });
await Promise.all([pfs.mkdirp(userDataPath), pfs.mkdirp(backupsPath)]);
const environmentService = new BrowserWorkbenchEnvironmentService('workspaceId', { remoteAuthority: 'remote' });
const environmentService = new BrowserWorkbenchEnvironmentService({ remoteAuthority: 'remote', workspaceId: 'workspaceId', logsPath: URI.file('logFile') });
environmentService.userRoamingDataHome = userDataResource;
const userDataFileSystemProvider = new FileUserDataProvider(URI.file(userDataPath), URI.file(backupsPath), diskFileSystemProvider, environmentService);
@@ -321,7 +321,7 @@ suite('FileUserDataProvider - Watching', () => {
localUserDataResource = URI.file(userDataPath);
userDataResource = localUserDataResource.with({ scheme: Schemas.userData });
const environmentService = new BrowserWorkbenchEnvironmentService('workspaceId', { remoteAuthority: 'remote' });
const environmentService = new BrowserWorkbenchEnvironmentService({ remoteAuthority: 'remote', workspaceId: 'workspaceId', logsPath: URI.file('logFile') });
environmentService.userRoamingDataHome = userDataResource;
const userDataFileSystemProvider = new FileUserDataProvider(localUserDataResource, localBackupsResource, new TestFileSystemProvider(fileEventEmitter.event), environmentService);